X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a393f450dc992c9b37300b4a6255bf4e1c97ce69..f30f25b559728c48e767774a34a72bde28bc85f7:/src/univ/menu.cpp?ds=sidebyside diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index ba4e56b519..e8916af3a8 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: univ/menu.cpp +// Name: src/univ/menu.cpp // Purpose: wxMenuItem, wxMenu and wxMenuBar implementation // Author: Vadim Zeitlin // Modified by: @@ -17,17 +17,14 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "univmenuitem.h" - #pragma implementation "univmenu.h" -#endif - #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif +#if wxUSE_MENUS + #ifndef WX_PRECOMP #include "wx/dynarray.h" #include "wx/control.h" // for FindAccelIndex() @@ -37,8 +34,6 @@ #include "wx/log.h" #endif // WX_PRECOMP -#if wxUSE_MENUS - #include "wx/popupwin.h" #include "wx/evtloop.h" #include "wx/dcclient.h" @@ -132,12 +127,16 @@ public: // override the base class version to dismiss any open submenus virtual void Dismiss(); - // notify the menu when the window disappears from screen - virtual void OnDismiss(); - // called when a submenu is dismissed void OnSubmenuDismiss(bool dismissParent); + // the default wxMSW wxPopupTransientWindow::OnIdle disables the capture + // when the cursor is inside the popup, which dsables the menu tracking + // so override it to do nothing +#ifdef __WXMSW__ + void OnIdle(wxIdleEvent& WXUNUSED(event)) { } +#endif + // get the currently selected item (may be NULL) wxMenuItem *GetCurrentItem() const { @@ -162,6 +161,8 @@ public: // don't dismiss the popup window if the parent menu was clicked virtual bool ProcessLeftDown(wxMouseEvent& event); + virtual bool SetCurrent(bool doit = true) { return wxPopupTransientWindow::SetCurrent(doit); }; + protected: // how did we perform this operation? enum InputMethod @@ -170,6 +171,9 @@ protected: WithMouse }; + // notify the menu when the window disappears from screen + virtual void OnDismiss(); + // draw the menu inside this window virtual void DoDraw(wxControlRenderer *renderer); @@ -184,7 +188,6 @@ protected: // set the current node and item withotu refreshing anything void SetCurrent(wxMenuItemList::compatibility_iterator node); - virtual bool SetCurrent(bool doit = true){return wxPopupTransientWindow::SetCurrent(doit);}; // change the current item refreshing the old and new items void ChangeCurrent(wxMenuItemList::compatibility_iterator node); @@ -282,6 +285,9 @@ BEGIN_EVENT_TABLE(wxPopupMenuWindow, wxPopupTransientWindow) EVT_LEFT_UP(wxPopupMenuWindow::OnLeftUp) EVT_MOTION(wxPopupMenuWindow::OnMouseMove) EVT_LEAVE_WINDOW(wxPopupMenuWindow::OnMouseLeave) +#ifdef __WXMSW__ + EVT_IDLE(wxPopupMenuWindow::OnIdle) +#endif END_EVENT_TABLE() BEGIN_EVENT_TABLE(wxMenuBar, wxMenuBarBase) @@ -428,6 +434,11 @@ void wxPopupMenuWindow::Popup(wxWindow *focus) wxPopupTransientWindow::Popup(focus); + // the base class no-longer captures the mouse automatically when Popup + // is called, so do it here to allow the menu tracking to work + if ( !HasCapture() ) + CaptureMouse(); + #ifdef __WXMSW__ // ensure that this window is really on top of everything: without using // SetWindowPos() it can be covered by its parent menu which is not @@ -467,6 +478,8 @@ void wxPopupMenuWindow::Dismiss() } wxPopupTransientWindow::Dismiss(); + + ResetCurrent(); } void wxPopupMenuWindow::OnDismiss() @@ -476,19 +489,13 @@ void wxPopupMenuWindow::OnDismiss() HandleDismiss(true); } -void wxPopupMenuWindow::OnSubmenuDismiss(bool dismissParent) +void wxPopupMenuWindow::OnSubmenuDismiss(bool WXUNUSED(dismissParent)) { m_hasOpenSubMenu = false; - - // we are closing whole menu so remove current highlight - if ( dismissParent ) - ResetCurrent(); } void wxPopupMenuWindow::HandleDismiss(bool dismissParent) { - ResetCurrent(); - m_menu->OnDismiss(dismissParent); } @@ -860,7 +867,13 @@ void wxPopupMenuWindow::OnMouseLeave(wxMouseEvent& event) void wxPopupMenuWindow::OnKeyDown(wxKeyEvent& event) { - if ( !ProcessKeyDown(event.GetKeyCode()) ) + wxMenuBar *menubar = m_menu->GetMenuBar(); + + if ( menubar ) + { + menubar->ProcessEvent(event); + } + else if ( !ProcessKeyDown(event.GetKeyCode()) ) { event.Skip(); } @@ -2146,9 +2159,6 @@ bool wxMenuBar::ProcessMouseEvent(const wxPoint& pt) return false; } - // FIXME: temporary workaround for crash, to be fixed - // in a later version. -#if 0 // select the new active item DoSelectMenu(currentNew); @@ -2159,7 +2169,6 @@ bool wxMenuBar::ProcessMouseEvent(const wxPoint& pt) // open the new menu if the old one we closed had been opened PopupCurrentMenu(false /* don't select first item - as Windows does */); } -#endif return true; } @@ -2467,11 +2476,8 @@ void wxMenuBar::OnDismissMenu(bool dismissMenuBar) void wxMenuBar::OnDismiss() { - if ( GetCapture() ) - { + if ( ReleaseMouseCapture() ) wxLogTrace(_T("mousecapture"), _T("Releasing mouse from wxMenuBar::OnDismiss")); - GetCapture()->ReleaseMouse(); - } if ( m_current != -1 ) { @@ -2484,6 +2490,42 @@ void wxMenuBar::OnDismiss() GiveAwayFocus(); } +bool wxMenuBar::ReleaseMouseCapture() +{ +#ifdef __WXX11__ + // With wxX11, when a menu is closed by clicking away from it, a control + // under the click will still get an event, even though the menu has the + // capture (bug?). So that control may already have taken the capture by + // this point, preventing us from releasing the menu's capture. So to work + // around this, we release both captures, then put back the control's + // capture. + wxWindow *capture = GetCapture(); + if ( capture ) + { + capture->ReleaseMouse(); + + if ( capture == this ) + return true; + + bool had = HasCapture(); + + if ( had ) + ReleaseMouse(); + + capture->CaptureMouse(); + + return had; + } +#else + if ( HasCapture() ) + { + ReleaseMouse(); + return true; + } +#endif + return false; +} + void wxMenuBar::GiveAwayFocus() { GetFrame()->SetFocus(); @@ -2566,4 +2608,3 @@ void wxWindow::DismissPopupMenu() } #endif // wxUSE_MENUS -