=== modified file 'gnome-panel/Makefile.am' --- old/gnome-panel/Makefile.am 2010-01-14 22:20:05 +0000 +++ new/gnome-panel/Makefile.am 2010-03-29 19:32:29 +0000 @@ -64,6 +64,7 @@ panel_sources = \ panel-compatibility.c \ panel.c \ applet.c \ + applet-signaler.c \ drawer.c \ panel-config-global.c \ panel-util.c \ @@ -109,6 +110,7 @@ panel_headers = \ panel-compatibility.h \ panel.h \ applet.h \ + applet-signaler.h \ drawer.h \ panel-util.h \ panel-properties-dialog.h \ === added file 'gnome-panel/applet-signaler.c' --- old/gnome-panel/applet-signaler.c 1970-01-01 00:00:00 +0000 +++ new/gnome-panel/applet-signaler.c 2010-03-29 19:32:29 +0000 @@ -0,0 +1,133 @@ +/* + * Fast User Switch Applet: status-manager.c + * + * Copyright (C) 2008 Canonical, Ltd. + * Authors: + * Ted Gould + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "applet-signaler.h" + +#define PANEL_APPLET_SIGNALER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANEL_TYPE_APPLET_SIGNALER, PanelAppletSignalerClass)) +#define PANEL_IS_APPLET_SIGNALER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANEL_TYPE_APPLET_SIGNALER)) +#define PANEL_APPLET_SIGNALER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANEL_TYPE_APPLET_SIGNALER, PanelAppletSignalerClass)) + +/* Signals */ +enum { + APPLET_ADDED, + APPLET_REMOVED, + LAST_SIGNAL +}; + +struct _PanelAppletSignaler +{ + GObject parent; +}; + +typedef struct _PanelAppletSignalerClass +{ + GObjectClass parent_class; + + PanelAppletSignalerFunc applet_added; + PanelAppletSignalerFunc applet_removed; +} +PanelAppletSignalerClass; + +guint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (PanelAppletSignaler, panel_applet_signaler, G_TYPE_OBJECT); + +static void +panel_applet_signaler_finalize (GObject * obj) +{ + return; +} + +static void +panel_applet_signaler_class_init (PanelAppletSignalerClass * class) +{ + GObjectClass * gobj; + gobj = G_OBJECT_CLASS(class); + + gobj->finalize = panel_applet_signaler_finalize; + + /* Signals */ + signals[APPLET_ADDED] = g_signal_new (PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(PanelAppletSignalerClass, applet_added), + NULL, NULL, /* accumulator */ + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, /* Return value */ + 1, G_TYPE_POINTER); /* Parameters */ + + signals[APPLET_REMOVED] = g_signal_new (PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(PanelAppletSignalerClass, applet_removed), + NULL, NULL, /* accumulator */ + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, /* Return value */ + 1, G_TYPE_POINTER); /* Parameters */ + + return; +} + +static void +panel_applet_signaler_init (PanelAppletSignaler * pas) +{ + return; +} + +static PanelAppletSignaler * default_signaler = NULL; + +PanelAppletSignaler * +panel_applet_signaler_get_default (void) +{ + if (default_signaler == NULL) { + default_signaler = g_object_new(PANEL_TYPE_APPLET_SIGNALER, NULL); + g_object_add_weak_pointer(G_OBJECT(default_signaler), + (gpointer *)&default_signaler); + } + + return default_signaler; +} + +static guint applet_count = 0; + +void +panel_applet_signaler_add_applet (AppletInfo * applet) +{ + /* Ensure that one is created */ + PanelAppletSignaler * signaler = panel_applet_signaler_get_default(); + + g_signal_emit(signaler, signals[APPLET_ADDED], NULL, applet); + + return; +} + +void +panel_applet_signaler_remove_applet (AppletInfo * applet) +{ + /* Ensure that one is created */ + PanelAppletSignaler * signaler = panel_applet_signaler_get_default(); + + g_signal_emit(signaler, signals[APPLET_REMOVED], NULL, applet); + + return; +} + === added file 'gnome-panel/applet-signaler.h' --- old/gnome-panel/applet-signaler.h 1970-01-01 00:00:00 +0000 +++ new/gnome-panel/applet-signaler.h 2010-03-29 19:32:29 +0000 @@ -0,0 +1,52 @@ +/* + * Fast User Switch Applet: status-manager.c + * + * Copyright (C) 2008 Canonical, Ltd. + * Authors: + * Ted Gould + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef APPLET_SIGNALER_H +#define APPLET_SIGNALER_H + +#include +#include "applet.h" + +G_BEGIN_DECLS + +/* Applet Signaler */ +/* Singleton Object to handle the world of applets */ + +#define PANEL_TYPE_APPLET_SIGNALER (panel_applet_signaler_get_type()) +#define PANEL_APPLET_SIGNALER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANEL_TYPE_APPLET_SIGNALER, PanelAppletSignaler)) +#define PANEL_IS_APPLET_SIGNALER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANEL_TYPE_APPLET_SIGNALER)) + +#define PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED "applet-added" +#define PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED "applet-removed" + +typedef struct _PanelAppletSignaler PanelAppletSignaler; +typedef void (*PanelAppletSignalerFunc)(PanelAppletSignaler * pas, AppletInfo * info, gpointer data); + +GType panel_applet_signaler_get_type (void) G_GNUC_CONST; +PanelAppletSignaler * panel_applet_signaler_get_default (void); + +void panel_applet_signaler_add_applet (AppletInfo * applet); +void panel_applet_signaler_remove_applet (AppletInfo * applet); + +G_END_DECLS + +#endif /* APPLET_SIGNALER_H */ === modified file 'gnome-panel/applet.c' --- old/gnome-panel/applet.c 2010-03-09 14:38:51 +0000 +++ new/gnome-panel/applet.c 2010-03-29 19:32:29 +0000 @@ -34,6 +34,7 @@ #include "panel-globals.h" #include "panel-properties-dialog.h" #include "panel-lockdown.h" +#include "applet-signaler.h" #define SMALL_ICON_SIZE 20 @@ -734,6 +735,7 @@ panel_applet_destroy (GtkWidget *widget info->widget = NULL; registered_applets = g_slist_remove (registered_applets, info); + panel_applet_signaler_remove_applet(info); queued_position_saves = g_slist_remove (queued_position_saves, info); @@ -1184,6 +1186,26 @@ panel_applet_get_id (AppletInfo *info) return info->id; } +/** \brief Get the Bonobo IID of the Applet + \param info The AppletInfo struct representing the applet + \return Either the IID of the applet or NULL if the applet does + not have an IID. +*/ +const char * +panel_applet_get_iid (AppletInfo *info) +{ + if (!info) + return NULL; + if (info->type != PANEL_OBJECT_BONOBO) + return NULL; + + PanelAppletFrame * frame = PANEL_APPLET_FRAME(info->data); + if (frame == NULL) + return NULL; /* This should never happen, but just in case */ + + return panel_applet_frame_get_iid(frame); +} + const char * panel_applet_get_id_by_widget (GtkWidget *applet_widget) { @@ -1207,6 +1229,9 @@ panel_applet_get_by_id (const char *id) { GSList *l; + if (id == NULL) + return NULL; + for (l = registered_applets; l; l = l->next) { AppletInfo *info = l->data; @@ -1217,6 +1242,33 @@ panel_applet_get_by_id (const char *id) return NULL; } +/** \brief Will find an applet by looking for it's IID + \param iid The IID to look for in an applet + \return Either the AppletInfo structure representing the applet or + NULL if an applet with that IID can not be found. +*/ +AppletInfo * +panel_applet_get_by_iid (const char *iid) +{ + GSList *l; + + if (iid == NULL) + return NULL; + + for (l = registered_applets; l; l = l->next) { + AppletInfo *info = l->data; + const char *applet_iid = panel_applet_get_iid(info); + + if (applet_iid == NULL) + continue; + + if (!strcmp (applet_iid, iid)) + return info; + } + + return NULL; +} + GSList * panel_applet_list_applets (void) { @@ -1352,6 +1404,7 @@ panel_applet_register (GtkWidget * else gtk_widget_child_focus (applet, GTK_DIR_TAB_FORWARD); + panel_applet_signaler_add_applet(info); return info; } === modified file 'gnome-panel/applet.h' --- old/gnome-panel/applet.h 2010-01-27 17:53:50 +0000 +++ new/gnome-panel/applet.h 2010-03-29 19:32:29 +0000 @@ -56,8 +56,10 @@ AppletInfo *panel_applet_register (Gt void panel_applet_stop_loading (const char *id); const char *panel_applet_get_id (AppletInfo *info); +const char *panel_applet_get_iid (AppletInfo *info); const char *panel_applet_get_id_by_widget (GtkWidget *widget); AppletInfo *panel_applet_get_by_id (const char *id); +AppletInfo *panel_applet_get_by_iid (const char *iid); AppletInfo *panel_applet_get_by_type (PanelObjectType object_type, GdkScreen *screen); GSList *panel_applet_list_applets (void); === modified file 'gnome-panel/panel-applet-frame.c' --- old/gnome-panel/panel-applet-frame.c 2010-03-09 14:38:51 +0000 +++ new/gnome-panel/panel-applet-frame.c 2010-03-29 19:32:29 +0000 @@ -1442,3 +1442,15 @@ panel_applet_frame_set_panel (PanelApple frame->priv->panel = panel; } + +/** \brief Gets the IID for a panel applet frame + \param frame Applet frame + \return The IID of the applet or NULL on error +*/ +const gchar * +panel_applet_frame_get_iid (PanelAppletFrame * frame) +{ + g_return_val_if_fail (PANEL_IS_APPLET_FRAME (frame), NULL); + + return frame->priv->iid; +} === modified file 'gnome-panel/panel-applet-frame.h' --- old/gnome-panel/panel-applet-frame.h 2009-06-22 22:26:26 +0000 +++ new/gnome-panel/panel-applet-frame.h 2010-03-29 19:32:29 +0000 @@ -78,6 +78,8 @@ void panel_applet_frame_load_from_ void panel_applet_frame_set_panel (PanelAppletFrame *frame, PanelWidget *panel); +const gchar * panel_applet_frame_get_iid (PanelAppletFrame * frame); + G_END_DECLS #endif /* __PANEL_APPLET_FRAME_H__ */ === modified file 'gnome-panel/panel-menu-bar.c' --- old/gnome-panel/panel-menu-bar.c 2010-03-09 14:38:51 +0000 +++ new/gnome-panel/panel-menu-bar.c 2010-03-29 19:32:29 +0000 @@ -47,6 +47,7 @@ #include "panel-stock-icons.h" #include "panel-typebuiltins.h" #include "panel-icon-names.h" +#include "applet-signaler.h" G_DEFINE_TYPE (PanelMenuBar, panel_menu_bar, GTK_TYPE_MENU_BAR) @@ -99,6 +100,36 @@ panel_menu_bar_hide_tooltip_and_focus (G return FALSE; } +#define FUSA_APPLET_IID "OAFIID:GNOME_FastUserSwitchApplet" + +static void +panel_menu_bar_set_tooltip_remove (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget) +{ + const char * iid = panel_applet_get_iid(info); + if (iid == NULL) + return; + + if (!strcmp(iid, FUSA_APPLET_IID)) + panel_util_set_tooltip_text (widget, + _("Change desktop appearance and behavior, get help, or log out")); + + return; +} + +static void +panel_menu_bar_set_tooltip_add (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget) +{ + const char * iid = panel_applet_get_iid(info); + if (iid == NULL) + return; + + if (!strcmp(iid, FUSA_APPLET_IID)) + panel_util_set_tooltip_text (widget, + _("Change system appearance and behavior, or get help")); + + return; +} + static void panel_menu_bar_setup_tooltip (PanelMenuBar *menubar) { @@ -109,6 +140,12 @@ panel_menu_bar_setup_tooltip (PanelMenuB panel_util_set_tooltip_text (menubar->priv->desktop_item, _("Change desktop appearance and behavior, get help, or log out")); + g_signal_connect(panel_applet_signaler_get_default(), PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_bar_set_tooltip_add), menubar->priv->desktop_item); + g_signal_connect(panel_applet_signaler_get_default(), PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_bar_set_tooltip_remove), menubar->priv->desktop_item); + + //FIXME: this doesn't handle the right-click case. Sigh. /* Hide tooltip if a menu is activated */ g_signal_connect (menubar->priv->applications_item, === modified file 'gnome-panel/panel-menu-items.c' --- old/gnome-panel/panel-menu-items.c 2010-03-09 14:38:51 +0000 +++ new/gnome-panel/panel-menu-items.c 2010-03-29 19:39:56 +0000 @@ -54,6 +54,7 @@ #include "panel-recent.h" #include "panel-stock-icons.h" #include "panel-util.h" +#include "applet-signaler.h" #define BOOKMARKS_FILENAME ".gtk-bookmarks" #define DESKTOP_IS_HOME_DIR_DIR "/apps/nautilus/preferences" @@ -1522,6 +1523,58 @@ panel_desktop_menu_item_set_panel (GtkWi "menu_panel", panel); } +#define FUSA_APPLET_IID "OAFIID:GNOME_FastUserSwitchApplet" + +static void +panel_menu_items_hide_on_fusa (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget) +{ + /* check if we are running stracciatella session */ + if (g_strcmp0(g_getenv("GDMSESSION"), "gnome-stracciatella") == 0) { + g_debug("Running stracciatella GNOME session, not touching menu items"); + return TRUE; + } + + const char * iid = panel_applet_get_iid(info); + if (iid == NULL) + return; + + if (!strcmp(iid, FUSA_APPLET_IID)) + gtk_widget_hide(widget); + + return; +} + +static void +panel_menu_items_show_on_fusa (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget) +{ + /* check if we are running stracciatella session */ + if (g_strcmp0(g_getenv("GDMSESSION"), "gnome-stracciatella") == 0) { + g_debug("Running stracciatella GNOME session, not touching menu items"); + return TRUE; + } + + const char * iid = panel_applet_get_iid(info); + if (iid == NULL) + return; + + if (!strcmp(iid, FUSA_APPLET_IID)) + gtk_widget_show(widget); + + return; +} + +static void +disconnect_signalers (PanelAppletSignaler *signaler, + GtkWidget *widget) +{ + g_signal_handlers_disconnect_by_func (signaler, + panel_menu_items_hide_on_fusa, + widget); + g_signal_handlers_disconnect_by_func (signaler, + panel_menu_items_show_on_fusa, + widget); +} + void panel_menu_items_append_lock_logout (GtkWidget *menu) { @@ -1532,6 +1585,11 @@ panel_menu_items_append_lock_logout (Gtk const char *translate; char *label; char *tooltip; + GtkWidget *separator = NULL; + AppletInfo *fusa = NULL; + PanelAppletSignaler *signaler = panel_applet_signaler_get_default (); + + fusa = panel_applet_get_by_iid(FUSA_APPLET_IID); separator_inserted = FALSE; children = gtk_container_get_children (GTK_CONTAINER (menu)); @@ -1539,17 +1597,42 @@ panel_menu_items_append_lock_logout (Gtk if (last != NULL) { separator_inserted = GTK_IS_SEPARATOR (GTK_WIDGET (last->data)); } + if (separator_inserted) { + g_object_weak_ref (G_OBJECT (last->data), + (GWeakNotify) disconnect_signalers, + signaler); + + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_items_hide_on_fusa), last->data); + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_items_show_on_fusa), last->data); + if (fusa != NULL) { + gtk_widget_hide(GTK_WIDGET(last->data)); + } + } g_list_free (children); if (panel_lock_screen_action_available ("lock")) { item = panel_menu_items_create_action_item (PANEL_ACTION_LOCK); if (item != NULL) { if (!separator_inserted) { - add_menu_separator (menu); + separator = add_menu_separator (menu); separator_inserted = TRUE; } gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_object_weak_ref (G_OBJECT (item), + (GWeakNotify) disconnect_signalers, + signaler); + + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_items_hide_on_fusa), item); + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_items_show_on_fusa), item); + if (fusa != NULL) { + gtk_widget_hide(GTK_WIDGET(item)); + } } } @@ -1592,19 +1675,65 @@ panel_menu_items_append_lock_logout (Gtk if (item != NULL) { if (!separator_inserted) { - add_menu_separator (menu); + separator = add_menu_separator (menu); separator_inserted = TRUE; } gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_object_weak_ref (G_OBJECT (item), + (GWeakNotify) disconnect_signalers, + signaler); + + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_items_hide_on_fusa), item); + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_items_show_on_fusa), item); + if (fusa != NULL) { + gtk_widget_hide(GTK_WIDGET(item)); + } } item = panel_menu_items_create_action_item (PANEL_ACTION_SHUTDOWN); if (item != NULL) { if (!separator_inserted) - add_menu_separator (menu); + separator = add_menu_separator (menu); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_object_weak_ref (G_OBJECT (item), + (GWeakNotify) disconnect_signalers, + signaler); + + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_items_hide_on_fusa), item); + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_items_show_on_fusa), item); + if (fusa != NULL) { + gtk_widget_hide(GTK_WIDGET(item)); + } + } + + /* Okay, this is confusing, but required to make the patch + * smaller. Basically if the seperator was created externally it + * gets the signal handlers added when it is detected, but the + * local variable remains NULL. This allows the return in the + * middle to still work. But, if the seperator gets built in the + * remainder of this function then the signal handlers get added + * on here as the local variable becomes a pointer to that created + * seperator. Whew. */ + if (separator != NULL) { + g_object_weak_ref (G_OBJECT (separator), + (GWeakNotify) disconnect_signalers, + signaler); + + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED, + G_CALLBACK(panel_menu_items_hide_on_fusa), separator); + g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED, + G_CALLBACK(panel_menu_items_show_on_fusa), separator); + if (fusa != NULL) { + gtk_widget_hide(GTK_WIDGET(separator)); + } } }