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)

Reply via email to