From f9a0affd6a1dc50e9aa742e6164d50aff4e3319e Mon Sep 17 00:00:00 2001 From: duncan Date: Mon, 19 Oct 2020 13:04:22 +0100 Subject: [PATCH] rebind menubar accelerators to the mainwindow --- src/control/Control.cpp | 2 ++ src/gui/MainWindow.cpp | 61 +++++++++++++++++++++++++++++++++-------- src/gui/MainWindow.h | 14 +++++----- src/gui/XournalView.cpp | 2 +- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/control/Control.cpp b/src/control/Control.cpp index ff4ca8b7..1618c30d 100644 --- a/src/control/Control.cpp +++ b/src/control/Control.cpp @@ -313,6 +313,8 @@ void Control::initWindow(MainWindow* win) { this->pluginController->registerMenu(); + win->rebindMenubarAccelerators(); + fireActionSelected(GROUP_SNAPPING, settings->isSnapRotation() ? ACTION_ROTATION_SNAPPING : ACTION_NONE); fireActionSelected(GROUP_GRID_SNAPPING, settings->isSnapGrid() ? ACTION_GRID_SNAPPING : ACTION_NONE); } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 81912fcb..9aab32c3 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -35,7 +35,7 @@ #include "util/DeviceListHelper.h" MainWindow::MainWindow(GladeSearchpath* gladeSearchPath, Control* control): - GladeGui(gladeSearchPath, "main.glade", "mainWindow"), ignoreNextHideEvent(false) { + GladeGui(gladeSearchPath, "main.glade", "mainWindow") { this->control = control; this->toolbarWidgets = new GtkWidget*[TOOLBAR_DEFINITIONS_LEN]; this->toolbarSelectMenu = new MainWindowToolbarMenu(this); @@ -150,6 +150,54 @@ MainWindow::MainWindow(GladeSearchpath* gladeSearchPath, Control* control): #endif } +gboolean MainWindow::isKeyForClosure(GtkAccelKey* key, GClosure* closure, gpointer data) { return closure == data; } + +gboolean MainWindow::invokeMenu(GtkWidget* widget) { + // g_warning("invoke_menu %s", gtk_widget_get_name(widget)); + gtk_widget_activate(widget); + return TRUE; +} + +void MainWindow::rebindAcceleratorsMenuItem(GtkWidget* widget, gpointer user_data) { + if (GTK_IS_MENU_ITEM(widget)) { + GtkAccelGroup* newAccelGroup = reinterpret_cast(user_data); + GList* menuAccelClosures = gtk_widget_list_accel_closures(widget); + for (GList* l = menuAccelClosures; l != NULL; l = l->next) { + GClosure* closure = reinterpret_cast(l->data); + GtkAccelGroup* accelGroup = gtk_accel_group_from_accel_closure(closure); + GtkAccelKey* key = gtk_accel_group_find(accelGroup, isKeyForClosure, closure); + + // g_warning("Rebind %s : %s", gtk_accelerator_get_label(key->accel_key, key->accel_mods), + // gtk_widget_get_name(widget)); + + gtk_accel_group_connect(newAccelGroup, key->accel_key, key->accel_mods, GtkAccelFlags(0), + g_cclosure_new_swap(G_CALLBACK(MainWindow::invokeMenu), widget, NULL)); + } + + MainWindow::rebindAcceleratorsSubMenu(widget, newAccelGroup); + } +} + +void MainWindow::rebindAcceleratorsSubMenu(GtkWidget* widget, gpointer user_data) { + if (GTK_IS_MENU_ITEM(widget)) { + GtkMenuItem* menuItem = reinterpret_cast(widget); + GtkWidget* subMenu = gtk_menu_item_get_submenu(menuItem); + if (GTK_IS_CONTAINER(subMenu)) { + gtk_container_foreach(reinterpret_cast(subMenu), rebindAcceleratorsMenuItem, user_data); + } + } +} + +// When the Menubar is hidden, accelerators no longer work so rebind them to the MainWindow +// It should be called after all plugins have been initialised so that their injected menu items are captured +void MainWindow::rebindMenubarAccelerators() { + this->globalAccelGroup = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(this->getWindow()), this->globalAccelGroup); + + GtkMenuBar* menuBar = (GtkMenuBar*)this->get("mainMenubar"); + gtk_container_foreach(reinterpret_cast(menuBar), rebindAcceleratorsSubMenu, this->globalAccelGroup); +} + MainWindow::~MainWindow() { for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { g_object_unref(this->toolbarWidgets[i]); @@ -181,17 +229,11 @@ const char* TOP_WIDGETS[] = {"tbTop1", "tbTop2", "mainContainerBox", nullptr}; void MainWindow::toggleMenuBar(MainWindow* win) { - if (win->ignoreNextHideEvent) { - win->ignoreNextHideEvent = false; - return; - } - GtkWidget* menu = win->get("mainMenubar"); if (gtk_widget_is_visible(menu)) { gtk_widget_hide(menu); } else { gtk_widget_show(menu); - win->ignoreNextHideEvent = true; } } @@ -274,11 +316,6 @@ void MainWindow::initHideMenu() { // Menu found, allow to hide it g_signal_connect(menuItem, "activate", G_CALLBACK(+[](GtkMenuItem* menuitem, MainWindow* self) { toggleMenuBar(self); }), this); - - GtkAccelGroup* accelGroup = gtk_accel_group_new(); - gtk_accel_group_connect(accelGroup, GDK_KEY_F10, static_cast(0), GTK_ACCEL_VISIBLE, - g_cclosure_new_swap(G_CALLBACK(toggleMenuBar), this, nullptr)); - gtk_window_add_accel_group(GTK_WINDOW(getWindow()), accelGroup); } // Hide menubar at startup if specified in settings diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 258f74ee..71486701 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -28,7 +28,6 @@ class ToolbarModel; class XournalView; class MainWindowToolbarMenu; - class MainWindow: public GladeGui, public LayerCtrlListener { public: MainWindow(GladeSearchpath* gladeSearchPath, Control* control); @@ -104,6 +103,8 @@ public: */ void setTouchscreenScrollingForDeviceMapping(); + void rebindMenubarAccelerators(); + private: void initXournalWidget(); @@ -114,7 +115,10 @@ private: static void toggleMenuBar(MainWindow* win); void createToolbarAndMenu(); - + static void rebindAcceleratorsMenuItem(GtkWidget* widget, gpointer user_data); + static void rebindAcceleratorsSubMenu(GtkWidget* widget, gpointer user_data); + static gboolean isKeyForClosure(GtkAccelKey* key, GClosure* closure, gpointer data); + static gboolean invokeMenu(GtkWidget* widget); static void buttonCloseSidebarClicked(GtkButton* button, MainWindow* win); @@ -171,9 +175,5 @@ private: GtkWidget** toolbarWidgets; MainWindowToolbarMenu* toolbarSelectMenu; - - /** - * Workaround for double hide menubar event - */ - bool ignoreNextHideEvent; + GtkAccelGroup* globalAccelGroup; }; diff --git a/src/gui/XournalView.cpp b/src/gui/XournalView.cpp index 7d2e99eb..b69abf1b 100644 --- a/src/gui/XournalView.cpp +++ b/src/gui/XournalView.cpp @@ -136,7 +136,7 @@ auto XournalView::onKeyPressEvent(GdkEventKey* event) -> bool { } // Esc leaves fullscreen mode - if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_F11) { + if (event->keyval == GDK_KEY_Escape) { if (control->isFullscreen()) { control->setFullscreen(false); return true;