From f0d43c65fe9c6b258a92ae9dfd612eae0060754b Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 14 Feb 2015 23:24:01 +0100 Subject: try a new method to proxy "select"/"deselect" signals --- module/main.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ module/menuitem-proxy.c | 4 ++ 2 files changed, 111 insertions(+) (limited to 'module') diff --git a/module/main.c b/module/main.c index e85ac3e..e978582 100644 --- a/module/main.c +++ b/module/main.c @@ -73,6 +73,14 @@ static void (* pre_hijacked_menu_bar_get_preferred_height_for_width) (GtkWidget gint *natural_height); #endif +#if GTK_MAJOR_VERSION == 2 +static void (* pre_hijacked_menu_item_select) (GtkItem *item); +static void (* pre_hijacked_menu_item_deselect) (GtkItem *item); +#elif GTK_MAJOR_VERSION == 3 +static void (* pre_hijacked_menu_item_select) (GtkMenuItem *item); +static void (* pre_hijacked_menu_item_deselect) (GtkMenuItem *item); +#endif + static void handle_should_hide_menubar_updated (GObject *object, GParamSpec *pspec, @@ -604,6 +612,73 @@ hijacked_menu_bar_get_preferred_height_for_width (GtkWidget *widget, } #endif +static gboolean +topmenu_should_allow_select_signal (GtkMenuItem *item) +{ + MenuItemData *item_data = topmenu_get_menu_item_data (item); + if (item_data) + { + GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (item)); + if (parent) + { + if (GTK_IS_MENU_BAR (parent) && topmenu_should_hide_menubar (parent)) + { + return FALSE; + } + } + } + + return TRUE; +} + +#if GTK_MAJOR_VERSION == 2 +static void +hijacked_menu_item_select (GtkItem *item) +{ + g_return_if_fail (GTK_IS_MENU_ITEM (item)); + GtkMenuItem *menu_item = GTK_MENU_ITEM (item); + + if (topmenu_should_allow_select_signal (menu_item)) + { + if (pre_hijacked_menu_item_select) + (* pre_hijacked_menu_item_select) (item); + } +} + +static void +hijacked_menu_item_deselect (GtkItem *item) +{ + g_return_if_fail (GTK_IS_MENU_ITEM (item)); + GtkMenuItem *menu_item = GTK_MENU_ITEM (item); + + if (topmenu_should_allow_select_signal (menu_item)) + { + if (pre_hijacked_menu_item_deselect) + (* pre_hijacked_menu_item_deselect) (item); + } +} +#elif GTK_MAJOR_VERSION == 3 +static void +hijacked_menu_item_select (GtkMenuItem *item) +{ + if (topmenu_should_allow_select_signal (item)) + { + if (pre_hijacked_menu_item_select) + (* pre_hijacked_menu_item_select) (item); + } +} + +static void +hijacked_menu_item_deselect (GtkMenuItem *item) +{ + if (topmenu_should_allow_select_signal (item)) + { + if (pre_hijacked_menu_item_deselect) + (* pre_hijacked_menu_item_deselect) (item); + } +} +#endif + static void hijack_window_class_vtable (GType type) { @@ -676,6 +751,28 @@ hijack_menu_bar_class_vtable (GType type) g_free (children); } +static void +hijack_menu_item_class_vtable (GType type) +{ +#if GTK_MAJOR_VERSION == 2 + GtkItemClass *item_class = g_type_class_ref (type); +#elif GTK_MAJOR_VERSION == 3 + GtkMenuItemClass *item_class = g_type_class_ref (type); +#endif + if (item_class->select == pre_hijacked_menu_item_select) + item_class->select = hijacked_menu_item_select; + if (item_class->deselect == pre_hijacked_menu_item_select) + item_class->deselect = hijacked_menu_item_deselect; + + guint n, i; + GType *children = g_type_children (type, &n); + + for (i = 0; i < n; i++) + hijack_menu_item_class_vtable (children[i]); + + g_free (children); +} + G_MODULE_EXPORT void gtk_module_init(void) { @@ -717,6 +814,16 @@ void gtk_module_init(void) pre_hijacked_menu_bar_get_preferred_height_for_width = widget_class->get_preferred_height_for_width; #endif hijack_menu_bar_class_vtable (GTK_TYPE_MENU_BAR); + + /* intercept select/deselect vcalls on GtkMenuItem (for proxying without showing submenu) */ +#if GTK_MAJOR_VERSION == 2 + GtkItemClass *item_class = g_type_class_ref (GTK_TYPE_MENU_ITEM); +#elif GTK_MAJOR_VERSION == 3 + GtkMenuItemClass *item_class = g_type_class_ref (GTK_TYPE_MENU_ITEM); +#endif + pre_hijacked_menu_item_select = item_class->select; + pre_hijacked_menu_item_deselect = item_class->deselect; + hijack_menu_item_class_vtable (GTK_TYPE_MENU_ITEM); } } diff --git a/module/menuitem-proxy.c b/module/menuitem-proxy.c index 55319b3..6c413b8 100644 --- a/module/menuitem-proxy.c +++ b/module/menuitem-proxy.c @@ -499,6 +499,8 @@ static void handle_proxy_select(GtkMenuItem *proxy, GtkMenuItem *item) GtkWidget *submenu = gtk_menu_item_get_submenu(item); GtkWidget *parent = gtk_widget_get_parent(GTK_WIDGET(proxy)); + g_signal_emit_by_name(item, "select", NULL); + if (submenu && parent) { if (!gtk_widget_is_sensitive(GTK_WIDGET(submenu))) return; @@ -535,6 +537,8 @@ static void handle_proxy_deselect(GtkMenuItem *proxy, GtkMenuItem *item) { GtkWidget *submenu = gtk_menu_item_get_submenu(item); + g_signal_emit_by_name(item, "deselect", NULL); + if (submenu) { g_signal_handlers_disconnect_by_func(submenu, handle_menu_leave_notify, item); g_signal_handlers_disconnect_by_func(gtk_widget_get_parent(GTK_WIDGET(proxy)), -- cgit v1.2.3