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,
