From 05875a76e970a7f786fff5686b5aed1745725403 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 26 Jun 2021 17:06:24 +0300 Subject: [PATCH 1/4] Fix handling mouse capture --- include/wx/univ/menu.h | 1 + src/univ/menu.cpp | 43 ++++++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/wx/univ/menu.h b/include/wx/univ/menu.h index 27ba99ad5b..169067915a 100644 --- a/include/wx/univ/menu.h +++ b/include/wx/univ/menu.h @@ -190,6 +190,7 @@ protected: void OnMouseMove(wxMouseEvent& event); void OnKeyDown(wxKeyEvent& event); void OnKillFocus(wxFocusEvent& event); + void OnCaptureLost(wxMouseCaptureLostEvent& event); // process the mouse move event, return true if we did, false to continue // processing as usual diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index 4dcce95c49..c8c6321915 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -180,10 +180,11 @@ protected: virtual void DoDraw(wxControlRenderer *renderer); // event handlers - void OnLeftUp(wxMouseEvent& event); + void OnLeftDown(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); void OnMouseLeave(wxMouseEvent& event); void OnKeyDown(wxKeyEvent& event); + void OnCaptureLost(wxMouseCaptureLostEvent& event); // reset the current item and node void ResetCurrent(); @@ -280,9 +281,10 @@ private: wxBEGIN_EVENT_TABLE(wxPopupMenuWindow, wxPopupTransientWindow) EVT_KEY_DOWN(wxPopupMenuWindow::OnKeyDown) - EVT_LEFT_UP(wxPopupMenuWindow::OnLeftUp) + EVT_LEFT_DOWN(wxPopupMenuWindow::OnLeftDown) EVT_MOTION(wxPopupMenuWindow::OnMouseMove) EVT_LEAVE_WINDOW(wxPopupMenuWindow::OnMouseLeave) + EVT_MOUSE_CAPTURE_LOST(wxPopupMenuWindow::OnCaptureLost) #ifdef __WXMSW__ EVT_IDLE(wxPopupMenuWindow::OnIdle) #endif @@ -290,11 +292,10 @@ wxEND_EVENT_TABLE() wxBEGIN_EVENT_TABLE(wxMenuBar, wxMenuBarBase) EVT_KILL_FOCUS(wxMenuBar::OnKillFocus) - EVT_KEY_DOWN(wxMenuBar::OnKeyDown) - EVT_LEFT_DOWN(wxMenuBar::OnLeftDown) EVT_MOTION(wxMenuBar::OnMouseMove) + EVT_MOUSE_CAPTURE_LOST(wxMenuBar::OnCaptureLost) wxEND_EVENT_TABLE() // ============================================================================ @@ -471,6 +472,9 @@ void wxPopupMenuWindow::Dismiss() OnSubmenuDismiss( false ); } + if ( HasCapture() ) + ReleaseMouse(); + wxPopupTransientWindow::Dismiss(); ResetCurrent(); @@ -717,13 +721,21 @@ bool wxPopupMenuWindow::ProcessLeftDown(wxMouseEvent& event) return false; } -void wxPopupMenuWindow::OnLeftUp(wxMouseEvent& event) +void wxPopupMenuWindow::OnLeftDown(wxMouseEvent& event) { wxMenuItemIter node = GetMenuItemFromPoint(event.GetPosition()); if ( node ) { ActivateItem(node->GetData(), WithMouse); } + else + { + wxMenuBar* menubar = m_menu->GetMenuBar(); + if ( menubar && !ProcessLeftDown(event) ) + { + menubar->ProcessEvent(event); + } + } } void wxPopupMenuWindow::OnMouseMove(wxMouseEvent& event) @@ -1041,6 +1053,11 @@ bool wxPopupMenuWindow::ProcessKeyDown(int key) return processed; } +void wxPopupMenuWindow::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) +{ + DismissAndNotify(); +} + // ---------------------------------------------------------------------------- // wxMenu // ---------------------------------------------------------------------------- @@ -2104,8 +2121,10 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) { if ( HasCapture() ) { - OnDismiss(); - + if ( IsShowingMenu() ) + { + DismissMenu(); + } event.Skip(); } else // we didn't have mouse capture, capture it now @@ -2113,9 +2132,8 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) m_current = GetMenuFromPoint(event.GetPosition()); if ( m_current == -1 ) { - // unfortunately, we can't prevent wxMSW from giving us the focus, - // so we can only give it back - GiveAwayFocus(); + DismissMenu(); // event outside menubar - dismiss + ReleaseMouseCapture(); // we could get capture back from popup window so release it } else // on item { @@ -2314,6 +2332,11 @@ void wxMenuBar::OnKeyDown(wxKeyEvent& event) } } +void wxMenuBar::OnCaptureLost(wxMouseCaptureLostEvent& event) +{ + DismissMenu(); +} + // ---------------------------------------------------------------------------- // wxMenuBar accel handling // ---------------------------------------------------------------------------- From 2209ec29f72df79fdb8466ba5c3e3b65a412d79d Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sun, 27 Jun 2021 21:48:22 +0300 Subject: [PATCH 2/4] Add handling LEFT_UP --- include/wx/univ/menu.h | 1 + src/univ/menu.cpp | 55 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/include/wx/univ/menu.h b/include/wx/univ/menu.h index 169067915a..72becf3b06 100644 --- a/include/wx/univ/menu.h +++ b/include/wx/univ/menu.h @@ -187,6 +187,7 @@ protected: // event handlers void OnLeftDown(wxMouseEvent& event); + void OnLeftUp(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); void OnKeyDown(wxKeyEvent& event); void OnKillFocus(wxFocusEvent& event); diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index c8c6321915..ac8769fe61 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -181,6 +181,7 @@ protected: // event handlers void OnLeftDown(wxMouseEvent& event); + void OnLeftUp(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); void OnMouseLeave(wxMouseEvent& event); void OnKeyDown(wxKeyEvent& event); @@ -282,6 +283,7 @@ wxBEGIN_EVENT_TABLE(wxPopupMenuWindow, wxPopupTransientWindow) EVT_KEY_DOWN(wxPopupMenuWindow::OnKeyDown) EVT_LEFT_DOWN(wxPopupMenuWindow::OnLeftDown) + EVT_LEFT_UP(wxPopupMenuWindow::OnLeftUp) EVT_MOTION(wxPopupMenuWindow::OnMouseMove) EVT_LEAVE_WINDOW(wxPopupMenuWindow::OnMouseLeave) EVT_MOUSE_CAPTURE_LOST(wxPopupMenuWindow::OnCaptureLost) @@ -294,6 +296,7 @@ wxBEGIN_EVENT_TABLE(wxMenuBar, wxMenuBarBase) EVT_KILL_FOCUS(wxMenuBar::OnKillFocus) EVT_KEY_DOWN(wxMenuBar::OnKeyDown) EVT_LEFT_DOWN(wxMenuBar::OnLeftDown) + EVT_LEFT_UP(wxMenuBar::OnLeftUp) EVT_MOTION(wxMenuBar::OnMouseMove) EVT_MOUSE_CAPTURE_LOST(wxMenuBar::OnCaptureLost) wxEND_EVENT_TABLE() @@ -356,7 +359,7 @@ void wxPopupMenuWindow::ChangeCurrent(wxMenuItemIter node) wxCHECK_RET( item, wxT("no current item?") ); // if it was the currently opened menu, close it - if ( item->IsSubMenu() && item->GetSubMenu()->IsShown() ) + if ( node && item->IsSubMenu() && item->GetSubMenu()->IsShown() ) { item->GetSubMenu()->Dismiss(); OnSubmenuDismiss( false ); @@ -722,6 +725,18 @@ bool wxPopupMenuWindow::ProcessLeftDown(wxMouseEvent& event) } void wxPopupMenuWindow::OnLeftDown(wxMouseEvent& event) +{ + wxMenuBar* menubar = m_menu->GetMenuBar(); + if ( menubar && !GetMenuItemFromPoint(event.GetPosition()) && !ProcessLeftDown(event) ) + { + wxPoint pos = event.GetPosition(); + wxPoint posScreen = ClientToScreen(pos); + event.SetPosition(menubar->ScreenToClient(posScreen)); + menubar->ProcessEvent(event); + } +} + +void wxPopupMenuWindow::OnLeftUp(wxMouseEvent& event) { wxMenuItemIter node = GetMenuItemFromPoint(event.GetPosition()); if ( node ) @@ -733,6 +748,9 @@ void wxPopupMenuWindow::OnLeftDown(wxMouseEvent& event) wxMenuBar* menubar = m_menu->GetMenuBar(); if ( menubar && !ProcessLeftDown(event) ) { + wxPoint pos = event.GetPosition(); + wxPoint posScreen = ClientToScreen(pos); + event.SetPosition(menubar->ScreenToClient(posScreen)); menubar->ProcessEvent(event); } } @@ -2129,14 +2147,25 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) } else // we didn't have mouse capture, capture it now { - m_current = GetMenuFromPoint(event.GetPosition()); - if ( m_current == -1 ) + int item = GetMenuFromPoint(event.GetPosition()); + if ( item == -1 ) { - DismissMenu(); // event outside menubar - dismiss - ReleaseMouseCapture(); // we could get capture back from popup window so release it + if ( IsShowingMenu() ) + { + DismissMenu(); // event outside menubar - dismiss + ReleaseMouseCapture(); // we could get capture back from popup window so release it + } + } + else if ( item == m_current && IsShowingMenu() ) + { + // double-click + DismissMenu(); + ReleaseMouseCapture(); } else // on item { + m_current = item; + wxLogTrace(wxT("mousecapture"), wxT("Capturing mouse from wxMenuBar::OnLeftDown")); CaptureMouse(); @@ -2149,6 +2178,15 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) } } +void wxMenuBar::OnLeftUp(wxMouseEvent& event) +{ + if ( !HasCapture() && IsShowingMenu() && GetMenuFromPoint(event.GetPosition()) == -1 ) + { + DismissMenu(); + ReleaseMouseCapture(); + } +} + void wxMenuBar::OnMouseMove(wxMouseEvent& event) { if ( HasCapture() ) @@ -2332,9 +2370,12 @@ void wxMenuBar::OnKeyDown(wxKeyEvent& event) } } -void wxMenuBar::OnCaptureLost(wxMouseCaptureLostEvent& event) +void wxMenuBar::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) { - DismissMenu(); + if ( IsShowingMenu() ) + { + DismissMenu(); + } } // ---------------------------------------------------------------------------- From ef90e73e5a7d9100e18ab093422d87bf0d8b79b5 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Mon, 28 Jun 2021 10:16:57 +0300 Subject: [PATCH 3/4] Properly refresh item after menu dismissing --- src/univ/menu.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index ac8769fe61..223e4ca203 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -2139,10 +2139,7 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) { if ( HasCapture() ) { - if ( IsShowingMenu() ) - { - DismissMenu(); - } + OnDismiss(); event.Skip(); } else // we didn't have mouse capture, capture it now @@ -2154,6 +2151,8 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) { DismissMenu(); // event outside menubar - dismiss ReleaseMouseCapture(); // we could get capture back from popup window so release it + RefreshItem((size_t)m_current); + m_current = -1; } } else if ( item == m_current && IsShowingMenu() ) @@ -2161,6 +2160,8 @@ void wxMenuBar::OnLeftDown(wxMouseEvent& event) // double-click DismissMenu(); ReleaseMouseCapture(); + RefreshItem((size_t)m_current); + m_current = -1; } else // on item { @@ -2184,6 +2185,8 @@ void wxMenuBar::OnLeftUp(wxMouseEvent& event) { DismissMenu(); ReleaseMouseCapture(); + RefreshItem((size_t)m_current); + m_current = -1; } } From 2f71702e4e0797a721e5a8a8248ace3e3e3020b5 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sun, 4 Jul 2021 18:33:58 +0300 Subject: [PATCH 4/4] Don't refresh unshown menu item --- src/univ/menu.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index 223e4ca203..77a03de14e 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -369,7 +369,13 @@ void wxPopupMenuWindow::ChangeCurrent(wxMenuItemIter node) } if ( m_nodeCurrent ) - RefreshItem(m_nodeCurrent->GetData()); + { + wxMenuItem *item = m_nodeCurrent->GetData(); + if ( item && item->GetMenu()->IsShown() ) + { + RefreshItem(m_nodeCurrent->GetData()); + } + } } }