include/vcl/toolkit/dialog.hxx |    2 
 include/vcl/weld/Dialog.hxx    |    4 +
 include/vcl/weld/weld.hxx      |    2 
 vcl/inc/salvtables.hxx         |    2 
 vcl/qt5/QtInstanceBuilder.cxx  |    1 
 vcl/source/app/salvtables.cxx  |   32 -------------
 vcl/source/weld/Dialog.cxx     |   33 ++++++++++++++
 vcl/source/window/dialog.cxx   |   13 -----
 vcl/unx/gtk3/gtkinst.cxx       |   94 +----------------------------------------
 9 files changed, 43 insertions(+), 140 deletions(-)

New commits:
commit 04e380b9aaf86fd4403d5ceed0cb8db98d94adb9
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Feb 13 13:35:02 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Sat Feb 14 00:49:43 2026 +0100

    vcl: Drop now unused custom Dialog command event logic
    
    DialogImpl::m_aPopupMenuHdl is now unused because
    Dialog::SetPopupMenuHdl no more gets called from
    anywhere since previous commit
    
        Change-Id: Ia23a95591319d7cdc8d9e27a4025603644b36f04
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Feb 13 13:17:06 2026 +0100
    
            tdf#130857 weld: Implement screenshot menu logic in weld::Dialog 
base
    
    Therefore, drop it and the corresponding logic
    altogether.
    
    Change-Id: I3b764df2cd44d1b63558ead7b35f9a91643f76e6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199343
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/include/vcl/toolkit/dialog.hxx b/include/vcl/toolkit/dialog.hxx
index 0a2a38c660d0..a75467a2dacd 100644
--- a/include/vcl/toolkit/dialog.hxx
+++ b/include/vcl/toolkit/dialog.hxx
@@ -110,7 +110,6 @@ public:
     virtual bool    EventNotify( NotifyEvent& rNEvt ) override;
     virtual void    StateChanged( StateChangedType nStateChange ) override;
     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
-    virtual void    Command( const CommandEvent& rCEvt ) override;
     virtual void    PixelInvalidate(const tools::Rectangle* pRectangle) 
override;
 
     virtual void queue_resize(StateChangedType eReason = 
StateChangedType::Layout) override;
@@ -153,7 +152,6 @@ public:
 
     void            Activate() override;
 
-    void            SetPopupMenuHdl(const Link<const CommandEvent&, bool>& 
rLink);
     void            SetInstallLOKNotifierHdl(const Link<void*, 
vcl::ILibreOfficeKitNotifier*>& rLink);
     void            SetLOKTunnelingState(bool bEnabled);
 
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index f0e190318120..674f78a021a8 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -355,7 +355,6 @@ struct DialogImpl
     tools::Long    mnResult;
     bool    mbStartedModal;
     VclAbstractDialog::AsyncContext maEndCtx;
-    Link<const CommandEvent&, bool> m_aPopupMenuHdl;
     Link<void*, vcl::ILibreOfficeKitNotifier*> m_aInstallLOKNotifierHdl;
     bool    m_bLOKTunneling;
 
@@ -723,11 +722,6 @@ Size bestmaxFrameSizeForScreenSize(const Size &rScreenSize)
 #endif
 }
 
-void Dialog::SetPopupMenuHdl(const Link<const CommandEvent&, bool>& rLink)
-{
-    mpDialogImpl->m_aPopupMenuHdl = rLink;
-}
-
 void Dialog::SetInstallLOKNotifierHdl(const Link<void*, 
vcl::ILibreOfficeKitNotifier*>& rLink)
 {
     mpDialogImpl->m_aInstallLOKNotifierHdl = rLink;
@@ -1648,13 +1642,6 @@ void Dialog::Activate()
     SystemWindow::Activate();
 }
 
