summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2021-10-01 12:42:26 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2021-10-05 10:50:23 +0200
commit03ea50373b37f2a0e5d44649a6ccc9c89d1e3244 (patch)
tree6841eec3179f704b2a411f6ee75e53abc3e2da9c /vcl
parent2af7baa30da250a6f6894175e9fda130554eb4ac (diff)
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/+/122928 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx2
-rw-r--r--vcl/inc/unx/gtk/gtksalmenu.hxx1
-rw-r--r--vcl/unx/gtk3/gtkframe.cxx42
3 files changed, 45 insertions, 0 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index b1ddd52913b8..fd4ab4af66da 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -392,6 +392,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 e55cb791e90c..a402e0d15ec1 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 14f2a2e76c59..a7ba7eec9cdb 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>
@@ -3737,6 +3738,41 @@ gboolean GtkSalFrame::signalUnmap(GtkWidget*, GdkEvent*, gpointer frame)
#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
+
+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);
@@ -3749,6 +3785,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_pDrawingArea);
if (bFocusInAnotherGtkWidget)