## Description: add some description ## Origin/Author: add some origin or author ## Bug: bug URL Index: gtk+2.0-2.24.0/gtk/Makefile.am =================================================================== --- gtk+2.0-2.24.0.orig/gtk/Makefile.am 2011-02-15 18:15:00.848117002 +0100 +++ gtk+2.0-2.24.0/gtk/Makefile.am 2011-02-15 18:15:01.078117002 +0100 @@ -249,6 +249,8 @@ gtkmenu.h \ gtkmenubar.h \ gtkmenuitem.h \ + ubuntumenuproxy.h \ + ubuntumenuproxymodule.h \ gtkmenushell.h \ gtkmenutoolbutton.h \ gtkmessagedialog.h \ @@ -519,6 +521,8 @@ gtkmenu.c \ gtkmenubar.c \ gtkmenuitem.c \ + ubuntumenuproxy.c \ + ubuntumenuproxymodule.c \ gtkmenushell.c \ gtkmenutoolbutton.c \ gtkmessagedialog.c \ Index: gtk+2.0-2.24.0/gtk/gtk.h =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtk.h 2011-02-15 18:14:58.878117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtk.h 2011-02-15 18:15:01.078117002 +0100 @@ -65,6 +65,8 @@ #include #include #include +#include +#include #include #include #include Index: gtk+2.0-2.24.0/gtk/gtk.symbols =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtk.symbols 2011-02-15 18:15:00.918117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtk.symbols 2011-02-15 18:15:01.078117002 +0100 @@ -2606,6 +2606,21 @@ #endif #endif +#if IN_HEADER(__UBUNTU_MENU_PROXY_H__) +#if IN_FILE(__UBUNTU_MENU_PROXY_C__) +ubuntu_menu_proxy_get_type G_GNUC_CONST +ubuntu_menu_proxy_get +ubuntu_menu_proxy_insert +#endif +#endif + +#if IN_HEADER(__UBUNTU_MENU_PROXY_MODULE_H__) +#if IN_FILE(__UBUNTU_MENU_PROXY_MODULE_C__) +ubuntu_menu_proxy_module_get_type +ubuntu_menu_proxy_module_get +#endif +#endif + #if IN_HEADER(__GTK_MENU_SHELL_H__) #if IN_FILE(__GTK_MENU_SHELL_C__) gtk_menu_shell_activate_item @@ -2620,6 +2635,7 @@ gtk_menu_shell_select_item gtk_menu_shell_set_take_focus gtk_menu_shell_get_take_focus +ubuntu_gtk_menu_shell_activate_mnemonic #endif #endif Index: gtk+2.0-2.24.0/gtk/gtkmenubar.c =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtkmenubar.c 2011-02-15 18:14:58.978117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtkmenubar.c 2011-02-15 18:18:20.688117002 +0100 @@ -55,6 +55,9 @@ { GtkPackDirection pack_direction; GtkPackDirection child_pack_direction; + + gboolean show; + gboolean local_notify; }; #define GTK_MENU_BAR_GET_PRIVATE(o) \ @@ -73,6 +76,8 @@ GtkRequisition *requisition); static void gtk_menu_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static void gtk_menu_bar_hide (GtkWidget *widget); +static void gtk_menu_bar_show (GtkWidget *widget); static void gtk_menu_bar_paint (GtkWidget *widget, GdkRectangle *area); static gint gtk_menu_bar_expose (GtkWidget *widget, @@ -105,9 +110,11 @@ widget_class->size_request = gtk_menu_bar_size_request; widget_class->size_allocate = gtk_menu_bar_size_allocate; + widget_class->hide = gtk_menu_bar_hide; + widget_class->show = gtk_menu_bar_show; widget_class->expose_event = gtk_menu_bar_expose; widget_class->hierarchy_changed = gtk_menu_bar_hierarchy_changed; - + menu_shell_class->submenu_placement = GTK_TOP_BOTTOM; menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay; menu_shell_class->move_current = gtk_menu_bar_move_current; @@ -218,8 +225,46 @@ } static void +local_notify (GtkWidget *widget, + GParamSpec *pspec, + gpointer user_data) +{ + GtkMenuBarPrivate *priv; + gboolean local; + + priv = GTK_MENU_BAR_GET_PRIVATE (widget); + + g_object_get (widget, + "ubuntu-local", &local, + NULL); + + priv->local_notify = TRUE; + + if (local) + { + if (priv->show) + gtk_widget_show (widget); + } + else + gtk_widget_hide (widget); + + priv->local_notify = FALSE; +} + +static void gtk_menu_bar_init (GtkMenuBar *object) { + GtkMenuBarPrivate *priv; + + priv = GTK_MENU_BAR_GET_PRIVATE (object); + + priv->show = FALSE; + priv->local_notify = FALSE; + + g_signal_connect (object, + "notify::ubuntu-local", + G_CALLBACK (local_notify), + NULL); } GtkWidget* @@ -290,7 +335,7 @@ requisition->width = 0; requisition->height = 0; - + if (gtk_widget_get_visible (widget)) { menu_bar = GTK_MENU_BAR (widget); @@ -504,6 +549,47 @@ } static void +gtk_menu_bar_hide (GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_MENU_BAR (widget)); + + GtkMenuBarPrivate *priv; + gboolean local; + + priv = GTK_MENU_BAR_GET_PRIVATE (widget); + + g_object_get (widget, + "ubuntu-local", &local, + NULL); + + if (!priv->local_notify) + priv->show = FALSE; + + GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->hide (widget); +} + +static void +gtk_menu_bar_show (GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_MENU_BAR (widget)); + + GtkMenuBarPrivate *priv; + gboolean local; + + priv = GTK_MENU_BAR_GET_PRIVATE (widget); + + g_object_get (widget, + "ubuntu-local", &local, + NULL); + + if (!priv->local_notify) + priv->show = TRUE; + + if (local == NULL || local) + GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->show (widget); +} + +static void gtk_menu_bar_paint (GtkWidget *widget, GdkRectangle *area) { @@ -626,8 +712,15 @@ GtkMenuShell *menu_shell = GTK_MENU_SHELL (menubars->data); _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE); - _gtk_menu_shell_activate (menu_shell); - gtk_menu_shell_select_first (menu_shell, FALSE); + if (ubuntu_gtk_menu_shell_activate_first (GTK_MENU_SHELL (menu_shell), FALSE)) + { + //g_print ("send activate to remote!\n"); + } + else + { + _gtk_menu_shell_activate (menu_shell); + gtk_menu_shell_select_first (menu_shell, FALSE); + } g_list_free (menubars); Index: gtk+2.0-2.24.0/gtk/gtkmenushell.c =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtkmenushell.c 2011-02-15 18:14:58.928117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtkmenushell.c 2011-02-15 18:15:01.088117002 +0100 @@ -37,6 +37,7 @@ #include "gtkmenubar.h" #include "gtkmenuitem.h" #include "gtkmenushell.h" +#include "ubuntumenuproxy.h" #include "gtkmnemonichash.h" #include "gtktearoffmenuitem.h" #include "gtkwindow.h" @@ -64,7 +65,8 @@ enum { PROP_0, - PROP_TAKE_FOCUS + PROP_TAKE_FOCUS, + PROP_LOCAL }; /* Terminology: @@ -135,6 +137,9 @@ GtkMnemonicHash *mnemonic_hash; GtkKeyHash *key_hash; + UbuntuMenuProxy *proxy; + gboolean local; + guint take_focus : 1; guint activated_submenu : 1; /* This flag is a crutch to keep mnemonics in the same menu @@ -381,6 +386,14 @@ TRUE, GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_LOCAL, + g_param_spec_boolean ("ubuntu-local", + P_("Local menu"), + P_("Determines whether the menu is local"), + FALSE, + GTK_PARAM_READWRITE)); + g_type_class_add_private (object_class, sizeof (GtkMenuShellPrivate)); } @@ -391,6 +404,22 @@ } static void +show_local_notify (UbuntuMenuProxy *proxy, + GParamSpec *pspec, + GtkMenuShell *shell) +{ + gboolean local; + + g_object_get (proxy, + "show-local", &local, + NULL); + + g_object_set (shell, + "ubuntu-local", local, + NULL); +} + +static void gtk_menu_shell_init (GtkMenuShell *menu_shell) { GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell); @@ -408,6 +437,13 @@ priv->key_hash = NULL; priv->take_focus = TRUE; priv->activated_submenu = FALSE; + priv->proxy = ubuntu_menu_proxy_get (); + priv->local = FALSE; + + if (priv->proxy != NULL) + g_signal_connect (priv->proxy, "notify::show-local", + G_CALLBACK (show_local_notify), + menu_shell); } static void @@ -417,12 +453,16 @@ GParamSpec *pspec) { GtkMenuShell *menu_shell = GTK_MENU_SHELL (object); + GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (object); switch (prop_id) { case PROP_TAKE_FOCUS: gtk_menu_shell_set_take_focus (menu_shell, g_value_get_boolean (value)); break; + case PROP_LOCAL: + priv->local = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -436,12 +476,23 @@ GParamSpec *pspec) { GtkMenuShell *menu_shell = GTK_MENU_SHELL (object); + GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell); + gboolean local; switch (prop_id) { case PROP_TAKE_FOCUS: g_value_set_boolean (value, gtk_menu_shell_get_take_focus (menu_shell)); break; + case PROP_LOCAL: + if (priv->proxy == NULL) { + local = TRUE; + } else { + local = priv->local; + } + + g_value_set_boolean (value, local); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -454,6 +505,13 @@ GtkMenuShell *menu_shell = GTK_MENU_SHELL (object); GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell); + if (priv->proxy != NULL) + { + g_signal_handlers_disconnect_by_func (priv->proxy, + show_local_notify, + menu_shell); + } + if (priv->mnemonic_hash) _gtk_mnemonic_hash_free (priv->mnemonic_hash); if (priv->key_hash) @@ -483,14 +541,24 @@ gint position) { GtkMenuShellClass *class; + GtkMenuShellPrivate *priv; g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell)); g_return_if_fail (GTK_IS_MENU_ITEM (child)); class = GTK_MENU_SHELL_GET_CLASS (menu_shell); + priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell); + if (class->insert) class->insert (menu_shell, child, position); + + /* insert to proxy */ + if (priv->proxy != NULL) + ubuntu_menu_proxy_insert (priv->proxy, + GTK_WIDGET (menu_shell), + child, + position); } static void @@ -1815,5 +1883,52 @@ } } +gboolean +ubuntu_gtk_menu_shell_activate_mnemonic (GtkMenuShell *shell, GtkWidget *item) +{ + GtkMenuShellPrivate *priv; + + g_return_val_if_fail (GTK_IS_MENU_SHELL (shell), FALSE); + + priv = GTK_MENU_SHELL_GET_PRIVATE (shell); + + if (priv->proxy && !ubuntu_menu_proxy_show_local (priv->proxy)) + { + ubuntu_menu_proxy_activate_menu (priv->proxy, + item); + + return TRUE; + } + + return FALSE; +} + +gboolean +ubuntu_gtk_menu_shell_activate_first (GtkMenuShell *menu_shell, + gboolean search_sensitive) +{ + GtkWidget *to_select = NULL; + GList *tmp_list; + + tmp_list = menu_shell->children; + while (tmp_list) + { + GtkWidget *child = tmp_list->data; + + if ((!search_sensitive && gtk_widget_get_visible (child)) || + _gtk_menu_item_is_selectable (child)) + { + to_select = child; + if (!GTK_IS_TEAROFF_MENU_ITEM (child)) + break; + } + + tmp_list = tmp_list->next; + } + + return to_select && + ubuntu_gtk_menu_shell_activate_mnemonic(menu_shell, to_select); +} + #define __GTK_MENU_SHELL_C__ #include "gtkaliasdef.c" Index: gtk+2.0-2.24.0/gtk/tests/Makefile.am =================================================================== --- gtk+2.0-2.24.0.orig/gtk/tests/Makefile.am 2011-02-15 18:14:58.848117002 +0100 +++ gtk+2.0-2.24.0/gtk/tests/Makefile.am 2011-02-15 18:15:01.088117002 +0100 @@ -45,6 +45,10 @@ recentmanager_SOURCES = recentmanager.c recentmanager_LDADD = $(progs_ldadd) +TEST_PROGS += menuproxy +menuproxy_SOURCES = menuproxy.c +menuproxy_LDADD = $(progs_ldadd) + TEST_PROGS += floating floating_SOURCES = floating.c floating_LDADD = $(progs_ldadd) Index: gtk+2.0-2.24.0/gtk/tests/menuproxy.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+2.0-2.24.0/gtk/tests/menuproxy.c 2011-02-15 18:15:01.088117002 +0100 @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2009 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Cody Russell + */ + +#undef GTK_DISABLE_DEPRECATED +#include "../gtk/gtk.h" + +typedef struct _TestProxy TestProxy; +typedef struct _TestProxyClass TestProxyClass; + +//static GType test_proxy_type_id = 0; +//static TestProxyClass *test_proxy_parent_class = NULL; + +#define TEST_TYPE_PROXY (test_proxy_type_id) +#define TEST_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_PROXY, TestProxy)) +#define TEST_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TEST_TYPE_PROXY, TestProxyClass)) +#define TEST_IS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_PROXY)) + +struct _TestProxy +{ + UbuntuMenuProxy parent_object; +}; + +struct _TestProxyClass +{ + UbuntuMenuProxyClass parent_class; +}; + +static void test_proxy_insert (UbuntuMenuProxy *proxy, + GtkWidget *child, + guint position); + +G_DEFINE_DYNAMIC_TYPE(TestProxy, test_proxy, UBUNTU_TYPE_MENU_PROXY) + +static void +test_proxy_init (TestProxy *proxy) +{ +} + +static void +test_proxy_class_init (TestProxyClass *class) +{ + UbuntuMenuProxyClass *proxy_class = UBUNTU_MENU_PROXY_CLASS (class); + + test_proxy_parent_class = g_type_class_peek_parent (class); + + proxy_class->insert = test_proxy_insert; +} + +static void +test_proxy_class_finalize (TestProxyClass *class) +{ +} + +static void +test_proxy_insert (UbuntuMenuProxy *proxy, + GtkWidget *child, + guint position) +{ +} + +/* ---------------------------------------------------- */ + +#define TEST_TYPE_MODULE (test_module_get_type ()) +#define TEST_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_MODULE, TestModule)) +#define TEST_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TEST_TYPE_MODULE, TestModuleClass)) +#define TEST_IS_MODULE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_MODULE)) +#define TEST_IS_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TEST_TYPE_MODULE)) +#define TEST_MODULE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TEST_TYPE_MODULE, TestModuleClass)) + + +typedef struct _TestModule TestModule; +typedef struct _TestModuleClass TestModuleClass; + +struct _TestModule +{ + GTypeModule parent_instance; +}; + +struct _TestModuleClass +{ + GTypeModuleClass parent_class; +}; + +static gboolean +test_module_load (GTypeModule *module) +{ + g_print ("registering type...\n"); + g_print (" type_id = %d\n", test_proxy_type_id); + + test_proxy_register_type (G_TYPE_MODULE (module)); + + //test_proxy_get_type (G_TYPE_MODULE (module)); + + g_print (" type_id = %d\n", test_proxy_type_id); + + return TRUE; +} + +static void +test_module_unload (GTypeModule *module) +{ +} + +static void +test_module_class_init (TestModuleClass *class) +{ + GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS (class); + + type_module_class->load = test_module_load; + type_module_class->unload = test_module_unload; +} + +static void +test_module_init (TestModule *module) +{ +} + +G_DEFINE_TYPE (TestModule, test_module, G_TYPE_TYPE_MODULE); + +TestModule * +test_module_new (void) +{ + TestModule *module = g_object_new (TEST_TYPE_MODULE, + NULL); + + g_print ("test_module_new(): %p\n", module); + + return module; +} + + +/* ---------------------------------------------------- */ + +static void +non_null_proxy_test (void) +{ + UbuntuMenuProxyModule *module; + + /* prevent the module loader from finding a proxy module */ + g_unsetenv ("UBUNTU_MENUPROXY"); + + module = ubuntu_menu_proxy_module_get (); + test_proxy_register_type (G_TYPE_MODULE (module)); + //test_proxy_get_type (G_TYPE_MODULE (module)); + + GtkWidget *widget = g_object_new (GTK_TYPE_MENU_BAR, NULL); + g_object_ref_sink (widget); + + g_assert (GTK_IS_MENU_BAR (widget)); + //g_assert (GTK_MENU_SHELL (widget)->proxy != NULL); + + g_object_unref (widget); +} + +static void +null_proxy_test (void) +{ + GtkWidget *widget = g_object_new (GTK_TYPE_MENU_BAR, NULL); + g_object_ref_sink (widget); + + g_assert (GTK_IS_MENU_BAR (widget)); + + //g_assert (GTK_MENU_SHELL (widget)->proxy == NULL); + + g_object_unref (widget); +} + +static gboolean inserted_called = FALSE; + +static void +inserted_cb (UbuntuMenuProxy *proxy, + GtkWidget *child, + guint position, + gpointer data) +{ + g_return_if_fail (UBUNTU_IS_MENU_PROXY (proxy)); + g_return_if_fail (GTK_IS_WIDGET (child)); + inserted_called = TRUE; +} + +static void +menubar_signals_proxy_test (void) +{ + GtkWidget *widget = NULL; + GtkWidget *menuitem = NULL; + UbuntuMenuProxy *proxy; + + //ubuntu_menu_proxy_register_type (test_proxy_get_type ()); + + widget = g_object_new (GTK_TYPE_MENU_BAR, NULL); + g_object_ref_sink (widget); + + g_assert (GTK_IS_MENU_BAR (widget)); + //g_assert (GTK_MENU_SHELL (widget)->proxy != NULL); + + /* + proxy = GTK_MENU_SHELL (widget)->proxy; + + g_signal_connect (proxy, + "inserted", G_CALLBACK (inserted_cb), + NULL); + */ + + // insert menuitem + menuitem = gtk_menu_item_new_with_label ("Test Item"); + gtk_menu_shell_append (GTK_MENU_SHELL (widget), + menuitem); + + g_assert (inserted_called == TRUE); + + g_object_unref (widget); +} + +static void +proxy_type_exists_test (void) +{ +#if 0 + UbuntuMenuProxyModule *module; + + g_unsetenv ("GTK_MENUPROXY"); + + module = ubuntu_menu_proxy_module_get (); + test_proxy_get_type (G_TYPE_MODULE (module)); +#endif + + g_assert (ubuntu_menu_proxy_get_type () != 0); +} + +static void +can_instantiate_test (void) +{ + TestModule *module = test_module_new (); + + g_type_module_use (G_TYPE_MODULE (module)); + + UbuntuMenuProxy *proxy = ubuntu_menu_proxy_get (); + + g_assert (proxy != NULL); + + g_object_ref_sink (proxy); + + g_assert (TEST_IS_PROXY (proxy)); + g_assert (UBUNTU_IS_MENU_PROXY (proxy)); + + g_object_unref (proxy); +} + +int +main (int argc, char *argv[]) +{ + gtk_test_init (&argc, &argv); + + g_test_add_func ("/proxy/null-proxy", null_proxy_test); + g_test_add_func ("/proxy/type-exists", proxy_type_exists_test); + g_test_add_func ("/proxy/can-instantiate", can_instantiate_test); + g_test_add_func ("/proxy/non-null-proxy", non_null_proxy_test); + g_test_add_func ("/proxy/menubar-signals-proxy", menubar_signals_proxy_test); + + return g_test_run(); +} Index: gtk+2.0-2.24.0/gtk/ubuntumenuproxy.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+2.0-2.24.0/gtk/ubuntumenuproxy.c 2011-02-15 18:15:01.088117002 +0100 @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2010 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Cody Russell + */ + +#include "config.h" +#include "gtkintl.h" +#include "gtkmarshalers.h" +#include "ubuntumenuproxy.h" +#include "ubuntumenuproxymodule.h" +#include "gtkmodules.h" +#include "gtkprivate.h" +#include "gtkalias.h" + +enum { + PROP_0, + PROP_SHOW_LOCAL +}; + +enum { + INSERTED, + LOCAL_NOTIFY, + ACTIVATE_MENU, + LAST_SIGNAL +}; + +#define UBUNTU_MENU_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UBUNTU_TYPE_MENU_PROXY, UbuntuMenuProxyPrivate)) + +typedef struct _UbuntuMenuProxyPrivate UbuntuMenuProxyPrivate; + +struct _UbuntuMenuProxyPrivate +{ + gboolean show_local; +}; + +static guint menu_proxy_signals[LAST_SIGNAL] = { 0 }; +static GObjectClass *parent_class = NULL; +static UbuntuMenuProxy *proxy_singleton = NULL; + +static void ubuntu_menu_proxy_real_insert (UbuntuMenuProxy *proxy, + GtkWidget *parent, + GtkWidget *child, + guint position); +static gboolean ubuntu_menu_proxy_real_show_local (UbuntuMenuProxy *proxy); + + + +/* --------------------------------------------------------- */ + +G_DEFINE_TYPE (UbuntuMenuProxy, ubuntu_menu_proxy, G_TYPE_OBJECT) + +static GObject * +ubuntu_menu_proxy_constructor (GType type, + guint n_params, + GObjectConstructParam *params) +{ + GObject *object; + + if (proxy_singleton != NULL) + { + object = g_object_ref (proxy_singleton); + } + else + { + object = G_OBJECT_CLASS (ubuntu_menu_proxy_parent_class)->constructor (type, + n_params, + params); + + proxy_singleton = UBUNTU_MENU_PROXY (object); + g_object_add_weak_pointer (object, (gpointer) &proxy_singleton); + } + + return object; +} + +static void +ubuntu_menu_proxy_init (UbuntuMenuProxy *proxy) +{ +} + +static void +ubuntu_menu_proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + UbuntuMenuProxyPrivate *priv = UBUNTU_MENU_PROXY_GET_PRIVATE (object); + + switch (prop_id) + { + case PROP_SHOW_LOCAL: + g_value_set_boolean (value, priv->show_local); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ubuntu_menu_proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + UbuntuMenuProxyPrivate *priv = UBUNTU_MENU_PROXY_GET_PRIVATE (object); + + switch (prop_id) + { + case PROP_SHOW_LOCAL: + priv->show_local = g_value_get_boolean (value); + g_signal_emit (object, menu_proxy_signals[LOCAL_NOTIFY], 0, priv->show_local); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ubuntu_menu_proxy_class_init (UbuntuMenuProxyClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + object_class->get_property = ubuntu_menu_proxy_get_property; + object_class->set_property = ubuntu_menu_proxy_set_property; + + g_object_class_install_property (object_class, + PROP_SHOW_LOCAL, + g_param_spec_boolean ("show-local", + P_("Show the local menu"), + P_("Whether the menu is displayed locally"), + FALSE, + GTK_PARAM_READWRITE)); + + menu_proxy_signals[INSERTED] = + g_signal_new (I_("inserted"), + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UbuntuMenuProxyClass, inserted), + NULL, NULL, + _gtk_marshal_VOID__OBJECT_UINT, + G_TYPE_NONE, 2, + GTK_TYPE_WIDGET, G_TYPE_UINT); + + menu_proxy_signals[LOCAL_NOTIFY] = + g_signal_new (I_("local-notify"), + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + NULL, + NULL, NULL, + _gtk_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); + + menu_proxy_signals[ACTIVATE_MENU] = + g_signal_new (I_("activate-menu"), + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + NULL, + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + class->insert = ubuntu_menu_proxy_real_insert; + class->show_local = ubuntu_menu_proxy_real_show_local; + + object_class->constructor = ubuntu_menu_proxy_constructor; + + g_type_class_add_private (object_class, sizeof (UbuntuMenuProxyPrivate)); +} + +UbuntuMenuProxy * +ubuntu_menu_proxy_get (void) +{ + if (!proxy_singleton) + { + ubuntu_menu_proxy_module_get (); + } + + return proxy_singleton; +} + +static void +ubuntu_menu_proxy_real_insert (UbuntuMenuProxy *proxy, + GtkWidget *parent, + GtkWidget *child, + guint position) +{ +} + +static gboolean +ubuntu_menu_proxy_real_show_local (UbuntuMenuProxy *proxy) +{ + return TRUE; +} + +void +ubuntu_menu_proxy_insert (UbuntuMenuProxy *proxy, + GtkWidget *parent, + GtkWidget *child, + guint position) +{ + g_return_if_fail (UBUNTU_IS_MENU_PROXY (proxy)); + + UBUNTU_MENU_PROXY_GET_CLASS (proxy)->insert (proxy, + parent, + child, + position); +} + +gboolean +ubuntu_menu_proxy_show_local (UbuntuMenuProxy *proxy) +{ + g_return_val_if_fail (UBUNTU_IS_MENU_PROXY (proxy), TRUE); + + return UBUNTU_MENU_PROXY_GET_CLASS (proxy)->show_local (proxy); +} + +void +ubuntu_menu_proxy_activate_menu (UbuntuMenuProxy *proxy, + GtkWidget *widget) +{ + g_signal_emit (proxy, menu_proxy_signals[ACTIVATE_MENU], 0, widget); +} + +#define __UBUNTU_MENU_PROXY_C__ +#include "gtkaliasdef.c" Index: gtk+2.0-2.24.0/gtk/ubuntumenuproxy.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+2.0-2.24.0/gtk/ubuntumenuproxy.h 2011-02-15 18:15:01.088117002 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Cody Russell + */ + +#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __UBUNTU_MENU_PROXY_H__ +#define __UBUNTU_MENU_PROXY_H__ + +#include +#include + +G_BEGIN_DECLS + +#define UBUNTU_TYPE_MENU_PROXY (ubuntu_menu_proxy_get_type ()) +#define UBUNTU_MENU_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UBUNTU_TYPE_MENU_PROXY, UbuntuMenuProxy)) +#define UBUNTU_MENU_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), UBUNTU_TYPE_MENU_PROXY, UbuntuMenuProxyClass)) +#define UBUNTU_IS_MENU_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UBUNTU_TYPE_MENU_PROXY)) +#define UBUNTU_IS_MENU_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), UBUNTU_TYPE_MENU_PROXY)) +#define UBUNTU_MENU_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), UBUNTU_TYPE_MENU_PROXY, UbuntuMenuProxyClass)) + + +typedef struct _UbuntuMenuProxy UbuntuMenuProxy; +typedef struct _UbuntuMenuProxyClass UbuntuMenuProxyClass; + +struct _UbuntuMenuProxy +{ + GObject parent_object; +}; + +struct _UbuntuMenuProxyClass +{ + GObjectClass parent_class; + + /* vtable */ + void (* insert) (UbuntuMenuProxy *proxy, GtkWidget *parent, GtkWidget *child, guint position); + gboolean (* show_local) (UbuntuMenuProxy *proxy); + + /* signals */ + void (* inserted) (UbuntuMenuProxy *proxy, GtkWidget *child); +}; + +GType ubuntu_menu_proxy_get_type (void) G_GNUC_CONST; +UbuntuMenuProxy* ubuntu_menu_proxy_get (void); +void ubuntu_menu_proxy_insert (UbuntuMenuProxy *proxy, + GtkWidget *parent, + GtkWidget *child, + guint position); +gboolean ubuntu_menu_proxy_show_local (UbuntuMenuProxy *proxy); +void ubuntu_menu_proxy_activate_menu (UbuntuMenuProxy *proxy, + GtkWidget *widget); + +G_END_DECLS + +#endif /* __UBUNTU_MENU_PROXY_H__ */ Index: gtk+2.0-2.24.0/gtk/ubuntumenuproxymodule.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+2.0-2.24.0/gtk/ubuntumenuproxymodule.c 2011-02-15 18:15:01.088117002 +0100 @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2010 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Cody Russell + */ + +#include "config.h" +#include "gtkintl.h" +#include "ubuntumenuproxy.h" +#include "ubuntumenuproxymodule.h" +#include "gtkmodules.h" +#include "gtkalias.h" + +enum { + PROP_0, + PROP_MODULENAME +}; + +static GObject *ubuntu_menu_proxy_module_constructor (GType type, + guint n_params, + GObjectConstructParam *params); +static void ubuntu_menu_proxy_module_finalize (GObject *object); +static gboolean ubuntu_menu_proxy_module_real_load (GTypeModule *gmodule); +static void ubuntu_menu_proxy_module_real_unload (GTypeModule *gmodule); + + +G_DEFINE_TYPE (UbuntuMenuProxyModule, ubuntu_menu_proxy_module, G_TYPE_TYPE_MODULE); + +static UbuntuMenuProxyModule *proxy_module_singleton = NULL; + +static void +ubuntu_menu_proxy_module_class_init (UbuntuMenuProxyModuleClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS (class); + + object_class->finalize = ubuntu_menu_proxy_module_finalize; + + type_module_class->load = ubuntu_menu_proxy_module_real_load; + type_module_class->unload = ubuntu_menu_proxy_module_real_unload; +} + +static void +ubuntu_menu_proxy_module_init (UbuntuMenuProxyModule *module) +{ + module->name = g_strdup (g_getenv ("UBUNTU_MENUPROXY")); + module->library = NULL; + module->load = NULL; + module->unload = NULL; +} + +static void +ubuntu_menu_proxy_module_finalize (GObject *object) +{ + UbuntuMenuProxyModule *module = UBUNTU_MENU_PROXY_MODULE (object); + + if (module->name != NULL) + { + g_free (module->name); + } + + G_OBJECT_CLASS (ubuntu_menu_proxy_module_parent_class)->finalize (object); +} + +static gboolean +ubuntu_menu_proxy_module_real_load (GTypeModule *gmodule) +{ + UbuntuMenuProxyModule *module = UBUNTU_MENU_PROXY_MODULE (gmodule); + gchar *path; + + if (proxy_module_singleton != NULL) + return TRUE; + + if (!module->name) + { + g_warning ("Module path not set"); + return FALSE; + } + + path = _gtk_find_module (module->name, "menuproxies"); + + module->library = g_module_open (path, 0); + + if (!module->library) + { + g_printerr ("%s\n", g_module_error ()); + return FALSE; + } + + /* Make sure that the loaded library contains the required methods */ + if (!g_module_symbol (module->library, + "menu_proxy_module_load", + (gpointer *) &module->load) || + !g_module_symbol (module->library, + "menu_proxy_module_unload", + (gpointer *) &module->unload)) + { + g_printerr ("%s\n", g_module_error ()); + g_module_close (module->library); + + return FALSE; + } + + /* Initialize the loaded module */ + module->load (module); + + return TRUE; +} + +static void +ubuntu_menu_proxy_module_real_unload (GTypeModule *gmodule) +{ + UbuntuMenuProxyModule *module = UBUNTU_MENU_PROXY_MODULE (gmodule); + + module->unload (module); + + g_module_close (module->library); + module->library = NULL; + + module->load = NULL; + module->unload = NULL; +} + +static gboolean +is_valid_module_name (const gchar *name) +{ +#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN) + return g_str_has_prefix (name, "lib") && g_str_has_suffix (name, ".so"); +#else + return g_str_has_suffix (name, ".dll"); +#endif +} + +static void +setup_instance (UbuntuMenuProxyModule *module) +{ + GType *proxy_types; + guint n_proxies; + + proxy_types = g_type_children (UBUNTU_TYPE_MENU_PROXY, + &n_proxies); + + if (n_proxies > 1) + { + g_warning ("There are %d child types of UbuntuMenuProxy, should be 0 or 1.\n", + n_proxies); + } + else if (n_proxies == 1) + { + g_object_new (proxy_types[0], NULL); + } +} + +UbuntuMenuProxyModule * +ubuntu_menu_proxy_module_get (void) +{ + if (!proxy_module_singleton) + { + UbuntuMenuProxyModule *module = NULL; + const gchar *module_name; + + module_name = g_getenv ("UBUNTU_MENUPROXY"); + + if (module_name != NULL) + { + if (is_valid_module_name (module_name)) + { + gchar *path = _gtk_find_module (module_name, "menuproxies"); + + module = g_object_new (UBUNTU_TYPE_MENU_PROXY_MODULE, + NULL); + + if (!g_type_module_use (G_TYPE_MODULE (module))) + { + g_warning ("Failed to load type module: %s\n", path); + + g_object_unref (module); + g_free (path); + + return NULL; + } + + setup_instance (module); + + g_free (path); + g_type_module_unuse (G_TYPE_MODULE (module)); + } + + proxy_module_singleton = module; + } + } + + return proxy_module_singleton; +} + +#define __UBUNTU_MENU_PROXY_MODULE_C__ +#include "gtkaliasdef.c" Index: gtk+2.0-2.24.0/gtk/ubuntumenuproxymodule.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+2.0-2.24.0/gtk/ubuntumenuproxymodule.h 2011-02-15 18:15:01.088117002 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Cody Russell + */ + +#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __UBUNTU_MENU_PROXY_MODULE_H__ +#define __UBUNTU_MENU_PROXY_MODULE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define UBUNTU_TYPE_MENU_PROXY_MODULE (ubuntu_menu_proxy_module_get_type ()) +#define UBUNTU_MENU_PROXY_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UBUNTU_TYPE_MENU_PROXY_MODULE, UbuntuMenuProxyModule)) +#define UBUNTU_MENU_PROXY_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), UBUNTU_TYPE_MENU_PROXY_MODULE, UbuntuMenuProxyModuleClass)) +#define UBUNTU_IS_MENU_MODULE_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UBUNTU_TYPE_MENU_PROXY_MODULE)) +#define UBUNTU_IS_MENU_PROXY_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), UBUNTU_TYPE_MENU_PROXY_MODULE)) +#define UBUNTU_MENU_PROXY_MODULE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), UBUNTU_TYPE_MENU_PROXY_MODULE, UbuntuMenuProxyModuleClass)) + +typedef struct _UbuntuMenuProxyModule UbuntuMenuProxyModule; +typedef struct _UbuntuMenuProxyModuleClass UbuntuMenuProxyModuleClass; +typedef struct _UbuntuMenuProxyModulePrivate UbuntuMenuProxyModulePrivate; + +struct _UbuntuMenuProxyModule +{ + GTypeModule parent_instance; + + UbuntuMenuProxyModulePrivate *priv; + + GModule *library; + gchar *name; + + void (* load) (UbuntuMenuProxyModule *module); + void (* unload) (UbuntuMenuProxyModule *module); +}; + +struct _UbuntuMenuProxyModuleClass +{ + GTypeModuleClass parent_class; +}; + +GType ubuntu_menu_proxy_module_get_type (void) G_GNUC_CONST; + +UbuntuMenuProxyModule *ubuntu_menu_proxy_module_get (void); + +G_END_DECLS + +#endif /* __UBUNTU_MENU_PROXY_MODULE_H__ */ Index: gtk+2.0-2.24.0/gtk/gtkwindow.c =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtkwindow.c 2011-02-15 18:14:58.808117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtkwindow.c 2011-02-15 18:15:01.098117002 +0100 @@ -94,7 +94,8 @@ PROP_GRAVITY, PROP_TRANSIENT_FOR, PROP_OPACITY, - + PROP_NO_PROXY, + /* Readonly properties */ PROP_IS_ACTIVE, PROP_HAS_TOPLEVEL_FOCUS, @@ -195,6 +196,8 @@ gdouble opacity; + gboolean no_proxy; + gchar *startup_id; }; @@ -502,6 +505,14 @@ NULL, GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_NO_PROXY, + g_param_spec_boolean ("ubuntu-no-proxy", + P_("Disable menu proxies for this window"), + P_("Disable menu proxies for this window"), + FALSE, + GTK_PARAM_READWRITE)); + /** * GtkWindow:startup-id: * @@ -1084,6 +1095,9 @@ case PROP_MNEMONICS_VISIBLE: gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value)); break; + case PROP_NO_PROXY: + priv->no_proxy = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1202,6 +1216,9 @@ case PROP_MNEMONICS_VISIBLE: g_value_set_boolean (value, priv->mnemonics_visible); break; + case PROP_NO_PROXY: + g_value_set_boolean (value, priv->no_proxy); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; Index: gtk+2.0-2.24.0/gtk/gtkmenuitem.c =================================================================== --- gtk+2.0-2.24.0.orig/gtk/gtkmenuitem.c 2011-02-15 18:14:58.898117002 +0100 +++ gtk+2.0-2.24.0/gtk/gtkmenuitem.c 2011-02-15 18:15:01.098117002 +0100 @@ -1395,7 +1395,17 @@ widget); } else - g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0); + { + if (GTK_IS_MENU_BAR (widget->parent) && + ubuntu_gtk_menu_shell_activate_mnemonic (GTK_MENU_SHELL (widget->parent), widget)) + { + //g_print ("send activate to remote!\n"); + } + else + { + g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0); + } + } return TRUE; }