From 221b330c4a21d2421f2c2d6de1570e8ea2c09d16 Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Sun, 18 May 2014 09:56:23 +0200 Subject: [PATCH 01/12] fix a memory leak --- appshell/appshell_extensions_gtk.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 4a3d58e45..86d4fa408 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -652,21 +652,26 @@ int32 GetPendingFilesToOpen(ExtensionString& files) { } -GtkWidget* GetMenuBar(CefRefPtr browser) +static GtkWidget* GetMenuBar(CefRefPtr browser) { GtkWidget* window = (GtkWidget*)getMenuParent(browser); GtkWidget* widget; GList *children, *iter; + GtkWidget* menuBar = NULL; children = gtk_container_get_children(GTK_CONTAINER(window)); for(iter = children; iter != NULL; iter = g_list_next(iter)) { widget = (GtkWidget*)iter->data; - if (GTK_IS_MENU_BAR(widget)) - return widget; + if (GTK_IS_MENU_BAR(widget)) { + menuBar = widget; + break; + } } - return NULL; + g_list_free(children); + + return menuBar; } int32 AddMenu(CefRefPtr browser, ExtensionString title, ExtensionString command, From 2216c01e7abc7d639eb4d7e91ddaa38e2806e2ba Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Sun, 18 May 2014 10:16:00 +0200 Subject: [PATCH 02/12] linux-native-menus: implement separators --- appshell/appshell_extensions_gtk.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 86d4fa408..d4874b448 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -704,7 +704,11 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, ExtensionString command, ExtensionString key, ExtensionString displayStr, ExtensionString position, ExtensionString relativeId) { - GtkWidget* entry = gtk_menu_item_new_with_label(itemTitle.c_str()); + GtkWidget* entry; + if (itemTitle == "---") + entry = gtk_separator_menu_item_new(); + else + entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", FakeCallback, NULL); // FIXME add lookup for menu widgets gtk_menu_shell_append(GTK_MENU_SHELL(_menuWidget), entry); From 83f374871810eb5ac9f2797899961f8652274f0a Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Sun, 18 May 2014 10:49:40 +0200 Subject: [PATCH 03/12] linux-native-menus: use the native menu model --- appshell/appshell_extensions_gtk.cpp | 39 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index d4874b448..fbfe57359 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -26,7 +26,7 @@ #include #include #include "appshell_extensions.h" -#include "appshell_extensions_platform.h" +#include "native_menu_model.h" #include "client_handler.h" #include @@ -37,8 +37,6 @@ #include #include -GtkWidget* _menuWidget; - // Supported browsers (order matters): // - google-chorme // - chromium-browser - chromium executable name (in ubuntu) @@ -677,22 +675,21 @@ static GtkWidget* GetMenuBar(CefRefPtr browser) int32 AddMenu(CefRefPtr browser, ExtensionString title, ExtensionString command, ExtensionString position, ExtensionString relativeId) { - // if (tag == kTagNotFound) { - // tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, ExtensionString()); - // } else { - // // menu already there - // return NO_ERROR; - // } + int tag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(command); + if (tag == kTagNotFound) { + tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, ExtensionString()); + } else { + // menu is already there + return NO_ERROR; + } GtkWidget* menuBar = GetMenuBar(browser); GtkWidget* menuWidget = gtk_menu_new(); GtkWidget* menuHeader = gtk_menu_item_new_with_label(title.c_str()); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuHeader), menuWidget); + NativeMenuModel::getInstance(getMenuParent(browser)).setOsItem(tag, menuHeader); gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuHeader); gtk_widget_show(menuHeader); - - // FIXME add lookup for menu widgets - _menuWidget = menuWidget; return NO_ERROR; } @@ -704,14 +701,28 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, ExtensionString command, ExtensionString key, ExtensionString displayStr, ExtensionString position, ExtensionString relativeId) { + int parentTag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(parentCommand); + if (parentTag == kTagNotFound) { + return ERR_NOT_FOUND; + } + + int tag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(command); + if (tag == kTagNotFound) { + tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, parentCommand); + } else { + return NO_ERROR; + } + GtkWidget* entry; if (itemTitle == "---") entry = gtk_separator_menu_item_new(); else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", FakeCallback, NULL); - // FIXME add lookup for menu widgets - gtk_menu_shell_append(GTK_MENU_SHELL(_menuWidget), entry); + NativeMenuModel::getInstance(getMenuParent(browser)).setOsItem(tag, entry); + GtkWidget* menuHeader = (GtkWidget*) NativeMenuModel::getInstance(getMenuParent(browser)).getOsItem(parentTag); + GtkWidget* menuWidget = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuHeader)); + gtk_menu_shell_append(GTK_MENU_SHELL(menuWidget), entry); gtk_widget_show(entry); return NO_ERROR; From c47819fb3d39ae3fe175f89eb361c4df712e6621 Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Sun, 18 May 2014 13:42:03 +0200 Subject: [PATCH 04/12] linux-native-menus: implement the callback --- appshell/appshell_extensions_gtk.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index fbfe57359..92dde66ad 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -37,6 +37,8 @@ #include #include +extern CefRefPtr g_handler; + // Supported browsers (order matters): // - google-chorme // - chromium-browser - chromium executable name (in ubuntu) @@ -694,7 +696,13 @@ int32 AddMenu(CefRefPtr browser, ExtensionString title, ExtensionStr return NO_ERROR; } -void FakeCallback() { +static void Callback(GtkMenuItem* menuItem, gpointer userData) { + if (g_handler.get() && g_handler->GetBrowserId()) { + int tag = GPOINTER_TO_INT(userData); + ExtensionString commandId = NativeMenuModel::getInstance(getMenuParent(g_handler->GetBrowser())).getCommandId(tag); + CefRefPtr callback = new EditCommandCallback(g_handler->GetBrowser(), commandId); + g_handler->SendJSCommand(g_handler->GetBrowser(), commandId, callback); + } } int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, ExtensionString itemTitle, @@ -718,7 +726,7 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, entry = gtk_separator_menu_item_new(); else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); - g_signal_connect(entry, "activate", FakeCallback, NULL); + g_signal_connect(entry, "activate", G_CALLBACK(Callback), GINT_TO_POINTER(tag)); NativeMenuModel::getInstance(getMenuParent(browser)).setOsItem(tag, entry); GtkWidget* menuHeader = (GtkWidget*) NativeMenuModel::getInstance(getMenuParent(browser)).getOsItem(parentTag); GtkWidget* menuWidget = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuHeader)); From 04f56c737516695a44c1be5c65a47d119436086d Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Mon, 19 May 2014 19:50:03 +0200 Subject: [PATCH 05/12] linux-native-menus: position the items correctly --- appshell/appshell_extensions_gtk.cpp | 82 ++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 92dde66ad..3ff23b97c 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -674,12 +674,61 @@ static GtkWidget* GetMenuBar(CefRefPtr browser) return menuBar; } +static int GetPosition(const ExtensionString& positionString, const ExtensionString& relativeId, + GtkWidget* container, NativeMenuModel& model) +{ + if (positionString == "" || positionString == "last") + return -1; + else if (positionString == "first") + return 0; + else if (relativeId.size() > 0) { + int relativeTag = model.getTag(relativeId); + GtkWidget* relativeMenuItem = (GtkWidget*) model.getOsItem(relativeTag); + int position = 0; + GList* children = gtk_container_get_children(GTK_CONTAINER(container)); + GList* iter; + for (iter = children; iter != NULL; iter = g_list_next(iter)) { + if (iter->data == relativeMenuItem) + break; + position++; + } + if (iter == NULL) + position = -1; + else if (positionString == "before") + ; + else if (positionString == "after") + position++; + else if (positionString == "firstInSection") { + for (; iter != NULL; iter = g_list_previous(iter)) { + if (GTK_IS_SEPARATOR_MENU_ITEM(iter->data)) + break; + position--; + } + position++; + } + else if (positionString == "lastInSection") { + for (; iter != NULL; iter = g_list_next(iter)) { + if (GTK_IS_SEPARATOR_MENU_ITEM(iter->data)) + break; + position++; + } + } + else + position = -1; + g_list_free(children); + return position; + } + else + return -1; +} + int32 AddMenu(CefRefPtr browser, ExtensionString title, ExtensionString command, - ExtensionString position, ExtensionString relativeId) + ExtensionString positionString, ExtensionString relativeId) { - int tag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(command); + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int tag = model.getTag(command); if (tag == kTagNotFound) { - tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, ExtensionString()); + tag = model.getOrCreateTag(command, ExtensionString()); } else { // menu is already there return NO_ERROR; @@ -689,8 +738,12 @@ int32 AddMenu(CefRefPtr browser, ExtensionString title, ExtensionStr GtkWidget* menuWidget = gtk_menu_new(); GtkWidget* menuHeader = gtk_menu_item_new_with_label(title.c_str()); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuHeader), menuWidget); - NativeMenuModel::getInstance(getMenuParent(browser)).setOsItem(tag, menuHeader); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuHeader); + model.setOsItem(tag, menuHeader); + int position = GetPosition(positionString, relativeId, menuBar, model); + if (position >= 0) + gtk_menu_shell_insert(GTK_MENU_SHELL(menuBar), menuHeader, position); + else + gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuHeader); gtk_widget_show(menuHeader); return NO_ERROR; @@ -707,16 +760,17 @@ static void Callback(GtkMenuItem* menuItem, gpointer userData) { int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, ExtensionString itemTitle, ExtensionString command, ExtensionString key, ExtensionString displayStr, - ExtensionString position, ExtensionString relativeId) + ExtensionString positionString, ExtensionString relativeId) { - int parentTag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(parentCommand); + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int parentTag = model.getTag(parentCommand); if (parentTag == kTagNotFound) { return ERR_NOT_FOUND; } - int tag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(command); + int tag = model.getTag(command); if (tag == kTagNotFound) { - tag = NativeMenuModel::getInstance(getMenuParent(browser)).getOrCreateTag(command, parentCommand); + tag = model.getOrCreateTag(command, parentCommand); } else { return NO_ERROR; } @@ -727,10 +781,14 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", G_CALLBACK(Callback), GINT_TO_POINTER(tag)); - NativeMenuModel::getInstance(getMenuParent(browser)).setOsItem(tag, entry); - GtkWidget* menuHeader = (GtkWidget*) NativeMenuModel::getInstance(getMenuParent(browser)).getOsItem(parentTag); + model.setOsItem(tag, entry); + GtkWidget* menuHeader = (GtkWidget*) model.getOsItem(parentTag); GtkWidget* menuWidget = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuHeader)); - gtk_menu_shell_append(GTK_MENU_SHELL(menuWidget), entry); + int position = GetPosition(positionString, relativeId, menuWidget, model); + if (position >= 0) + gtk_menu_shell_insert(GTK_MENU_SHELL(menuWidget), entry, position); + else + gtk_menu_shell_append(GTK_MENU_SHELL(menuWidget), entry); gtk_widget_show(entry); return NO_ERROR; From 6c09c32975ce031659cc34578570b2129788c8b8 Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Sun, 25 May 2014 08:51:01 +0200 Subject: [PATCH 06/12] linux-native-menus: implement some more functions --- appshell/appshell_extensions_gtk.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 3ff23b97c..09f87f8f0 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -796,11 +796,19 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, int32 RemoveMenu(CefRefPtr browser, const ExtensionString& commandId) { - return NO_ERROR; + // works for menu and menu item + return RemoveMenuItem(browser, commandId); } int32 RemoveMenuItem(CefRefPtr browser, const ExtensionString& commandId) { + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int tag = model.getTag(commandId); + if (tag == kTagNotFound) + return ERR_NOT_FOUND; + GtkWidget* menuItem = (GtkWidget*) model.getOsItem(tag); + model.removeMenuItem(commandId); + gtk_widget_destroy(menuItem); return NO_ERROR; } @@ -811,11 +819,23 @@ int32 GetMenuItemState(CefRefPtr browser, ExtensionString commandId, int32 SetMenuTitle(CefRefPtr browser, ExtensionString commandId, ExtensionString menuTitle) { + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int tag = model.getTag(commandId); + if (tag == kTagNotFound) + return ERR_NOT_FOUND; + GtkWidget* menuItem = (GtkWidget*) model.getOsItem(tag); + gtk_menu_item_set_label(GTK_MENU_ITEM(menuItem), menuTitle.c_str()); return NO_ERROR; } int32 GetMenuTitle(CefRefPtr browser, ExtensionString commandId, ExtensionString& menuTitle) { + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int tag = model.getTag(commandId); + if (tag == kTagNotFound) + return ERR_NOT_FOUND; + GtkWidget* menuItem = (GtkWidget*) model.getOsItem(tag); + menuTitle = gtk_menu_item_get_label(GTK_MENU_ITEM(menuItem)); return NO_ERROR; } From 2f15dfdd4fc517ff1479b26c1f79181d764856a7 Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Thu, 20 Apr 2017 16:45:48 +0530 Subject: [PATCH 07/12] Added support of native menu shortcuts in Linux --- appshell/appshell_extensions_gtk.cpp | 117 +++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 09f87f8f0..21f6847a4 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -36,6 +36,10 @@ #include #include #include +#include +#include +#include +#include extern CefRefPtr g_handler; @@ -758,6 +762,92 @@ static void Callback(GtkMenuItem* menuItem, gpointer userData) { } } + +ExtensionString GetDisplayKeyString(const ExtensionString& keyStr) +{ + ExtensionString result = keyStr; + + // We get a keyStr that looks like "Ctrl-O", which is the format we + // need for the accelerator table. For displaying in the menu, though, + // we have to change it to "Ctrl+O". Careful not to change the final + // character, though, so "Ctrl--" ends up as "Ctrl+-". + if (result.size() > 0) { + replace(result.begin(), result.end() - 1, '-', '+'); + } + return result; +} + + +int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionString& key, GdkModifierType* modifier, guint* keyVal, ExtensionString& commandId) { + if (key.size()) { + GtkAccelGroup *accel_group = NULL; + accel_group = gtk_accel_group_new(); + + std::vector tokens; + std::istringstream f(key.c_str()); + std::string s; + while (getline(f, s, '-')) { + tokens.push_back(s); + } + std::string shortcut = ""; + // convert shortcut format + // e.g. Ctrl+A converts to A whose entry is stored in accelerator table + for (int i=0;i browser, ExtensionString parentCommand, ExtensionString itemTitle, ExtensionString command, ExtensionString key, ExtensionString displayStr, ExtensionString positionString, ExtensionString relativeId) @@ -781,7 +871,11 @@ int32 AddMenuItem(CefRefPtr browser, ExtensionString parentCommand, else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", G_CALLBACK(Callback), GINT_TO_POINTER(tag)); + GdkModifierType modifier = GdkModifierType(0); + guint keyVal = 0; + ExtensionString commandId = model.getCommandId(tag); model.setOsItem(tag, entry); + ParseShortcut(browser, entry, key, &modifier, &keyVal, commandId); GtkWidget* menuHeader = (GtkWidget*) model.getOsItem(parentTag); GtkWidget* menuWidget = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuHeader)); int position = GetPosition(positionString, relativeId, menuWidget, model); @@ -824,6 +918,19 @@ int32 SetMenuTitle(CefRefPtr browser, ExtensionString commandId, Ext if (tag == kTagNotFound) return ERR_NOT_FOUND; GtkWidget* menuItem = (GtkWidget*) model.getOsItem(tag); + ExtensionString shortcut; + GetMenuTitle(browser, commandId, shortcut); + size_t pos = shortcut.find("\t"); + if (pos != -1) { + shortcut = shortcut.substr(pos); + } else { + shortcut = ""; + } + + ExtensionString newTitle = menuTitle; + if (shortcut.length() > 0) { + newTitle += shortcut; + } gtk_menu_item_set_label(GTK_MENU_ITEM(menuItem), menuTitle.c_str()); return NO_ERROR; } @@ -841,6 +948,16 @@ int32 GetMenuTitle(CefRefPtr browser, ExtensionString commandId, Ext int32 SetMenuItemShortcut(CefRefPtr browser, ExtensionString commandId, ExtensionString shortcut, ExtensionString displayStr) { + NativeMenuModel model = NativeMenuModel::getInstance(getMenuParent(browser)); + int32 tag = model.getTag(commandId); + if (tag == kTagNotFound) { + return ERR_NOT_FOUND; + } + GtkWidget* entry = (GtkWidget*) model.getOsItem(tag); + GdkModifierType modifier = GdkModifierType(0); + guint keyVal = 0; + ParseShortcut(browser, entry, shortcut, &modifier, &keyVal, commandId); + return NO_ERROR; } From ff6abd46c8346c47afa82d03bc50dee8cf11e367 Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Mon, 24 Apr 2017 18:35:25 +0530 Subject: [PATCH 08/12] Addressed review comments --- appshell/appshell_extensions_gtk.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 21f6847a4..3515eb7de 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -778,13 +778,13 @@ ExtensionString GetDisplayKeyString(const ExtensionString& keyStr) } -int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionString& key, GdkModifierType* modifier, guint* keyVal, ExtensionString& commandId) { +static int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionString& key, GdkModifierType* modifier, guint* keyVal, ExtensionString& commandId) { if (key.size()) { GtkAccelGroup *accel_group = NULL; accel_group = gtk_accel_group_new(); std::vector tokens; - std::istringstream f(key.c_str()); + std::istringstream f(key); std::string s; while (getline(f, s, '-')) { tokens.push_back(s); @@ -802,7 +802,7 @@ int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionSt } } gchar* val = (gchar*)shortcut.c_str(); - gtk_accelerator_parse (val, keyVal, modifier); + gtk_accelerator_parse(val, keyVal, modifier); // Fallback if (!(*keyVal)) { @@ -829,7 +829,7 @@ int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionSt *keyVal = GDK_KEY_Page_Up; } else if (tokens[i] == "PageDown") { *keyVal = GDK_KEY_Page_Down; - } else if (tokens[i] == "[" || tokens[i] == "]" || tokens[i] == "+" || tokens[i] == "." || tokens[i] == "," || tokens[i] == "\\") { + } else if (tokens[i] == "[" || tokens[i] == "]" || tokens[i] == "+" || tokens[i] == "." || tokens[i] == "," || tokens[i] == "\\" || tokens[i] == "/" || tokens[i] == "`") { *keyVal = tokens[i][0]; } else if (tokens[i] == "−") { *keyVal = GDK_KEY_minus; @@ -839,9 +839,12 @@ int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionSt if (*keyVal) { gtk_widget_add_accelerator(entry, "activate", accel_group, *keyVal, *modifier, GTK_ACCEL_VISIBLE); } else if (shortcut.size()) { + // If fallback also fails, then + // we append the shorcut to menu title + // e.g. MENU_TITLE (Ctrl + A) ExtensionString menuTitle; GetMenuTitle(browser, commandId, menuTitle); - menuTitle += "\t( " + shortcut + " )"; + menuTitle += "\t( " + GetDisplayKeyString(key) + " )"; gtk_menu_item_set_label(GTK_MENU_ITEM(entry), menuTitle.c_str()); } } @@ -931,7 +934,7 @@ int32 SetMenuTitle(CefRefPtr browser, ExtensionString commandId, Ext if (shortcut.length() > 0) { newTitle += shortcut; } - gtk_menu_item_set_label(GTK_MENU_ITEM(menuItem), menuTitle.c_str()); + gtk_menu_item_set_label(GTK_MENU_ITEM(menuItem), newTitle.c_str()); return NO_ERROR; } From 0f6700072eaf17a59d32ab447efb0a770186ef10 Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Tue, 25 Apr 2017 00:47:50 +0530 Subject: [PATCH 09/12] Added functionality of enabling and disabling menu items --- appshell/appshell_extensions.cpp | 3 +++ appshell/appshell_extensions_gtk.cpp | 16 +++++++++++++++- appshell/appshell_extensions_mac.mm | 5 +++++ appshell/appshell_extensions_platform.h | 2 ++ appshell/appshell_extensions_win.cpp | 5 +++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/appshell/appshell_extensions.cpp b/appshell/appshell_extensions.cpp index 925c5305e..0cc899bb6 100644 --- a/appshell/appshell_extensions.cpp +++ b/appshell/appshell_extensions.cpp @@ -606,6 +606,9 @@ class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate { bool enabled = argList->GetBool(2); bool checked = argList->GetBool(3); error = NativeMenuModel::getInstance(getMenuParent(browser)).setMenuItemState(command, enabled, checked); + if (error == NO_ERROR) { + error = SetMenuItemState(browser, command, enabled, checked); + } } } else if (message_name == "SetMenuTitle") { // Parameters: diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 3515eb7de..ec9c86b9f 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -40,6 +40,7 @@ #include #include #include +#include extern CefRefPtr g_handler; @@ -763,7 +764,7 @@ static void Callback(GtkMenuItem* menuItem, gpointer userData) { } -ExtensionString GetDisplayKeyString(const ExtensionString& keyStr) +static ExtensionString GetDisplayKeyString(const ExtensionString& keyStr) { ExtensionString result = keyStr; @@ -914,6 +915,19 @@ int32 GetMenuItemState(CefRefPtr browser, ExtensionString commandId, return NO_ERROR; } +int32 SetMenuItemState(CefRefPtr browser, ExtensionString command, bool& enabled, bool& checked) +{ + // TODO: Implement functionality for checked + NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); + int tag = model.getTag(command); + if (tag == kTagNotFound) { + return ERR_NOT_FOUND; + } + GtkWidget* menuItem = (GtkWidget*) model.getOsItem(tag); + gtk_widget_set_sensitive(menuItem, enabled); + return NO_ERROR; +} + int32 SetMenuTitle(CefRefPtr browser, ExtensionString commandId, ExtensionString menuTitle) { NativeMenuModel& model = NativeMenuModel::getInstance(getMenuParent(browser)); diff --git a/appshell/appshell_extensions_mac.mm b/appshell/appshell_extensions_mac.mm index 53cefc5ee..02732eb9b 100644 --- a/appshell/appshell_extensions_mac.mm +++ b/appshell/appshell_extensions_mac.mm @@ -1137,6 +1137,11 @@ int32 GetMenuItemState(CefRefPtr browser, ExtensionString commandId, return NO_ERROR; } +int32 SetMenuItemState(CefRefPtr browser, ExtensionString command, bool& enabled, bool& checked) +{ + return NO_ERROR; +} + int32 SetMenuTitle(CefRefPtr browser, ExtensionString command, ExtensionString itemTitle) { NSString* itemTitleStr = [[[NSString alloc] initWithUTF8String:itemTitle.c_str()] autorelease]; int32 tag = NativeMenuModel::getInstance(getMenuParent(browser)).getTag(command); diff --git a/appshell/appshell_extensions_platform.h b/appshell/appshell_extensions_platform.h index 518755399..c50c881aa 100644 --- a/appshell/appshell_extensions_platform.h +++ b/appshell/appshell_extensions_platform.h @@ -135,6 +135,8 @@ int32 RemoveMenuItem(CefRefPtr browser, const ExtensionString& comma int32 GetMenuItemState(CefRefPtr browser, ExtensionString commandId, bool& enabled, bool& checked, int& index); +int32 SetMenuItemState(CefRefPtr browser, ExtensionString command, bool& enabled, bool& checked); + int32 SetMenuTitle(CefRefPtr browser, ExtensionString commandId, ExtensionString menuTitle); int32 GetMenuTitle(CefRefPtr browser, ExtensionString commandId, ExtensionString& menuTitle); diff --git a/appshell/appshell_extensions_win.cpp b/appshell/appshell_extensions_win.cpp index 5b3070ee3..2c8c9bb9f 100644 --- a/appshell/appshell_extensions_win.cpp +++ b/appshell/appshell_extensions_win.cpp @@ -1818,6 +1818,11 @@ int GetMenuItemPosition(HMENU hMenu, UINT commandID) return -1; } +int32 SetMenuItemState(CefRefPtr browser, ExtensionString command, bool& enabled, bool& checked) +{ + return NO_ERROR; +} + int32 SetMenuTitle(CefRefPtr browser, ExtensionString command, ExtensionString itemTitle) { static WCHAR titleBuf[MAX_LOADSTRING]; From 98ccf5b2eb8ab278cfd3e911c915df1e539e2aea Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Tue, 25 Apr 2017 14:48:27 +0530 Subject: [PATCH 10/12] Code Cleanup --- appshell/appshell_extensions_gtk.cpp | 47 +++++++++++++--------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index ec9c86b9f..80e00311a 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -779,8 +779,10 @@ static ExtensionString GetDisplayKeyString(const ExtensionString& keyStr) } -static int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionString& key, GdkModifierType* modifier, guint* keyVal, ExtensionString& commandId) { +static int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, ExtensionString& key, ExtensionString& commandId) { if (key.size()) { + GdkModifierType modifier = GdkModifierType(0); + guint keyVal = 0; GtkAccelGroup *accel_group = NULL; accel_group = gtk_accel_group_new(); @@ -803,42 +805,42 @@ static int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, Exte } } gchar* val = (gchar*)shortcut.c_str(); - gtk_accelerator_parse(val, keyVal, modifier); + gtk_accelerator_parse(val, &keyVal, &modifier); // Fallback - if (!(*keyVal)) { + if (!(keyVal)) { for (int i=0;i browser, ExtensionString parentCommand, else entry = gtk_menu_item_new_with_label(itemTitle.c_str()); g_signal_connect(entry, "activate", G_CALLBACK(Callback), GINT_TO_POINTER(tag)); - GdkModifierType modifier = GdkModifierType(0); - guint keyVal = 0; ExtensionString commandId = model.getCommandId(tag); model.setOsItem(tag, entry); - ParseShortcut(browser, entry, key, &modifier, &keyVal, commandId); + ParseShortcut(browser, entry, key, commandId); GtkWidget* menuHeader = (GtkWidget*) model.getOsItem(parentTag); GtkWidget* menuWidget = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuHeader)); int position = GetPosition(positionString, relativeId, menuWidget, model); @@ -971,10 +971,7 @@ int32 SetMenuItemShortcut(CefRefPtr browser, ExtensionString command return ERR_NOT_FOUND; } GtkWidget* entry = (GtkWidget*) model.getOsItem(tag); - GdkModifierType modifier = GdkModifierType(0); - guint keyVal = 0; - ParseShortcut(browser, entry, shortcut, &modifier, &keyVal, commandId); - + ParseShortcut(browser, entry, shortcut, commandId); return NO_ERROR; } From 1524d7beb1e2b4bde2b3f21ce56a313ecba80840 Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Thu, 27 Apr 2017 14:10:37 +0530 Subject: [PATCH 11/12] Addressed review comment --- appshell/appshell_extensions_gtk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 80e00311a..0443ff392 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -686,7 +686,7 @@ static int GetPosition(const ExtensionString& positionString, const ExtensionStr return -1; else if (positionString == "first") return 0; - else if (relativeId.size() > 0) { + else if (!relativeId.empty()) { int relativeTag = model.getTag(relativeId); GtkWidget* relativeMenuItem = (GtkWidget*) model.getOsItem(relativeTag); int position = 0; From 0ecc5c8e653ba6f1c24a3e32d2fd34edc0ee0a2b Mon Sep 17 00:00:00 2001 From: Saurabh Kathpalia Date: Tue, 2 May 2017 22:54:53 +0530 Subject: [PATCH 12/12] Addressed review comments --- appshell/appshell_extensions_gtk.cpp | 62 ++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/appshell/appshell_extensions_gtk.cpp b/appshell/appshell_extensions_gtk.cpp index 0443ff392..4bddea458 100644 --- a/appshell/appshell_extensions_gtk.cpp +++ b/appshell/appshell_extensions_gtk.cpp @@ -42,6 +42,33 @@ #include #include +// Modifiers +#define MODIFIER_CONTROL "Ctrl" +#define MODIFIER_ALT "Alt" +#define MODIFIER_SHIFT "Shift" + +// Keys +#define KEY_ENTER "Enter" +#define KEY_UP_ARROW "Up" +#define KEY_UNICODE_UP_ARROW "\u2191" +#define KEY_DOWN_ARROW "Down" +#define KEY_UNICODE_DOWN_ARROW "\u2193" +#define KEY_RIGHT_ARROW "Right" +#define KEY_LEFT_ARROW "Left" +#define KEY_SPACE "Space" +#define KEY_PAGE_UP "PageUp" +#define KEY_PAGE_DOWN "PageDown" +#define KEY_OPEN_SQUARE_BRACE "[" +#define KEY_CLOSE_SQUARE_BRACE "]" +#define KEY_PLUS "+" +#define KEY_MINUS "−" +#define KEY_DOT "." +#define KEY_BACK_SLASH "\\" +#define KEY_SLASH "/" +#define KEY_BACK_QUOTE "`" +#define KEY_COMMA "," + + extern CefRefPtr g_handler; // Supported browsers (order matters): @@ -795,12 +822,13 @@ static int32 ParseShortcut(CefRefPtr browser, GtkWidget* entry, Exte std::string shortcut = ""; // convert shortcut format // e.g. Ctrl+A converts to A whose entry is stored in accelerator table - for (int i=0;i browser, GtkWidget* entry, Exte // Fallback if (!(keyVal)) { - for (int i=0;i