-void Dialog::Command(const CommandEvent& rCEvt)
-{
-    if (mpDialogImpl->m_aPopupMenuHdl.Call(rCEvt))
-        return;
-    SystemWindow::Command(rCEvt);
-}
-
 struct TopLevelWindowLockerImpl
 {
     std::stack<std::vector<VclPtr<vcl::Window>>> m_aBusyStack;
commit f0fbe79cd5b5fd0444189f07d5fc06d41764b3c7
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Feb 13 13:17:06 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Sat Feb 14 00:49:35 2026 +0100

    tdf#130857 weld: Implement screenshot menu logic in weld::Dialog base
    
    Instead of having a separate implementation
    to show a menu with a "Screenshot" entry
    that triggers running the screenshot annotation
    dialog in each toolkit-specific weld::Dialog subclass,
    implement the logic right in the base class.
    
    In order to do so, override weld::Widget::signal_command
    in weld::Dialog to show the screenshot menu if enabled via
    the corresponding setting.
    (Previous gtk3 and vcl implementations would check the
    setting before connecting the context menu event handlers,
    but that is equivalent.)
    
    This reuses the vcl/SalInstanceDialog logic from
    SalInstanceDialog::PopupScreenShotMenuHdl previously
    adjusted to use the weld API abstraction in earlier commit
    
        Change-Id: I1fa5c132e485ec0042176e9cc5b6f07fcdce7c75
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Feb 13 11:13:11 2026 +0100
    
            tdf#130857 vcl: Port dialog screenshot menu to weld abstraction
    
    and moves it to the new weld::Dialog::signal_command method.
    
    Drop the vcl and gtk3 specific implementations as they
    are no more needed now.
    
    Apart from deduplicating/unifying the gtk3 and vcl
    implementations, this also means that the logic is
    now also available for the Qt-based VCL plugins
    when native widgets are used with
    SAL_VCL_QT_USE_WELDED_WIDGETS=1, and for the gtk4
    VCL plugin.
    
    For Qt, declare the menu's .ui file as supported.
    
    The menu/dialog were tested fine for all of gen, gtk3 and qt6
    (with SAL_VCL_QT_USE_WELDED_WIDGETS=1) for
    the "Help" -> "About LibreOfficeDev" dialog
    according to the desecription at [1]:
    
    > To create dialog screenshots from running LibreOffice, you need to
    > activate screenshotting mode (akin to experimental mode) in Tools ▸
    > Options ▸ Advanced ▸ Open Expert Configuration, the relevant
    > configuration key is org.openoffice.Office.Common.Misc.ScreenshotMode.
    > Once screenshotting mode is active, right mouse click into any dialog
    > action area (where "OK", "Cancel" etc. buttons are) will make a context
    > menu appear:
    >
    > Click Screenshot item of the context menu to create screenshot of the
    > current dialog.
    
    For gtk4, the menu now shows up as expected, but
    activating the "Screenshot" menu entry currently
    triggers an assert:
    
        soffice.bin: cui/source/dialogs/screenshotannotationdlg.cxx:266: 
ScreenshotAnnotationDlg_Impl::ScreenshotAnnotationDlg_Impl(weld::Window *, 
weld::Builder &, weld::Dialog &): Assertion `!maParentDialogBitmap.IsEmpty()' 
failed.
    
    The underlying issue is preexisting and will be
    addressed in a separate upcoming commit.
    (So far, there simply wasn't a way to trigger
    the relevant code path this way as the menu
    wasn't shown for gtk4 yet.)
    
    [1] 
https://wiki.documentfoundation.org/Documentation/Screenshots#Creating_screenshots_manually
    
    Change-Id: Ia23a95591319d7cdc8d9e27a4025603644b36f04
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199342
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/include/vcl/weld/Dialog.hxx b/include/vcl/weld/Dialog.hxx
index 4fb2187fb8ac..ebda6651d9b9 100644
--- a/include/vcl/weld/Dialog.hxx
+++ b/include/vcl/weld/Dialog.hxx
@@ -22,7 +22,11 @@ private:
                           const std::function<void(sal_Int32)>& func)
         = 0;
 
+    DECL_LINK(CommandHdl, const CommandEvent&, bool);
+
 protected:
+    virtual bool signal_command(const CommandEvent& rCEvt);
+
     void executeScreenshotAnnotationDialog();
 
 public:
diff --git a/include/vcl/weld/weld.hxx b/include/vcl/weld/weld.hxx
index 1694ab95c2ac..4bf7601fcd56 100644
--- a/include/vcl/weld/weld.hxx
+++ b/include/vcl/weld/weld.hxx
@@ -112,7 +112,7 @@ protected:
     bool notify_events_disabled() const { return m_nBlockNotify != 0; }
     void enable_notify_events() { --m_nBlockNotify; }
 
-    bool signal_command(const CommandEvent& rCEvt) { return 
m_aCommandHdl.Call(rCEvt); }
+    virtual bool signal_command(const CommandEvent& rCEvt) { return 
m_aCommandHdl.Call(rCEvt); }
     void signal_focus_in() { m_aFocusInHdl.Call(*this); }
     void signal_focus_out() { m_aFocusOutHdl.Call(*this); }
     bool signal_mnemonic_activate() { return 
m_aMnemonicActivateHdl.Call(*this); }
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 06163e9ea6e5..d0e32ee5ebe2 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -516,8 +516,6 @@ private:
     tools::Long m_nOldEditWidthReq; // Original width request of the input 
field
     sal_Int32 m_nOldBorderWidth; // border width for expanded dialog
 
-    DECL_LINK(PopupScreenShotMenuHdl, const CommandEvent&, bool);
-
     void recursively_unset_default_buttons();
 
     void implResetDefault(const vcl::Window* _pWindow);
diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 3b61b91a68da..18c55da978ac 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -371,6 +371,7 @@ constexpr auto SUPPORTED_WITH_QT_PARENT = 
frozen::make_unordered_set<std::u16str
     u"svx/ui/formnavigator.ui",
     u"svx/ui/formnavimenu.ui",
     u"vcl/ui/editmenu.ui",
+    u"vcl/ui/screenshotmenu.ui",
     u"xmlsec/ui/certdetails.ui",
     u"xmlsec/ui/certgeneral.ui",
 });
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 14434d5adc9d..f2fd5701a180 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1756,11 +1756,6 @@ SalInstanceDialog::SalInstanceDialog(::Dialog* pDialog, 
SalInstanceBuilder* pBui
     , m_nOldEditWidthReq(0)
     , m_nOldBorderWidth(0)
 {
-    const bool 
bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
-    if (bScreenshotMode)
-    {
-        m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, 
PopupScreenShotMenuHdl));
-    }
 }
 
 bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> 
const& rxOwner,
@@ -1978,33 +1973,6 @@ bool SalInstanceDialog::is_default_button(const 
weld::Button* pCandidate) const
     return pWidget && pWidget->GetStyle() & WB_DEFBUTTON;
 }
 
-IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, 
rCEvt, bool)
-{
-    if (CommandEventId::ContextMenu == rCEvt.GetCommand())
-    {
-        std::unique_ptr<weld::Builder> xBuilder(
-            Application::CreateBuilder(this, 
u"vcl/ui/screenshotmenu.ui"_ustr));
-        std::unique_ptr<weld::Menu> pMenu = xBuilder->weld_menu(u"menu"_ustr);
-        static constexpr OUString sMenuItemId = u"screenshot"_ustr;
-        pMenu->append(sMenuItemId, VclResId(SV_BUTTONTEXT_SCREENSHOT));
-        // set tooltip if extended tips are enabled
-        if (ImplGetSVHelpData().mbBalloonHelp)
-            pMenu->set_tooltip_text(sMenuItemId, 
VclResId(SV_HELPTEXT_SCREENSHOT));
-        pMenu->set_item_help_id(sMenuItemId, 
u"InteractiveScreenshotMode"_ustr);
-
-        if (pMenu->popup_at_rect(this, 
tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))
-            == sMenuItemId)
-            executeScreenshotAnnotationDialog();
-
-        // consume event when:
-        // - CommandEventId::ContextMenu
-        // - bScreenshotMode
-        return true;
-    }
-
-    return false;
-}
-
 SalInstanceMessageDialog::SalInstanceMessageDialog(::MessageDialog* pDialog,
                                                    SalInstanceBuilder* 
pBuilder,
                                                    bool bTakeOwnership)
diff --git a/vcl/source/weld/Dialog.cxx b/vcl/source/weld/Dialog.cxx
index 4272eb4f79f4..a0514d9ac337 100644
--- a/vcl/source/weld/Dialog.cxx
+++ b/vcl/source/weld/Dialog.cxx
@@ -7,11 +7,44 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <strings.hrc>
+#include <svdata.hxx>
+
+#include <officecfg/Office/Common.hxx>
 #include <vcl/abstdlg.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld/Builder.hxx>
 #include <vcl/weld/Dialog.hxx>
+#include <vcl/weld/Menu.hxx>
 
 namespace weld
 {
+bool Dialog::signal_command(const CommandEvent& rCEvt)
+{
+    if (CommandEventId::ContextMenu == rCEvt.GetCommand()
+        && officecfg::Office::Common::Misc::ScreenshotMode::get())
+    {
+        std::unique_ptr<weld::Builder> xBuilder(
+            Application::CreateBuilder(this, 
u"vcl/ui/screenshotmenu.ui"_ustr));
+        std::unique_ptr<weld::Menu> pMenu = xBuilder->weld_menu(u"menu"_ustr);
+        static constexpr OUString sMenuItemId = u"screenshot"_ustr;
+        pMenu->append(sMenuItemId, VclResId(SV_BUTTONTEXT_SCREENSHOT));
+        // set tooltip if extended tips are enabled
+        if (ImplGetSVHelpData().mbBalloonHelp)
+            pMenu->set_tooltip_text(sMenuItemId, 
VclResId(SV_HELPTEXT_SCREENSHOT));
+        pMenu->set_item_help_id(sMenuItemId, 
u"InteractiveScreenshotMode"_ustr);
+
+        if (pMenu->popup_at_rect(this, 
tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))
+            == sMenuItemId)
+            executeScreenshotAnnotationDialog();
+
+        return true;
+    }
+
+    return Window::signal_command(rCEvt);
+}
+
 void Dialog::executeScreenshotAnnotationDialog()
 {
     // open screenshot annotation dialog
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index d1f53f59eef0..df6e58d83fd4 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -7001,88 +7001,6 @@ private:
 
     void asyncresponse(gint ret);
 
-#if !GTK_CHECK_VERSION(4, 0, 0)
-    static void signalActivate(GtkMenuItem*, gpointer data)
-    {
-        bool* pActivate = static_cast<bool*>(data);
-        *pActivate = true;
-    }
-#endif
-
-#if !GTK_CHECK_VERSION(4, 0, 0)
-    bool signal_screenshot_popup_menu(const GdkEventButton* pEvent)
-    {
-        GtkWidget *pMenu = gtk_menu_new();
-
-        GtkWidget* pMenuItem = 
gtk_menu_item_new_with_mnemonic(MapToGtkAccelerator(VclResId(SV_BUTTONTEXT_SCREENSHOT)).getStr());
-        gtk_menu_shell_append(GTK_MENU_SHELL(pMenu), pMenuItem);
-        bool bActivate(false);
-        g_signal_connect(pMenuItem, "activate", G_CALLBACK(signalActivate), 
&bActivate);
-        gtk_widget_set_visible(pMenuItem, true);
-
-        int button, event_time;
-        if (pEvent)
-        {
-            button = pEvent->button;
-            event_time = pEvent->time;
-        }
-        else
-        {
-            button = 0;
-            event_time = gtk_get_current_event_time();
-        }
-
-        gtk_menu_attach_to_widget(GTK_MENU(pMenu), GTK_WIDGET(m_pDialog), 
nullptr);
-
-        GMainLoop* pLoop = g_main_loop_new(nullptr, true);
-        gulong nSignalId = g_signal_connect_swapped(G_OBJECT(pMenu), 
"deactivate", G_CALLBACK(g_main_loop_quit), pLoop);
-
-        gtk_menu_popup(GTK_MENU(pMenu), nullptr, nullptr, nullptr, nullptr, 
button, event_time);
-
-        if (g_main_loop_is_running(pLoop))
-            main_loop_run(pLoop);
-
-        g_main_loop_unref(pLoop);
-        g_signal_handler_disconnect(pMenu, nSignalId);
-        gtk_menu_detach(GTK_MENU(pMenu));
-
-        if (bActivate)
-            executeScreenshotAnnotationDialog();
-
-        return false;
-    }
-#endif
-
-    static gboolean signalScreenshotPopupMenu(GtkWidget*, gpointer widget)
-    {
-#if !GTK_CHECK_VERSION(4, 0, 0)
-        GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget);
-        return pThis->signal_screenshot_popup_menu(nullptr);
-#else
-        (void)widget;
-        return false;
-#endif
-    }
-
-#if !GTK_CHECK_VERSION(4, 0, 0)
-    static gboolean signalScreenshotButton(GtkWidget*, GdkEventButton* pEvent, 
gpointer widget)
-    {
-        GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget);
-        SolarMutexGuard aGuard;
-        return pThis->signal_screenshot_button(pEvent);
-    }
-
-    bool signal_screenshot_button(GdkEventButton* pEvent)
-    {
-        if 
(gdk_event_triggers_context_menu(reinterpret_cast<GdkEvent*>(pEvent)) && 
pEvent->type == GDK_BUTTON_PRESS)
-        {
-            //if handled for context menu, stop processing
-            return signal_screenshot_popup_menu(pEvent);
-        }
-        return false;
-    }
-#endif
-
 public:
     GtkInstanceDialog(GtkWindow* pDialog, GtkInstanceBuilder* pBuilder, bool 
bTakeOwnership)
         : GtkInstanceWindow(pDialog, pBuilder, bTakeOwnership)
@@ -7102,14 +7020,10 @@ public:
             m_nCloseSignalId = g_signal_connect(m_pDialog, "close", 
G_CALLBACK(signalClose), this);
         else
             m_nCloseSignalId = 0;
-        const bool 
bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get());
-        if (bScreenshotMode)
-        {
-            g_signal_connect(m_pDialog, "popup-menu", 
G_CALLBACK(signalScreenshotPopupMenu), this);
-#if !GTK_CHECK_VERSION(4, 0, 0)
-            g_signal_connect(m_pDialog, "button-press-event", 
G_CALLBACK(signalScreenshotButton), this);
-#endif
-        }
+
+        // ensure context menu entry events are emitted, needed for the 
screenshot menu
+        ensureButtonPressSignal();
+        ensurePopupMenuSignal();
     }
 
     virtual bool runAsync(const std::shared_ptr<weld::DialogController>& 
rDialogController,

Reply via email to