## Description: add some description ## Origin/Author: add some origin or author ## Bug: bug URL Description: Add GtkMenuProxy support for remoting menus. Index: gtk+3.0-3.3.6/gtk/gtk.h =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtk.h 2012-01-12 12:27:08.242524557 +0100 +++ gtk+3.0-3.3.6/gtk/gtk.h 2012-01-12 12:27:20.658524220 +0100 @@ -75,6 +75,8 @@ #include #include #include +#include +#include #include #include #include Index: gtk+3.0-3.3.6/gtk/gtkmenubar.c =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkmenubar.c 2012-01-12 12:27:08.222524558 +0100 +++ gtk+3.0-3.3.6/gtk/gtkmenubar.c 2012-01-12 12:27:20.658524220 +0100 @@ -67,9 +67,9 @@ { GtkPackDirection pack_direction; GtkPackDirection child_pack_direction; + gboolean shell_shows; }; - static void gtk_menu_bar_set_property (GObject *object, guint prop_id, const GValue *value, @@ -94,10 +94,14 @@ gint *natural); static void gtk_menu_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static void gtk_menu_bar_realize (GtkWidget *widget); +static void gtk_menu_bar_unrealize (GtkWidget *widget); static gint gtk_menu_bar_draw (GtkWidget *widget, cairo_t *cr); static void gtk_menu_bar_hierarchy_changed (GtkWidget *widget, GtkWidget *old_toplevel); +static gboolean gtk_menu_bar_can_activate_accel (GtkWidget *widget, + guint signal_id); static gint gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell); static void gtk_menu_bar_move_current (GtkMenuShell *menu_shell, GtkMenuDirectionType direction); @@ -127,10 +131,11 @@ widget_class->get_preferred_width_for_height = gtk_menu_bar_get_preferred_width_for_height; widget_class->get_preferred_height_for_width = gtk_menu_bar_get_preferred_height_for_width; widget_class->size_allocate = gtk_menu_bar_size_allocate; + widget_class->realize = gtk_menu_bar_realize; + widget_class->unrealize = gtk_menu_bar_unrealize; widget_class->draw = gtk_menu_bar_draw; widget_class->hierarchy_changed = gtk_menu_bar_hierarchy_changed; - - gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_MENU_BAR); + widget_class->can_activate_accel = gtk_menu_bar_can_activate_accel; menu_shell_class->submenu_placement = GTK_TOP_BOTTOM; menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay; @@ -346,6 +351,9 @@ menu_shell = GTK_MENU_SHELL (widget); priv = menu_bar->priv; + if (priv->shell_shows) + return; + children = menu_shell->priv->children; if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || @@ -477,6 +485,27 @@ menu_shell = GTK_MENU_SHELL (widget); priv = menu_bar->priv; + if (priv->shell_shows) + { + GtkAllocation zero = { 0, 0, 0, 0 }; + GdkWindow *window; + + /* We manually assign an empty allocation to the menubar to + * prevent the container from attempting to draw it at all. + */ + gtk_widget_set_allocation (widget, &zero); + + /* Then we move the GdkWindow belonging to the menubar outside of + * the clipping rectangle of the parent window so that we can't + * see it. + */ + window = gtk_widget_get_window (widget); + if (window != NULL) + gdk_window_move_resize (window, -1, -1, 1, 1); + + return; + } + gtk_widget_set_allocation (widget, allocation); if (gtk_widget_get_realized (widget)) @@ -631,6 +660,46 @@ } } +static void +gtk_menu_bar_shell_shows_menubar_cb (GtkSettings *settings, + GParamSpec *pspec, + gpointer user_data) +{ + GtkMenuBar *menu_bar; + + menu_bar = GTK_MENU_BAR (user_data); + + g_object_get (settings, "gtk-shell-shows-menubar", &menu_bar->priv->shell_shows, NULL); + + gtk_widget_queue_resize (GTK_WIDGET (menu_bar)); +} + +static void +gtk_menu_bar_realize (GtkWidget *widget) +{ + GtkSettings *settings; + + GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->realize (widget); + + settings = gtk_widget_get_settings (widget); + + g_signal_connect (settings, "notify::gtk-shell-shows-menubar", + G_CALLBACK (gtk_menu_bar_shell_shows_menubar_cb), widget); + gtk_menu_bar_shell_shows_menubar_cb (settings, NULL, widget); +} + +static void +gtk_menu_bar_unrealize (GtkWidget *widget) +{ + GtkSettings *settings; + + settings = gtk_widget_get_settings (widget); + + g_signal_handlers_disconnect_by_func (settings, gtk_menu_bar_shell_shows_menubar_cb, widget); + + GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->unrealize (widget); +} + static gint gtk_menu_bar_draw (GtkWidget *widget, cairo_t *cr) @@ -739,8 +808,16 @@ { GtkMenuShell *menu_shell = GTK_MENU_SHELL (menubars->data); - _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE); - 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_set_keyboard_mode (menu_shell, TRUE); + gtk_menu_shell_select_first (menu_shell, FALSE); + gtk_menu_shell_select_first (menu_shell, FALSE); + } g_list_free (menubars); @@ -807,6 +884,16 @@ add_to_window (GTK_WINDOW (toplevel), menubar); } +static gboolean +gtk_menu_bar_can_activate_accel (GtkWidget *widget, + guint signal_id) +{ + g_return_val_if_fail (GTK_IS_MENU_BAR (widget), + gtk_widget_can_activate_accel (widget, signal_id)); + + return gtk_widget_is_sensitive (widget); +} + /** * _gtk_menu_bar_cycle_focus: * @menubar: a #GtkMenuBar Index: gtk+3.0-3.3.6/gtk/gtkmenuitem.c =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkmenuitem.c 2012-01-12 12:27:08.250524556 +0100 +++ gtk+3.0-3.3.6/gtk/gtkmenuitem.c 2012-01-12 12:27:20.658524220 +0100 @@ -38,6 +38,7 @@ #include "gtkmenuprivate.h" #include "gtkseparatormenuitem.h" #include "gtkprivate.h" +#include "ubuntumenuproxy.h" #include "gtkbuildable.h" #include "gtkactivatable.h" #include "gtkwidgetprivate.h" @@ -1740,7 +1741,18 @@ gtk_menu_shell_select_item (GTK_MENU_SHELL (parent), widget); } else - g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0); + { + GtkWidget *parent = gtk_widget_get_parent (widget); + if (GTK_IS_MENU_BAR (parent) && + ubuntu_gtk_menu_shell_activate_mnemonic (GTK_MENU_SHELL (parent), widget)) + { + //g_print ("send activate to remote!\n"); + } + else + { + g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0); + } + } return TRUE; } Index: gtk+3.0-3.3.6/gtk/gtkmenushell.c =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkmenushell.c 2012-01-12 12:27:08.262524556 +0100 +++ gtk+3.0-3.3.6/gtk/gtkmenushell.c 2012-01-12 12:27:52.390523357 +0100 @@ -48,6 +48,7 @@ #include "gtkmenuitemprivate.h" #include "gtkmenushellprivate.h" #include "gtkmenuprivate.h" +#include "ubuntumenuproxy.h" #include "gtkmnemonichash.h" #include "gtkwindow.h" #include "gtkprivate.h" @@ -474,6 +475,7 @@ GtkMenuShellPrivate); menu_shell->priv = priv; priv->take_focus = TRUE; + priv->proxy = ubuntu_menu_proxy_get (); } static void @@ -582,10 +584,20 @@ GtkWidget *child, gint position) { + GtkMenuShellPrivate *priv; + g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell)); g_return_if_fail (GTK_IS_MENU_ITEM (child)); g_signal_emit (menu_shell, menu_shell_signals[INSERT], 0, child, position); + + /* insert to proxy */ + priv = menu_shell->priv; + if (priv->proxy != NULL) + ubuntu_menu_proxy_insert (priv->proxy, + GTK_WIDGET (menu_shell), + child, + position); } static void @@ -2016,6 +2028,54 @@ } } +gboolean +ubuntu_gtk_menu_shell_activate_first (GtkMenuShell *menu_shell, + gboolean search_sensitive) +{ + GtkMenuShellPrivate *priv = menu_shell->priv; + GtkWidget *to_select = NULL; + GList *tmp_list; + + tmp_list = priv->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); +} + +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 = shell->priv; + + if (priv->proxy && !ubuntu_menu_proxy_show_local (priv->proxy)) + { + ubuntu_menu_proxy_activate_menu (priv->proxy, + item); + + return TRUE; + } + + return FALSE; +} + /** * gtk_menu_shell_get_selected_item: * @menu_shell: a #GtkMenuShell Index: gtk+3.0-3.3.6/gtk/gtkmenushellprivate.h =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkmenushellprivate.h 2012-01-12 12:27:08.198524557 +0100 +++ gtk+3.0-3.3.6/gtk/gtkmenushellprivate.h 2012-01-12 12:27:20.658524220 +0100 @@ -24,6 +24,7 @@ #include #include #include +#include "ubuntumenuproxy.h" G_BEGIN_DECLS @@ -54,6 +55,8 @@ GtkKeyHash *key_hash; GdkDevice *grab_pointer; + + UbuntuMenuProxy *proxy; }; void _gtk_menu_shell_select_last (GtkMenuShell *menu_shell, Index: gtk+3.0-3.3.6/gtk/gtk.symbols =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtk.symbols 2012-01-12 12:27:08.206524558 +0100 +++ gtk+3.0-3.3.6/gtk/gtk.symbols 2012-01-12 12:27:20.662524220 +0100 @@ -3882,3 +3882,9 @@ gtk_window_unmaximize gtk_window_unstick gtk_wrap_mode_get_type +ubuntu_gtk_menu_shell_activate_mnemonic +ubuntu_menu_proxy_get_type +ubuntu_menu_proxy_get +ubuntu_menu_proxy_insert +ubuntu_menu_proxy_module_get_type +ubuntu_menu_proxy_module_get Index: gtk+3.0-3.3.6/gtk/gtkwindow.c =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkwindow.c 2012-01-12 12:27:08.214524557 +0100 +++ gtk+3.0-3.3.6/gtk/gtkwindow.c 2012-01-12 12:27:20.662524220 +0100 @@ -118,6 +118,8 @@ GdkWindow *grip_window; + gboolean no_proxy; + gchar *startup_id; gchar *title; gchar *wmclass_class; @@ -225,6 +227,7 @@ PROP_HAS_RESIZE_GRIP, PROP_RESIZE_GRIP_VISIBLE, PROP_APPLICATION, + PROP_NO_PROXY, /* Readonly properties */ PROP_IS_ACTIVE, PROP_HAS_TOPLEVEL_FOCUS, @@ -631,6 +634,14 @@ NULL, GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_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: * @@ -1290,6 +1301,9 @@ case PROP_FOCUS_VISIBLE: gtk_window_set_focus_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; @@ -1414,6 +1428,9 @@ case PROP_FOCUS_VISIBLE: g_value_set_boolean (value, priv->focus_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+3.0-3.3.6/gtk/Makefile.am =================================================================== --- gtk+3.0-3.3.6.orig/gtk/Makefile.am 2012-01-12 12:27:08.270524556 +0100 +++ gtk+3.0-3.3.6/gtk/Makefile.am 2012-01-12 12:27:20.662524220 +0100 @@ -267,6 +267,8 @@ gtkmenu.h \ gtkmenubar.h \ gtkmenuitem.h \ + ubuntumenuproxy.h \ + ubuntumenuproxymodule.h \ gtkmenushell.h \ gtkmenutoolbutton.h \ gtkmessagedialog.h \ @@ -634,6 +636,8 @@ gtkmenu.c \ gtkmenubar.c \ gtkmenuitem.c \ + ubuntumenuproxy.c \ + ubuntumenuproxymodule.c \ gtkmenushell.c \ gtkmenutoolbutton.c \ gtkmessagedialog.c \ Index: gtk+3.0-3.3.6/gtk/ubuntumenuproxy.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+3.0-3.3.6/gtk/ubuntumenuproxy.c 2012-01-12 12:27:20.662524220 +0100 @@ -0,0 +1,246 @@ +/* + * 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" + +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) +{ + UbuntuMenuProxyPrivate *priv = UBUNTU_MENU_PROXY_GET_PRIVATE (proxy); + return priv->show_local; +} + +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); +} Index: gtk+3.0-3.3.6/gtk/ubuntumenuproxy.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+3.0-3.3.6/gtk/ubuntumenuproxy.h 2012-01-12 12:27:20.666524219 +0100 @@ -0,0 +1,73 @@ +/* + * 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 + +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); +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+3.0-3.3.6/gtk/ubuntumenuproxymodule.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+3.0-3.3.6/gtk/ubuntumenuproxymodule.c 2012-01-12 12:27:20.666524219 +0100 @@ -0,0 +1,210 @@ +/* + * 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 "gtkmodulesprivate.h" +#include "gtkprivate.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; +} Index: gtk+3.0-3.3.6/gtk/ubuntumenuproxymodule.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+3.0-3.3.6/gtk/ubuntumenuproxymodule.h 2012-01-12 12:27:20.666524219 +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); + +UbuntuMenuProxyModule *ubuntu_menu_proxy_module_get (void); + +G_END_DECLS + +#endif /* __UBUNTU_MENU_PROXY_MODULE_H__ */ Index: gtk+3.0-3.3.6/gtk/gtkmnemonichash.c =================================================================== --- gtk+3.0-3.3.6.orig/gtk/gtkmnemonichash.c 2012-01-12 12:27:08.254524557 +0100 +++ gtk+3.0-3.3.6/gtk/gtkmnemonichash.c 2012-01-12 12:27:20.666524219 +0100 @@ -20,6 +20,9 @@ */ #include "gtkmnemonichash.h" +#include "ubuntumenuproxy.h" +#include "gtkmenuitem.h" +#include "gtkaccellabel.h" struct _GtkMnemnonicHash { @@ -115,6 +118,7 @@ GtkWidget *widget, *chosen_widget; GdkWindow *window; gboolean overloaded; + UbuntuMenuProxy * menu_proxy = ubuntu_menu_proxy_get(); targets = g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval)); @@ -128,9 +132,11 @@ widget = GTK_WIDGET (list->data); window = gtk_widget_get_window (widget); - if (gtk_widget_is_sensitive (widget) && + if ((menu_proxy && !ubuntu_menu_proxy_show_local(menu_proxy) && GTK_IS_ACCEL_LABEL(widget)) + || (gtk_widget_is_sensitive (widget) && gtk_widget_get_mapped (widget) && window && gdk_window_is_viewable (window)) + ) { if (chosen_widget) {