[haiku-commits] r37261 - in haiku/trunk: headers/os/interface src/kits/interface

  • From: stefano.ceccherini@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 26 Jun 2010 14:29:17 +0200 (CEST)

Author: jackburton
Date: 2010-06-26 14:29:17 +0200 (Sat, 26 Jun 2010)
New Revision: 37261
Changeset: http://dev.haiku-os.org/changeset/37261/haiku
Ticket: http://dev.haiku-os.org/ticket/4930

Modified:
   haiku/trunk/headers/os/interface/Menu.h
   haiku/trunk/src/kits/interface/Menu.cpp
Log:
Applied patch by Ziusudra in ticket #4930 to avoid a deadlock when 
navigating the menus via keyboard.
I also factored some code into functions, in particular the code to
add the dynamic items. Also keep track if the dynamic items have been added
or not (using a new boolean class member).
I tested for regressions but couldn't find any.



Modified: haiku/trunk/headers/os/interface/Menu.h
===================================================================
--- haiku/trunk/headers/os/interface/Menu.h     2010-06-26 09:59:36 UTC (rev 
37260)
+++ haiku/trunk/headers/os/interface/Menu.h     2010-06-26 12:29:17 UTC (rev 
37261)
@@ -183,7 +183,8 @@
                        BMenu&                          operator=(const BMenu& 
other);
 
                        void                            _InitData(BMessage* 
archive);
-                       bool                            _Show(bool 
selectFirstItem = false);
+                       bool                            _Show(bool 
selectFirstItem = false,
+                                                                       bool 
keyDown = false);
                        void                            _Hide();
                        BMenuItem*                      _Track(int* action, 
long start = -1);
 
@@ -235,18 +236,22 @@
                        void                            _Uninstall();
                        void                            _SelectItem(BMenuItem* 
item,
                                                                        bool 
showSubmenu = true,
-                                                                       bool 
selectFirstItem = false);
+                                                                       bool 
selectFirstItem = false,
+                                                                       bool 
keyDown = false);
                        bool                            
_SelectNextItem(BMenuItem* item, bool forward);
                        BMenuItem*                      _NextItem(BMenuItem* 
item, bool forward) const;
                        void                            _SetIgnoreHidden(bool 
on);
                        void                            _SetStickyMode(bool on);
                        bool                            _IsStickyMode() const;
+                       void                            
_GetIsAltCommandKey(bool &value) const;
                        void                            _CalcTriggers();
                        bool                            _ChooseTrigger(const 
char* title, int32& index,
                                                                        uint32& 
trigger,
                                                                        
BPrivate::TriggerList& triggers);
                        void                            
_UpdateWindowViewSize(const bool &updatePosition);
-                       bool                            _OkToProceed(BMenuItem* 
item);
+                       bool                            _AddDynamicItems();
+                       bool                            _OkToProceed(BMenuItem* 
item,
+                                                                       bool 
keyDown = false);
 
                        bool                            
_CustomTrackingWantsToQuit();
 
@@ -277,7 +282,10 @@
 
                        LayoutData*                     fLayoutData;
 
-                       int32                           _reserved;
+                       bool                            fDynamicItemsAdded;
+                       bool                            _reserved1;
+                       bool                            _reserved2;
+                       bool                            _reserved3;
 
                        char                            fTrigger;
                        bool                            fResizeToFit;

Modified: haiku/trunk/src/kits/interface/Menu.cpp
===================================================================
--- haiku/trunk/src/kits/interface/Menu.cpp     2010-06-26 09:59:36 UTC (rev 
37260)
+++ haiku/trunk/src/kits/interface/Menu.cpp     2010-06-26 12:29:17 UTC (rev 
37261)
@@ -210,6 +210,7 @@
        fMaxContentWidth(0.0f),
        fInitMatrixSize(NULL),
        fExtraMenuData(NULL),
+       fDynamicItemsAdded(false),
        fTrigger(0),
        fResizeToFit(true),
        fUseCachedMenuLayout(false),
@@ -244,6 +245,7 @@
        fMaxContentWidth(0.0f),
        fInitMatrixSize(NULL),
        fExtraMenuData(NULL),
+       fDynamicItemsAdded(false),
        fTrigger(0),
        fResizeToFit(true),
        fUseCachedMenuLayout(false),
@@ -279,6 +281,7 @@
        fMaxContentWidth(0.0f),
        fInitMatrixSize(NULL),
        fExtraMenuData(NULL),
+       fDynamicItemsAdded(false),
        fTrigger(0),
        fResizeToFit(true),
        fUseCachedMenuLayout(false),
