vcl/inc/unx/gtk/gtkframe.hxx | 2 ++ vcl/inc/unx/gtk/gtksalmenu.hxx | 1 + vcl/unx/gtk3/gtkframe.cxx | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+)
New commits: commit 7abf811bcbb92562a8da965d2ff03b9d53853e09 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Oct 1 12:42:26 2021 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Oct 1 22:51:24 2021 +0200 tdf#144846 launch gtk3 menubar menus from LibreOffice code rather than using the builtin gtk mechanism so we can avoid duplicate mnemonics in the sidebar getting used instead. Change-Id: I6c761ae63ae25d835de9444b0e298c63996a83a7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122926 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index b71d40785200..ced3613ad0ca 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -410,6 +410,8 @@ class GtkSalFrame final : public SalFrame void SetIcon(const char* pIcon); + bool HandleMenubarMnemonic(guint eState, guint nKeyval); + public: cairo_surface_t* m_pSurface; basegfx::B2IVector m_aFrameSize; diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx index 36b695a2ccc9..8b68391b1fc9 100644 --- a/vcl/inc/unx/gtk/gtksalmenu.hxx +++ b/vcl/inc/unx/gtk/gtksalmenu.hxx @@ -121,6 +121,7 @@ public: GtkSalMenu* GetTopLevel(); void SetNeedsUpdate(); + GtkWidget* GetMenuBarWidget() const { return mpMenuBarWidget; } GtkWidget* GetMenuBarContainerWidget() const { return mpMenuBarContainerWidget; } void CreateMenuBarWidget(); diff --git a/vcl/unx/gtk3/gtkframe.cxx b/vcl/unx/gtk3/gtkframe.cxx index a62bdd67162b..aa1d5b600187 100644 --- a/vcl/unx/gtk3/gtkframe.cxx +++ b/vcl/unx/gtk3/gtkframe.cxx @@ -24,6 +24,7 @@ #include <unx/gtk/gtksalmenu.hxx> #include <unx/gtk/hudawareness.h> #include <vcl/event.hxx> +#include <vcl/i18nhelp.hxx> #include <vcl/keycodes.hxx> #include <unx/geninst.h> #include <headless/svpgdi.hxx> @@ -3847,6 +3848,40 @@ static bool key_forward(GdkEventKey* pEvent, GtkWindow* pDest) return bHandled; } +static bool activate_menubar_mnemonic(GtkWidget* pWidget, guint nKeyval) +{ + const char* pLabel = gtk_menu_item_get_label(GTK_MENU_ITEM(pWidget)); + gunichar cAccelChar = 0; + if (!pango_parse_markup(pLabel, -1, '_', nullptr, nullptr, &cAccelChar, nullptr)) + return false; + if (!cAccelChar) + return false; + auto nMnemonicKeyval = gdk_keyval_to_lower(gdk_unicode_to_keyval(cAccelChar)); + if (nKeyval == nMnemonicKeyval) + return gtk_widget_mnemonic_activate(pWidget, false); + return false; +} + +bool GtkSalFrame::HandleMenubarMnemonic(guint eState, guint nKeyval) +{ + bool bUsedInMenuBar = false; + if (eState & GDK_ALT_MASK) + { + if (GtkWidget* pMenuBar = m_pSalMenu ? m_pSalMenu->GetMenuBarWidget() : nullptr) + { + GList* pChildren = gtk_container_get_children(GTK_CONTAINER(pMenuBar)); + for (GList* pChild = g_list_first(pChildren); pChild; pChild = g_list_next(pChild)) + { + bUsedInMenuBar = activate_menubar_mnemonic(static_cast<GtkWidget*>(pChild->data), nKeyval); + if (bUsedInMenuBar) + break; + } + g_list_free(pChildren); + } + } + return bUsedInMenuBar; +} + gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer frame) { UpdateLastInputEventTime(pEvent->time); @@ -3859,6 +3894,12 @@ gboolean GtkSalFrame::signalKey(GtkWidget* pWidget, GdkEventKey* pEvent, gpointe if (GTK_IS_WINDOW(pThis->m_pWindow)) { + // tdf#144846 If this is registered as a menubar mnemonic then ensure + // that any other widget won't be considered as a candidate by taking + // over the task of launch the menubar menu outself + if (pThis->HandleMenubarMnemonic(pEvent->state, pEvent->keyval)) + return true; + GtkWidget* pFocusWindow = gtk_window_get_focus(GTK_WINDOW(pThis->m_pWindow)); bFocusInAnotherGtkWidget = pFocusWindow && pFocusWindow != GTK_WIDGET(pThis->m_pFixedContainer); if (bFocusInAnotherGtkWidget)