include/svtools/scrolladaptor.hxx | 2 - include/vcl/customweld.hxx | 6 ++-- include/vcl/weld.hxx | 6 ++-- sd/source/ui/animations/CustomAnimationPane.cxx | 2 - vcl/inc/qt5/QtInstanceWidget.hxx | 6 ++-- vcl/inc/salvtables.hxx | 6 ++-- vcl/qt5/QtInstanceWidget.cxx | 25 ++++++++++++++---- vcl/source/app/salvtables.cxx | 6 ++-- vcl/unx/gtk3/gtkinst.cxx | 33 +++++++++++++----------- 9 files changed, 55 insertions(+), 37 deletions(-)
New commits: commit 176bc1783f4fd162114a47a692d9eee6c4cf96c5 Author: Michael Weghorn <[email protected]> AuthorDate: Tue May 13 12:37:09 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Wed May 14 08:38:37 2025 +0200 tdf#130857 qt weld: Implement mouse grab API Change-Id: I224b29b71852064fd40f455cbf52f06e89521cb7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185255 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/qt5/QtInstanceWidget.cxx b/vcl/qt5/QtInstanceWidget.cxx index 34c7cbbcdcfb..3e303c58ecb8 100644 --- a/vcl/qt5/QtInstanceWidget.cxx +++ b/vcl/qt5/QtInstanceWidget.cxx @@ -560,15 +560,30 @@ OUString QtInstanceWidget::get_tooltip_text() const void QtInstanceWidget::set_cursor_data(void*) { assert(false && "Not implemented yet"); } -void QtInstanceWidget::grab_mouse() { assert(false && "Not implemented yet"); } +void QtInstanceWidget::grab_mouse() +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { getQWidget()->grabMouse(); }); +} bool QtInstanceWidget::has_mouse_grab() const { - assert(false && "Not implemented yet"); - return false; + SolarMutexGuard g; + + bool bHasMouseGrab = false; + GetQtInstance().RunInMainThread( + [&] { bHasMouseGrab = QWidget::mouseGrabber() == getQWidget(); }); + + return bHasMouseGrab; } -void QtInstanceWidget::release_mouse() { assert(false && "Not implemented yet"); } +void QtInstanceWidget::release_mouse() +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { getQWidget()->releaseMouse(); }); +} bool QtInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& rX, int& rY, int& rWidth, int& rHeight) const commit 61fa9c603b5757f36e471d381195c15d96fc6548 Author: Michael Weghorn <[email protected]> AuthorDate: Tue May 13 12:07:04 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Wed May 14 08:38:30 2025 +0200 tdf#130857 weld: Simplify/Clarify grab API The weld::Widget API for grabbing is inspired by `gtk_grab_add` from GTK 3 [1] which grabs both, mouse and keyboard, blocking interaction with other widgets in the application. For LibreOffice, only grabbing the mouse is of interest. CustomWidgetController::CaptureMouse is the only caller of weld::Widget::add_grab, and the VCL implementation in SalInstanceWidget::add_grab also only calls `Window::CaptureMouse` on its vcl::Window. In addition, there is a concept of a "grab count", i.e. calling `weld::Widget::grab_add` multiple times without `weld::Widget::grab_remove` means that `weld::Widget::grab_remove` needs to be called the same amount of times later on. However, the concept of having "multiple grabs" at the same time is also not used anywhere in LO in practice, and the VCL implementation also doesn't implement that concept. Therefore: 1) Drop the logical concept of multiple grabs from the weld::API. Adjust the gtk3 implementation to make sure to have at most one grab at a time that is owned by LO application code. (Internal GTK toolkit code may use additional grabs.) 2) Rename the methods to make clear that only the mouse grab is of relevance. (The gtk3 implementation still uses `gtk_grab_add`, i.e. grabs the keyboard as well.) In GTK 4, there is no more API for grabbing the mouse and only a counter was used to keep track of how often weld::Widget::add_grab had been called. Switch that to a bool instead. Qt provides separate methods for grabbing the mouse (QWidget::grabMouse [2]) and the keyboard (QWidget::grabKeyboard [3]). This commit is also to clarify that only the former will be needed when implementing this weld API for the Qt-based VCL plugins in an upcoming commit and grabbing the keyboard isn't needed. [1] https://docs.gtk.org/gtk3/method.Widget.grab_add.html [2] https://doc.qt.io/qt-6/qwidget.html#grabMouse [3] https://doc.qt.io/qt-6/qwidget.html#grabKeyboard Change-Id: If6f34a5eed8efe3dfb8d453c1ee97796cd4418c7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185254 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/include/svtools/scrolladaptor.hxx b/include/svtools/scrolladaptor.hxx index 1eba1dfdf844..4b6c18dfca3f 100644 --- a/include/svtools/scrolladaptor.hxx +++ b/include/svtools/scrolladaptor.hxx @@ -67,7 +67,7 @@ public: virtual bool Inactive() const override { return !m_xScrollBar->get_sensitive(); } - bool HasGrab() const { return m_xScrollBar->has_grab(); } + bool HasGrab() const { return m_xScrollBar->has_mouse_grab(); } void SetThickness(int nThickness); diff --git a/include/vcl/customweld.hxx b/include/vcl/customweld.hxx index ca50afbd23e0..b875e4963423 100644 --- a/include/vcl/customweld.hxx +++ b/include/vcl/customweld.hxx @@ -90,12 +90,12 @@ public: return m_pDrawingArea->get_accessible_id(); return OUString(); } - void CaptureMouse() { m_pDrawingArea->grab_add(); } - bool IsMouseCaptured() const { return m_pDrawingArea->has_grab(); } + void CaptureMouse() { m_pDrawingArea->grab_mouse(); } + bool IsMouseCaptured() const { return m_pDrawingArea->has_mouse_grab(); } Point GetPointerPosPixel() const { return m_pDrawingArea->get_pointer_position(); } void EnableRTL(bool bEnable) { m_pDrawingArea->set_direction(bEnable); } bool IsRTLEnabled() const { return m_pDrawingArea->get_direction(); } - void ReleaseMouse() { m_pDrawingArea->grab_remove(); } + void ReleaseMouse() { m_pDrawingArea->release_mouse(); } void SetPointer(PointerStyle ePointerStyle) { m_pDrawingArea->set_cursor(ePointerStyle); } void SetHelpId(const OUString& rHelpId) { m_pDrawingArea->set_help_id(rHelpId); } void SetAccessibleName(const OUString& rName) { m_pDrawingArea->set_accessible_name(rName); } diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index ec8f3f5ac4b9..02e8a97a387a 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -301,9 +301,9 @@ public: m_aStyleUpdatedHdl = rLink; } - virtual void grab_add() = 0; - virtual bool has_grab() const = 0; - virtual void grab_remove() = 0; + virtual void grab_mouse() = 0; + virtual bool has_mouse_grab() const = 0; + virtual void release_mouse() = 0; // font size is in points, not pixels, e.g. see Window::[G]etPointFont virtual vcl::Font get_font() = 0; diff --git a/sd/source/ui/animations/CustomAnimationPane.cxx b/sd/source/ui/animations/CustomAnimationPane.cxx index f38390e4aee4..364d1cbddadc 100644 --- a/sd/source/ui/animations/CustomAnimationPane.cxx +++ b/sd/source/ui/animations/CustomAnimationPane.cxx @@ -2098,7 +2098,7 @@ IMPL_LINK_NOARG(CustomAnimationPane, AnimationSelectHdl, weld::TreeView&, void) IMPL_LINK_NOARG(CustomAnimationPane, SelectionHandler, Timer*, void) { - if (mxLBAnimation->has_grab()) // tdf#136474 try again later + if (mxLBAnimation->has_mouse_grab()) // tdf#136474 try again later { maIdle.Start(); return; diff --git a/vcl/inc/qt5/QtInstanceWidget.hxx b/vcl/inc/qt5/QtInstanceWidget.hxx index 53ace384176e..fb2bfb512e43 100644 --- a/vcl/inc/qt5/QtInstanceWidget.hxx +++ b/vcl/inc/qt5/QtInstanceWidget.hxx @@ -120,11 +120,11 @@ public: virtual void set_cursor_data(void*) override; - virtual void grab_add() override; + virtual void grab_mouse() override; - virtual bool has_grab() const override; + virtual bool has_mouse_grab() const override; - virtual void grab_remove() override; + virtual void release_mouse() override; virtual bool get_extents_relative_to(const Widget& rRelative, int& rX, int& rY, int& rWidth, int& rHeight) const override; diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index a9c4b4c3f306..04439f471dce 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -340,11 +340,11 @@ public: virtual bool get_extents_relative_to(const Widget& rRelative, int& x, int& y, int& width, int& height) const override; - virtual void grab_add() override; + virtual void grab_mouse() override; - virtual bool has_grab() const override; + virtual bool has_mouse_grab() const override; - virtual void grab_remove() override; + virtual void release_mouse() override; virtual bool get_direction() const override; diff --git a/vcl/qt5/QtInstanceWidget.cxx b/vcl/qt5/QtInstanceWidget.cxx index e759abe019dd..34c7cbbcdcfb 100644 --- a/vcl/qt5/QtInstanceWidget.cxx +++ b/vcl/qt5/QtInstanceWidget.cxx @@ -560,15 +560,15 @@ OUString QtInstanceWidget::get_tooltip_text() const void QtInstanceWidget::set_cursor_data(void*) { assert(false && "Not implemented yet"); } -void QtInstanceWidget::grab_add() { assert(false && "Not implemented yet"); } +void QtInstanceWidget::grab_mouse() { assert(false && "Not implemented yet"); } -bool QtInstanceWidget::has_grab() const +bool QtInstanceWidget::has_mouse_grab() const { assert(false && "Not implemented yet"); return false; } -void QtInstanceWidget::grab_remove() { assert(false && "Not implemented yet"); } +void QtInstanceWidget::release_mouse() { assert(false && "Not implemented yet"); } bool QtInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& rX, int& rY, int& rWidth, int& rHeight) const diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index d4fe36fd8b0c..6ef981e16125 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -590,11 +590,11 @@ bool SalInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& x, return true; } -void SalInstanceWidget::grab_add() { m_xWidget->CaptureMouse(); } +void SalInstanceWidget::grab_mouse() { m_xWidget->CaptureMouse(); } -bool SalInstanceWidget::has_grab() const { return m_xWidget->IsMouseCaptured(); } +bool SalInstanceWidget::has_mouse_grab() const { return m_xWidget->IsMouseCaptured(); } -void SalInstanceWidget::grab_remove() { m_xWidget->ReleaseMouse(); } +void SalInstanceWidget::release_mouse() { m_xWidget->ReleaseMouse(); } bool SalInstanceWidget::get_direction() const { return m_xWidget->IsRTLEnabled(); } diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index c43224bf81aa..07cac1419e65 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -2872,8 +2872,10 @@ private: gulong m_nDragDataDeleteignalId; gulong m_nDragGetSignalId; + // whether mouse has explicitly been grabbed from LO application code + bool m_bMouseGrabbed; + #if GTK_CHECK_VERSION(4, 0, 0) - int m_nGrabCount; GtkEventController* m_pFocusController; GtkEventController* m_pClickController; GtkEventController* m_pMotionController; @@ -3448,8 +3450,8 @@ public: , m_nDragFailedSignalId(0) , m_nDragDataDeleteignalId(0) , m_nDragGetSignalId(0) + , m_bMouseGrabbed(false) #if GTK_CHECK_VERSION(4, 0, 0) - , m_nGrabCount(0) , m_pFocusController(nullptr) , m_pClickController(nullptr) , m_pMotionController(nullptr) @@ -4080,31 +4082,32 @@ public: } #endif - virtual void grab_add() override + virtual void grab_mouse() override { -#if GTK_CHECK_VERSION(4, 0, 0) - ++m_nGrabCount; -#else - gtk_grab_add(m_pWidget); +#if !GTK_CHECK_VERSION(4, 0, 0) + // have at most one grab owned by LO application code + if (!m_bMouseGrabbed) + gtk_grab_add(m_pWidget); #endif + m_bMouseGrabbed = true; } - virtual bool has_grab() const override + virtual bool has_mouse_grab() const override { #if GTK_CHECK_VERSION(4, 0, 0) - return m_nGrabCount != 0; + return m_bMouseGrabbed; #else return gtk_widget_has_grab(m_pWidget); #endif } - virtual void grab_remove() override + virtual void release_mouse() override { -#if GTK_CHECK_VERSION(4, 0, 0) - --m_nGrabCount; -#else - gtk_grab_remove(m_pWidget); +#if !GTK_CHECK_VERSION(4, 0, 0) + if (m_bMouseGrabbed) + gtk_grab_remove(m_pWidget); #endif + m_bMouseGrabbed = false; } virtual bool get_direction() const override @@ -8755,7 +8758,7 @@ public: virtual ScrollType get_scroll_type() const override { // tdf#153049 want a mousewheel spin to be treated as DontKnow - return has_grab() ? ScrollType::Drag : ScrollType::DontKnow; + return has_mouse_grab() ? ScrollType::Drag : ScrollType::DontKnow; } virtual int get_scroll_thickness() const override