@@ -367,35 +370,11 @@
 {
        BView::AttachedToWindow();
 
-       // TODO: Move into init_interface_kit().
-       // Currently we can't do that, as get_key_map() blocks forever
-       // when called on input_server initialization, since it tries
-       // to send a synchronous message to itself (input_server is
-       // a BApplication)
+       _GetIsAltCommandKey(sAltAsCommandKey);
+               
+       bool attachAborted = _AddDynamicItems();
 
-       BMenu::sAltAsCommandKey = true;
-       key_map* keys = NULL;
-       char* chars = NULL;
-       get_key_map(&keys, &chars);
-       if (keys == NULL || keys->left_command_key != 0x5d
-               || keys->left_control_key != 0x5c)
-               BMenu::sAltAsCommandKey = false;
-       free(chars);
-       free(keys);
-
-       BMenuItem* superItem = Superitem();
-       BMenu* superMenu = Supermenu();
-       if (AddDynamicItem(B_INITIAL_ADD)) {
-               do {
-                       if (superMenu != NULL && 
!superMenu->_OkToProceed(superItem)) {
-                               AddDynamicItem(B_ABORT);
-                               fAttachAborted = true;
-                               break;
-                       }
-               } while (AddDynamicItem(B_PROCESSING));
-       }
-
-       if (!fAttachAborted) {
+       if (!attachAborted) {
                _CacheFontInfo();
                _LayoutItems(0);
                _UpdateWindowViewSize(false);
@@ -515,7 +494,11 @@
                                _SelectNextItem(fSelected, true);
                        else {
                                if (fSelected && fSelected->Submenu()) {
-                                       _SelectItem(fSelected, true, true);
+                                       
fSelected->Submenu()->_SetStickyMode(true); 
+                                               // fix me: this shouldn't be 
needed but dynamic menus 
+                                               // aren't getting it set 
correctly when keyboard 
+                                               // navigating, which aborts the 
attach 
+                                       _SelectItem(fSelected, true, true, 
true);
                                } else if 
(dynamic_cast<BMenuBar*>(Supermenu())) {
                                        // if we have no submenu and we're an
                                        // item in the top menu below the 
menubar,
@@ -1261,6 +1244,7 @@
        fMaxContentWidth(0.0f),
        fInitMatrixSize(NULL),
        fExtraMenuData(NULL),
+       fDynamicItemsAdded(false),
        fTrigger(0),
        fResizeToFit(resizeToFit),
        fUseCachedMenuLayout(false),
@@ -1462,7 +1446,7 @@
 
 
 bool
-BMenu::_Show(bool selectFirstItem)
+BMenu::_Show(bool selectFirstItem, bool keyDown)
 {
        // See if the supermenu has a cached menuwindow,
        // and use that one if possible.
@@ -1486,7 +1470,19 @@
                return false;
 
        if (window->Lock()) {
+               bool attachAborted = false;
+               if (keyDown)
+                       attachAborted = _AddDynamicItems();     
+               
+               if (attachAborted) {
+                       if (ourWindow)
+                               window->Quit();
+                       else
+                               window->Unlock();
+                       return false;
+               }
                fAttachAborted = false;
+               
                window->AttachMenu(this);
 
                if (ItemAt(0) != NULL) {
@@ -2499,7 +2495,8 @@
 
 
 void
-BMenu::_SelectItem(BMenuItem* menuItem, bool showSubmenu, bool selectFirstItem)
+BMenu::_SelectItem(BMenuItem* menuItem, bool showSubmenu,
+       bool selectFirstItem, bool keyDown)
 {
        // Avoid deselecting and then reselecting the same item
        // which would cause flickering
@@ -2519,7 +2516,7 @@
        if (fSelected != NULL && showSubmenu) {
                BMenu* subMenu = fSelected->Submenu();
                if (subMenu != NULL && subMenu->Window() == NULL) {
-                       if (!subMenu->_Show(selectFirstItem)) {
+                       if (!subMenu->_Show(selectFirstItem, keyDown)) {
                                // something went wrong, deselect the item
                                fSelected->Select(false);
                                fSelected = NULL;
@@ -2620,6 +2617,29 @@
 
 
 void
+BMenu::_GetIsAltCommandKey(bool &value) const
+{
+       // TODO: Move into init_interface_kit().
+       // Currently we can't do that, as get_key_map() blocks forever
+       // when called on input_server initialization, since it tries
+       // to send a synchronous message to itself (input_server is
+       // a BApplication)
+
+       bool altAsCommand = true;
+       key_map* keys = NULL;
+       char* chars = NULL;
+       get_key_map(&keys, &chars);
+       if (keys == NULL || keys->left_command_key != 0x5d
+               || keys->left_control_key != 0x5c)
+               altAsCommand = false;
+       free(chars);
+       free(keys);
+
+       value = altAsCommand;
+}
+
+
+void
 BMenu::_CalcTriggers()
 {
        BPrivate::TriggerList triggerList;
@@ -2729,8 +2749,35 @@
 
 
 bool
-BMenu::_OkToProceed(BMenuItem* item)
+BMenu::_AddDynamicItems()
 {
+       if (fDynamicItemsAdded)
+               return false;
+               
+       bool attachAborted = false;
+       BMenuItem* superItem = Superitem();
+       BMenu* superMenu = Supermenu();
+       if (AddDynamicItem(B_INITIAL_ADD)) {
+               do {
+                       if (superMenu != NULL
+                               && !superMenu->_OkToProceed(superItem)) {
+                               AddDynamicItem(B_ABORT);
+                               attachAborted = true;
+                               break;
+                       }
+               } while (AddDynamicItem(B_PROCESSING));
+       }
+       
+       if (!attachAborted)
+               fDynamicItemsAdded = true;
+       
+       return attachAborted;
+}
+
+
+bool
+BMenu::_OkToProceed(BMenuItem* item, bool keyDown)
+{
        BPoint where;
        ulong buttons;
        GetMouse(&where, &buttons, false);
@@ -2743,7 +2790,8 @@
        // Deskbar, though.
        if ((buttons != 0 && stickyMode)
                || ((dynamic_cast<BMenuBar*>(this) == NULL
-                       && (buttons == 0 && !stickyMode)) || 
_HitTestItems(where) != item))
+                       && (buttons == 0 && !stickyMode))
+               || ((_HitTestItems(where) != item) && !keyDown)))
                return false;
 
        return true;


Other related posts:

  • » [haiku-commits] r37261 - in haiku/trunk: headers/os/interface src/kits/interface - stefano . ceccherini