vcl/qt5/QtInstanceDrawingArea.cxx | 10 ----- vcl/qt5/QtInstanceTreeView.cxx | 9 ----- vcl/qt5/QtInstanceWidget.cxx | 8 ++++ vcl/unx/gtk3/gtkinst.cxx | 65 +++++++++++--------------------------- 4 files changed, 28 insertions(+), 64 deletions(-)
New commits: commit 9c3ace1c2f6b1ff74f17e775f2dda98481a67ecd Author: Michael Weghorn <[email protected]> AuthorDate: Thu Dec 11 01:26:41 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Fri Dec 12 13:26:18 2025 +0100 tdf#130857 gtk weld: Forward keyboard-triggered context menu events, too Previous commit Change-Id: Ie283a5f4975b7ba124abc69623d29c130c6ae2b6 Author: Michael Weghorn <[email protected]> Date: Thu Dec 11 01:07:05 2025 +0100 tdf#130857 gtk weld: Forward context menu events for all widgets implemented forwarding context menu events for all widgets when they are triggered using the mouse. Implement the same for keyboard-triggered events, at least for gtk3 (the GtkWidget::popup-menu event doesn't seem to exist any more in GTK 4), for which this was previously implemented for the weld::TreeView, weld::IconView and weld::DrawingArea subclasses. Move the logic to the base class. This results in the corresponding output when testing the example as described in Change-Id: I07c5f136cc1671e1e0ca0ee3df11d2d9febc654a Author: Michael Weghorn <[email protected]> Date: Thu Dec 11 00:45:42 2025 +0100 tdf#130857 qt weld: Forward context menu events for all widgets , but now using the gtk3 VCL plugin and triggering the context menu event by moving focus to the button and pressing the context menu key on the keyboard instead of right-clicking it using the mouse. Change-Id: I919546761718384adb05fbaf8c3410999a0bba54 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195419 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index f8c6ef2d2084..ed775b97c427 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -2742,6 +2742,7 @@ private: GtkCssProvider* m_pBgCssProvider; #if !GTK_CHECK_VERSION(4, 0, 0) GdkDragAction m_eDragAction; + gulong m_nPopupMenuSignalId; #endif gulong m_nFocusInSignalId; gulong m_nMnemonicActivateSignalId; @@ -3318,6 +3319,7 @@ public: , m_pBgCssProvider(nullptr) #if !GTK_CHECK_VERSION(4, 0, 0) , m_eDragAction(GdkDragAction(0)) + , m_nPopupMenuSignalId(0) #endif , m_nFocusInSignalId(0) , m_nMnemonicActivateSignalId(0) @@ -3370,6 +3372,10 @@ public: virtual void connect_command(const Link<const CommandEvent&, bool>& rLink) override { +#if !GTK_CHECK_VERSION(4, 0, 0) + if (!m_nPopupMenuSignalId) + m_nPopupMenuSignalId = g_signal_connect(m_pWidget, "popup-menu", G_CALLBACK(signalPopupMenu), this); +#endif ensureButtonPressSignal(); weld::Widget::connect_command(rLink); } @@ -4141,6 +4147,10 @@ public: if (m_pDragCancelEvent) Application::RemoveUserEvent(m_pDragCancelEvent); +#if !GTK_CHECK_VERSION(4, 0, 0) + if (m_nPopupMenuSignalId) + g_signal_handler_disconnect(m_pWidget, m_nPopupMenuSignalId); +#endif if (m_nDragMotionSignalId) g_signal_handler_disconnect(m_pWidget, m_nDragMotionSignalId); if (m_nDragDropSignalId) @@ -13923,7 +13933,6 @@ private: gulong m_nRowDeletedSignalId; gulong m_nRowInsertedSignalId; #if !GTK_CHECK_VERSION(4, 0, 0) - gulong m_nPopupMenuSignalId; gulong m_nKeyPressSignalId; gulong m_nCrossingSignalid; #endif @@ -14632,7 +14641,6 @@ public: , m_nTestCollapseRowSignalId(g_signal_connect(pTreeView, "test-collapse-row", G_CALLBACK(signalTestCollapseRow), this)) , m_nVAdjustmentChangedSignalId(0) #if !GTK_CHECK_VERSION(4, 0, 0) - , m_nPopupMenuSignalId(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this)) , m_nKeyPressSignalId(g_signal_connect(pTreeView, "key-press-event", G_CALLBACK(signalKeyPress), this)) , m_nCrossingSignalid(g_signal_connect(pTreeView, "enter-notify-event", G_CALLBACK(signalCrossing), this)) #endif @@ -16634,7 +16642,6 @@ public: #if !GTK_CHECK_VERSION(4, 0, 0) g_signal_handler_disconnect(m_pTreeView, m_nCrossingSignalid); g_signal_handler_disconnect(m_pTreeView, m_nKeyPressSignalId); - g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId); #endif g_signal_handler_disconnect(m_pTreeModel, m_nRowDeletedSignalId); g_signal_handler_disconnect(m_pTreeModel, m_nRowInsertedSignalId); @@ -16704,9 +16711,6 @@ private: gint m_nIdCol; gulong m_nSelectionChangedSignalId; gulong m_nItemActivatedSignalId; -#if !GTK_CHECK_VERSION(4, 0, 0) - gulong m_nPopupMenu; -#endif gulong m_nQueryTooltipSignalId = 0; ImplSVEvent* m_pSelectionChangeEvent; @@ -16951,9 +16955,6 @@ public: , m_nSelectionChangedSignalId(g_signal_connect(pIconView, "selection-changed", G_CALLBACK(signalSelectionChanged), this)) , m_nItemActivatedSignalId(g_signal_connect(pIconView, "item-activated", G_CALLBACK(signalItemActivated), this)) -#if !GTK_CHECK_VERSION(4, 0, 0) - , m_nPopupMenu(g_signal_connect(pIconView, "popup-menu", G_CALLBACK(signalPopupMenu), this)) -#endif , m_pSelectionChangeEvent(nullptr) { m_nIdCol = std::max(m_nTextCol, m_nImageCol) + 1; @@ -17275,9 +17276,6 @@ public: g_signal_handler_disconnect(m_pIconView, m_nItemActivatedSignalId); g_signal_handler_disconnect(m_pIconView, m_nSelectionChangedSignalId); -#if !GTK_CHECK_VERSION(4, 0, 0) - g_signal_handler_disconnect(m_pIconView, m_nPopupMenu); -#endif } }; @@ -18274,7 +18272,6 @@ private: #endif gulong m_nQueryTooltip; #if !GTK_CHECK_VERSION(4, 0, 0) - gulong m_nPopupMenu; gulong m_nScrollEvent; #endif GtkGesture *m_pZoomGesture; @@ -18452,7 +18449,6 @@ public: , m_pSurface(nullptr) , m_nQueryTooltip(g_signal_connect(m_pDrawingArea, "query-tooltip", G_CALLBACK(signalQueryTooltip), this)) #if !GTK_CHECK_VERSION(4, 0, 0) - , m_nPopupMenu(g_signal_connect(m_pDrawingArea, "popup-menu", G_CALLBACK(signalPopupMenu), this)) , m_nScrollEvent(g_signal_connect(m_pDrawingArea, "scroll-event", G_CALLBACK(signalScroll), this)) #endif { @@ -18709,9 +18705,6 @@ public: m_xAccessible->dispose(); #if !GTK_CHECK_VERSION(4, 0, 0) g_signal_handler_disconnect(m_pDrawingArea, m_nScrollEvent); -#endif -#if !GTK_CHECK_VERSION(4, 0, 0) - g_signal_handler_disconnect(m_pDrawingArea, m_nPopupMenu); #endif g_signal_handler_disconnect(m_pDrawingArea, m_nQueryTooltip); #if GTK_CHECK_VERSION(4, 0, 0) commit bb0bde112ee4d1fd33f32c3ca556c045f2620190 Author: Michael Weghorn <[email protected]> AuthorDate: Thu Dec 11 01:07:05 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Fri Dec 12 13:26:11 2025 +0100 tdf#130857 gtk weld: Forward context menu events for all widgets This is basically the gtk3 and gtk4 version of previous commit Change-Id: I07c5f136cc1671e1e0ca0ee3df11d2d9febc654a Author: Michael Weghorn <[email protected]> Date: Thu Dec 11 00:45:42 2025 +0100 tdf#130857 qt weld: Forward context menu events for all widgets and allows handling ContextMenu events for all weld::Widget subclasses, as demonstrated e.g. by the scenario described in the above-mentioned commit, which now also works with gtk3 and gtk4. Change-Id: Ie283a5f4975b7ba124abc69623d29c130c6ae2b6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195418 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 60c8b7a0f4a9..f8c6ef2d2084 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -2571,7 +2571,7 @@ protected: Point aPos(gtk_widget_get_allocated_width(pWidget) / 2, gtk_widget_get_allocated_height(pWidget) / 2); CommandEvent aCEvt(aPos, CommandEventId::ContextMenu, false); - return pThis->signal_popup_menu(aCEvt); + return pThis->signal_command(aCEvt); } #endif @@ -2812,11 +2812,6 @@ private: } #endif - virtual bool signal_popup_menu(const CommandEvent&) - { - return false; - } - #if GTK_CHECK_VERSION(4, 0, 0) static void signalButtonPress(GtkGestureClick* pGesture, int n_press, gdouble x, gdouble y, gpointer widget) { @@ -2848,7 +2843,7 @@ private: { //if handled for context menu, stop processing CommandEvent aCEvt(aPos, CommandEventId::ContextMenu, true); - if (signal_popup_menu(aCEvt)) + if (signal_command(aCEvt)) { gtk_gesture_set_state(GTK_GESTURE(pGesture), GTK_EVENT_SEQUENCE_CLAIMED); return; @@ -2914,7 +2909,7 @@ private: { //if handled for context menu, stop processing CommandEvent aCEvt(aPos, CommandEventId::ContextMenu, true); - if (signal_popup_menu(aCEvt)) + if (signal_command(aCEvt)) return true; } @@ -3373,6 +3368,12 @@ public: localizeDecimalSeparator(); } + virtual void connect_command(const Link<const CommandEvent&, bool>& rLink) override + { + ensureButtonPressSignal(); + weld::Widget::connect_command(rLink); + } + virtual void connect_key_press(const Link<const KeyEvent&, bool>& rLink) override { if (!m_nKeyPressSignalId) @@ -13979,11 +13980,6 @@ private: pThis->handle_row_activated(); } - virtual bool signal_popup_menu(const CommandEvent& rCEvt) override - { - return weld::TreeView::signal_command(rCEvt); - } - void insert_row(GtkTreeIter& iter, const GtkTreeIter* parent, int pos, const OUString* pId, const OUString* pText, const OUString* pIconName, const VirtualDevice* pDevice) { @@ -16256,12 +16252,6 @@ public: g_signal_handler_unblock(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId); } - virtual void connect_command(const Link<const CommandEvent&, bool>& rLink) override - { - ensureButtonPressSignal(); - weld::TreeView::connect_command(rLink); - } - virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter* pResult, bool bDnDMode, bool bAutoScroll) override { if (rPos.X() < 0 || rPos.Y() < 0) @@ -16722,11 +16712,6 @@ private: DECL_LINK(async_signal_selection_changed, void*, void); - virtual bool signal_popup_menu(const CommandEvent& rCEvt) override - { - return signal_command(rCEvt); - } - void launch_signal_selection_changed() { //tdf#117991 selection change is sent before the focus change, and focus change @@ -18377,10 +18362,7 @@ private: gtk_tooltip_set_tip_area(tooltip, &aGdkHelpArea); return true; } - virtual bool signal_popup_menu(const CommandEvent& rCEvt) override - { - return signal_command(rCEvt); - } + #if !GTK_CHECK_VERSION(4, 0, 0) bool signal_scroll(const GdkEventScroll* pEvent) { commit c8c7ea29c558d9415c2985abace647eed64a927b Author: Michael Weghorn <[email protected]> AuthorDate: Thu Dec 11 00:45:42 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Fri Dec 12 13:26:03 2025 +0100 tdf#130857 qt weld: Forward context menu events for all widgets Following Change-Id: I9367bdbb8be7994057667fab539aaf135751e063 Author: Michael Weghorn <[email protected]> Date: Wed Dec 10 23:08:21 2025 +0100 tdf#130857 weld: Move CommandEvent handling to weld::Widget base , now move handling of context menu events from the QtInstanceDrawingArea and QtInstanceTreeView subclasses to the QtInstanceWidget base class. This deduplicates code and makes this work for all widgets, not just those 2 specific ones. Sample scenario to test: * apply the below diff locally and build LO * start Writer with the qt6 VCL plugin and environment variable SAL_VCL_QT_USE_WELDED_WIDGETS=1 * open the "Help" -> "About LibreOfficeDev" dialog * right-click on the button that can be used to copy the version information to trigger a context menu event * observe that this demo warning (added because of the below local modification for testing) is now shown on stderr: warn:cui.dialogs:204595:204595:cui/source/dialogs/about.cxx:288: got context menu event Local diff for testing: diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx index 51a57b8ec072..2c49ce2cb66f 100644 --- a/cui/source/dialogs/about.cxx +++ b/cui/source/dialogs/about.cxx @@ -26,6 +26,7 @@ #include <osl/process.h> //osl_getProcessLocale #include <rtl/bootstrap.hxx> #include <sal/log.hxx> //SAL_WARN +#include <vcl/commandevent.hxx> #include <vcl/graph.hxx> //Graphic #include <vcl/settings.hxx> //GetSettings #include <vcl/svapp.hxx> //Application:: @@ -139,6 +140,7 @@ AboutDialog::AboutDialog(weld::Window* pParent) // Handler m_pCopyButton->connect_clicked(LINK(this, AboutDialog, HandleClick)); + m_pCopyButton->connect_command(LINK(this, AboutDialog, ContextMenuHdl)); m_pCloseButton->grab_focus(); } @@ -278,4 +280,14 @@ IMPL_LINK_NOARG(AboutDialog, HandleClick, weld::Button&, void) vcl::unohelper::TextDataObject::CopyStringTo(sInfo, xClipboard); } + +IMPL_LINK(AboutDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) +{ + assert(this); + if (rCEvt.GetCommand() == CommandEventId::ContextMenu) + SAL_WARN("cui.dialogs", "got context menu event"); + + return false; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/about.hxx b/cui/source/inc/about.hxx index 42eae5467eab..6e7e2e0f5471 100644 --- a/cui/source/inc/about.hxx +++ b/cui/source/inc/about.hxx @@ -49,6 +49,7 @@ private: static bool IsStringValidGitHash(std::u16string_view hash); DECL_LINK(HandleClick, weld::Button&, void); + DECL_LINK(ContextMenuHdl, const CommandEvent&, bool); public: AboutDialog(weld::Window* pParent); Change-Id: I07c5f136cc1671e1e0ca0ee3df11d2d9febc654a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195417 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/qt5/QtInstanceDrawingArea.cxx b/vcl/qt5/QtInstanceDrawingArea.cxx index b6b87d68a065..1aa528be322d 100644 --- a/vcl/qt5/QtInstanceDrawingArea.cxx +++ b/vcl/qt5/QtInstanceDrawingArea.cxx @@ -13,7 +13,6 @@ #include <QtAccessibleWidget.hxx> #include <QtData.hxx> -#include <vcl/commandevent.hxx> #include <vcl/qt/QtUtils.hxx> #include <QtGui/QHelpEvent> @@ -121,15 +120,6 @@ bool QtInstanceDrawingArea::eventFilter(QObject* pObject, QEvent* pEvent) switch (pEvent->type()) { - case QEvent::ContextMenu: - { - QContextMenuEvent* pContextMenuEvent = static_cast<QContextMenuEvent*>(pEvent); - const Point aPos = toPoint(pContextMenuEvent->pos()); - const CommandEvent aEvent(aPos, CommandEventId::ContextMenu); - if (signal_command(aEvent)) - return true; - break; - } case QEvent::Paint: handlePaintEvent(); return false; diff --git a/vcl/qt5/QtInstanceTreeView.cxx b/vcl/qt5/QtInstanceTreeView.cxx index abaf70a6f92a..75cf1214a926 100644 --- a/vcl/qt5/QtInstanceTreeView.cxx +++ b/vcl/qt5/QtInstanceTreeView.cxx @@ -10,7 +10,6 @@ #include <QtInstanceTreeView.hxx> #include <QtInstanceTreeView.moc> -#include <vcl/commandevent.hxx> #include <vcl/qt/QtUtils.hxx> #include <QtWidgets/QHeaderView> @@ -1111,14 +1110,6 @@ bool QtInstanceTreeView::eventFilter(QObject* pObject, QEvent* pEvent) if (pEvent->type() == QEvent::ToolTip && pObject == m_pTreeView->viewport()) return handleViewPortToolTipEvent(static_cast<QHelpEvent&>(*pEvent)); - if (pEvent->type() == QEvent::ContextMenu) - { - QContextMenuEvent* pContextMenuEvent = static_cast<QContextMenuEvent*>(pEvent); - CommandEvent aCEvt(toPoint(pContextMenuEvent->pos()), CommandEventId::ContextMenu, - pContextMenuEvent->reason() == QContextMenuEvent::Mouse); - return signal_command(aCEvt); - } - return QtInstanceWidget::eventFilter(pObject, pEvent); } diff --git a/vcl/qt5/QtInstanceWidget.cxx b/vcl/qt5/QtInstanceWidget.cxx index e765272d341e..724895c70612 100644 --- a/vcl/qt5/QtInstanceWidget.cxx +++ b/vcl/qt5/QtInstanceWidget.cxx @@ -13,6 +13,7 @@ #include <QtInstanceContainer.hxx> #include <i18nlangtag/languagetag.hxx> +#include <vcl/commandevent.hxx> #include <vcl/transfer.hxx> #include <vcl/qt/QtUtils.hxx> @@ -273,6 +274,13 @@ bool QtInstanceWidget::eventFilter(QObject* pObject, QEvent* pEvent) switch (pEvent->type()) { + case QEvent::ContextMenu: + { + QContextMenuEvent* pContextMenuEvent = static_cast<QContextMenuEvent*>(pEvent); + CommandEvent aCEvt(toPoint(pContextMenuEvent->pos()), CommandEventId::ContextMenu, + pContextMenuEvent->reason() == QContextMenuEvent::Mouse); + return signal_command(aCEvt); + } case QEvent::DragEnter: { if (!m_pDropTarget)
