Mercurial > pidgin
changeset 12016:24c7fb94d3a3
[gaim-migrate @ 14309]
Patch from charkins to fix potential problems with the buddy list becoming invisible with no way to restore visiblity. This (re)introduces the concept of a "visibility manager" that, if present, will be in charge of controlling the visibility of the buddy list.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Wed, 09 Nov 2005 02:25:26 +0000 |
parents | 5a63ea24ac83 |
children | 2b6e0be024fb |
files | doc/gtkblist-signals.dox plugins/ChangeLog.API plugins/docklet/docklet-win32.c plugins/docklet/docklet.c plugins/docklet/docklet.h src/gtkblist.c |
diffstat | 6 files changed, 141 insertions(+), 107 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/gtkblist-signals.dox Wed Nov 09 01:36:28 2005 +0000 +++ b/doc/gtkblist-signals.dox Wed Nov 09 02:25:26 2005 +0000 @@ -1,12 +1,32 @@ /** @page gtkblist-signals GtkBlist Signals @signals + @signal gtkblist-hiding + @signal gtkblist-unhiding @signal gtkblist-created @signal drawing-tooltip @endsignals <hr> + @signaldef gtkblist-hiding + @signalproto +void (*gtkblist-hiding)(GaimBuddyList *blist); + @endsignalproto + @signaldesc + Emitted when the buddy list is about to be hidden. + @param blist The buddy list. + @endsignaldef + + @signaldef gtkblist-unhiding + @signalproto +void (*gtkblist-unhiding)(GaimBuddyList *blist); + @endsignalproto + @signaldesc + Emitted when the buddy list is about to be unhidden. + @param blist The buddy list. + @endsignaldef + @signaldef gtkblist-created @signalproto void (*gtkblist-created)(GaimBuddyList *blist);
--- a/plugins/ChangeLog.API Wed Nov 09 01:36:28 2005 +0000 +++ b/plugins/ChangeLog.API Wed Nov 09 02:25:26 2005 +0000 @@ -135,6 +135,12 @@ a given string * gaim_util_chrreplace() to replace a given character with a different character + * gaim_gtk_blist_toggle_visibility() to intelligently toggle the + visiblity of the buddy list + * gaim_gtk_blist_visibility_manager_add() to indicate the addition of a + visibility manager - see the docs for more information + * gaim_gtk_blist_visibility_manager_remove() to indicate the removal of + a visibility manager - see the docs for more information Signals - Changed: * "received-im-msg" and "received-chat-msg" to match, both now pass a @@ -172,6 +178,8 @@ * "buddy-status-changed": A buddy changed status; see Doxygen docs for full details. * "buddy-idle-changed": A buddy's idle status changed; see Doxygen docs for full details. See Doxygen docs for details. + * "gtkblist-hiding": See Doxygen docs for details. + * "gtkblist-unhiding": See Doxygen docs for details. Signals - Removed: * "buddy-away": replaced by buddy-status-changed
--- a/plugins/docklet/docklet-win32.c Wed Nov 09 01:36:28 2005 +0000 +++ b/plugins/docklet/docklet-win32.c Wed Nov 09 02:25:26 2005 +0000 @@ -190,6 +190,15 @@ systray_change_icon(sysicon_blank, NULL); } +void wgaim_tray_minimize(GaimGtkBuddyList *gtkblist) { + MinimizeWndToTray(GDK_WINDOW_HWND(gtkblist->window->window)); +} + +void wgaim_tray_maximize(GaimGtkBuddyList *gtkblist) { + RestoreWndFromTray(GDK_WINDOW_HWND(gtkblist->window->window)); +} + + static void wgaim_tray_create() { OSVERSIONINFO osinfo; /* dummy window to process systray messages */ @@ -220,31 +229,28 @@ /* Create icon in systray */ systray_init_icon(systray_hwnd, sysicon_disconn); + + gaim_signal_connect(gaim_gtk_blist_get_handle(), "gtkblist-hiding", + &handle, GAIM_CALLBACK(wgaim_tray_minimize), NULL); + gaim_signal_connect(gaim_gtk_blist_get_handle(), "gtkblist-unhiding", + &handle, GAIM_CALLBACK(wgaim_tray_maximize), NULL); + gaim_debug(GAIM_DEBUG_INFO, "tray icon", "created\n"); } static void wgaim_tray_destroy() { + gaim_signals_disconnect_by_handle(&handle); systray_remove_nid(); DestroyWindow(systray_hwnd); docklet_remove(TRUE); } -void wgaim_tray_minimize(GtkWidget *window) { - MinimizeWndToTray(GDK_WINDOW_HWND(window->window)); -} - -void wgaim_tray_maximize(GtkWidget *window) { - RestoreWndFromTray(GDK_WINDOW_HWND(window->window)); -} - static struct docklet_ui_ops wgaim_tray_ops = { wgaim_tray_create, wgaim_tray_destroy, wgaim_tray_update_icon, wgaim_tray_blank_icon, - wgaim_tray_minimize, - wgaim_tray_maximize, NULL };
--- a/plugins/docklet/docklet.c Wed Nov 09 01:36:28 2005 +0000 +++ b/plugins/docklet/docklet.c Wed Nov 09 02:25:26 2005 +0000 @@ -52,7 +52,6 @@ GaimPlugin *handle = NULL; static struct docklet_ui_ops *ui_ops = NULL; static DockletStatus status = DOCKLET_STATUS_OFFLINE; -static gulong gtkblist_delete_cb_id = 0; static gboolean enable_join_chat = FALSE; static guint docklet_blinking_timer = 0; @@ -212,74 +211,8 @@ } /************************************************************************** - * minimize to and unminimize from the tray icon - **************************************************************************/ -static void -minimize_to_tray() -{ - GaimGtkBuddyList *blist = gaim_gtk_blist_get_default_gtk_blist(); - - if(!blist || !blist->window) - return; - - if (ui_ops && ui_ops->minimize) - ui_ops->minimize(blist->window); - - gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE); - gtk_widget_hide(blist->window); - - docklet_update_status(); -} - -static void -unminimize_from_tray() -{ - GaimGtkBuddyList *blist = gaim_gtk_blist_get_default_gtk_blist(); - - if(!blist || !blist->window) - return; - - if (ui_ops && ui_ops->maximize) - ui_ops->maximize(blist->window); - - gaim_blist_set_visible(TRUE); - - docklet_update_status(); -} - -static void -docklet_toggle_blist() -{ - if(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")) - minimize_to_tray(); - else - unminimize_from_tray(); -} - -/************************************************************************** * callbacks and signal handlers **************************************************************************/ -/* catch delete events on gtkblist and hide it instead */ -static gboolean -gtkblist_delete_cb(GtkWidget *widget) { - gaim_debug(GAIM_DEBUG_INFO, "docklet", "hiding buddy list\n"); - minimize_to_tray(widget); - return TRUE; -} - -/* connect to delete signal when gtkblist is created */ -static void -gtkblist_created_cb(GaimBuddyList *list) -{ - if(list!=NULL && GAIM_IS_GTK_BLIST(list) && - GAIM_GTK_BLIST(list)->window!=NULL && - gtkblist_delete_cb_id==0) { - - gtkblist_delete_cb_id = g_signal_connect(G_OBJECT(GAIM_GTK_BLIST(list)->window), - "delete_event", G_CALLBACK(gtkblist_delete_cb), NULL); - } -} - static void gaim_quit_cb() { @@ -334,6 +267,12 @@ gaim_prefs_set_bool("/gaim/gtk/sound/mute", GTK_CHECK_MENU_ITEM(toggle)->active); } +static void +docklet_toggle_blist(GtkWidget *toggle, void *data) +{ + gaim_blist_set_visible(GTK_CHECK_MENU_ITEM(toggle)->active); +} + #ifdef _WIN32 /* This is a workaround for a bug in windows GTK+. Clicking outside of the menu does not get rid of it, so instead we get rid of it as soon as the @@ -440,7 +379,7 @@ || status==DOCKLET_STATUS_AWAY_PENDING) focus_first_unseen_conv(); else - docklet_toggle_blist(); + gaim_gtk_blist_toggle_visibility(); break; case 3: docklet_menu(); @@ -451,6 +390,7 @@ void docklet_embedded() { + gaim_gtk_blist_visibility_manager_add(); docklet_update_status(); if (ui_ops && ui_ops->update_icon) ui_ops->update_icon(status); @@ -459,7 +399,7 @@ void docklet_remove(gboolean visible) { - unminimize_from_tray(); + gaim_gtk_blist_visibility_manager_remove(); } void @@ -508,36 +448,22 @@ gaim_signal_connect(conv_handle, "conversation-updated", plugin, GAIM_CALLBACK(docklet_conv_updated_cb), NULL); - gaim_signal_connect(gaim_gtk_blist_get_handle(), "gtkblist-created", - plugin, GAIM_CALLBACK(gtkblist_created_cb), NULL); - gtkblist_created_cb(gaim_get_blist()); - gaim_signal_connect(core_handle, "quitting", plugin, GAIM_CALLBACK(gaim_quit_cb), NULL); enable_join_chat = online_account_supports_chat(); - if(!gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")) - minimize_to_tray(); - return TRUE; } static gboolean plugin_unload(GaimPlugin *plugin) { - GaimGtkBuddyList *gtkblist = gaim_gtk_blist_get_default_gtk_blist(); - if (ui_ops && ui_ops->destroy) ui_ops->destroy(); /* remove callbacks */ - gaim_signals_disconnect_by_handle(handle); - if(gtkblist_delete_cb_id!=0) - g_signal_handler_disconnect(G_OBJECT(gtkblist->window), gtkblist_delete_cb_id); - gtkblist_delete_cb_id = 0; - - unminimize_from_tray(); + gaim_signals_disconnect_by_handle(handle); gaim_debug(GAIM_DEBUG_INFO, "docklet", "plugin unloaded\n");
--- a/plugins/docklet/docklet.h Wed Nov 09 01:36:28 2005 +0000 +++ b/plugins/docklet/docklet.h Wed Nov 09 02:25:26 2005 +0000 @@ -41,8 +41,6 @@ void (*destroy)(); void (*update_icon)(DockletStatus); void (*blank_icon)(); - void (*minimize)(GtkWidget *); - void (*maximize)(GtkWidget *); GtkMenuPositionFunc position_menu; };
--- a/src/gtkblist.c Wed Nov 09 01:36:28 2005 +0000 +++ b/src/gtkblist.c Wed Nov 09 02:25:26 2005 +0000 @@ -101,6 +101,9 @@ static GtkWidget *protomenu = NULL; +static guint visibility_manager_count = 0; +static gboolean gtk_blist_obscured = FALSE; + static GList *gaim_gtk_blist_sort_methods = NULL; static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; static GtkTreeIter sort_method_none(GaimBlistNode *node, GaimBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur); @@ -150,10 +153,42 @@ /*************************************************** * Callbacks * ***************************************************/ +static gboolean gtk_blist_visibility_cb(GtkWidget *w, GdkEventVisibility *event, gpointer data) +{ + if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) + gtk_blist_obscured = TRUE; + else + gtk_blist_obscured = FALSE; + + /* continue to handle event normally */ + return FALSE; +} + +static gboolean gtk_blist_window_state_cb(GtkWidget *w, GdkEventWindowState *event, gpointer data) +{ + if(event->changed_mask & GDK_WINDOW_STATE_WITHDRAWN) { + if(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) + gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE); + else + gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", TRUE); + } + + if(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) { + if(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) + gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", FALSE); + else + gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", TRUE); + } + + return FALSE; +} static gboolean gtk_blist_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data) { - gaim_core_quit(); + if(visibility_manager_count) + gaim_blist_set_visible(FALSE); + else + gaim_core_quit(); /* we handle everything, event should not propogate further */ return TRUE; @@ -3218,8 +3253,7 @@ {"application/x-im-contact", 0, DRAG_BUDDY}, {"text/x-vcard", 0, DRAG_VCARD }}; if (gtkblist && gtkblist->window) { - if (gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")) - gtk_widget_show(gtkblist->window); + gaim_blist_set_visible(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")); return; } @@ -3233,8 +3267,10 @@ gtk_widget_show(gtkblist->vbox); gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->vbox); - g_signal_connect_after(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); + g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL); g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL); + g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL); + g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL); gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); /******************************* Menu bar *************************************/ @@ -3400,11 +3436,8 @@ gaim_gtk_blist_update_sort_methods(); /* OK... let's show this bad boy. */ - if (gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")) { - gaim_gtk_blist_refresh(list); - gaim_gtk_blist_restore_position(); - gtk_widget_show(gtkblist->window); - } + gaim_gtk_blist_refresh(list); + gaim_blist_set_visible(gaim_prefs_get_bool("/gaim/gtk/blist/list_visible")); /* start the refresh timer */ gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); @@ -3943,13 +3976,20 @@ if (!(gtkblist && gtkblist->window)) return; - gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", show); + //gaim_prefs_set_bool("/gaim/gtk/blist/list_visible", show); if (show) { + if(!GAIM_WINDOW_ICONIFIED(gtkblist->window) && !GTK_WIDGET_VISIBLE(gtkblist->window)) + gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-unhiding", gtkblist); gaim_gtk_blist_restore_position(); gtk_window_present(GTK_WINDOW(gtkblist->window)); } else { - gtk_window_iconify(GTK_WINDOW(gtkblist->window)); + if(visibility_manager_count) { + gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-hiding", gtkblist); + gtk_widget_hide(gtkblist->window); + } else { + gtk_window_iconify(GTK_WINDOW(gtkblist->window)); + } } } @@ -4569,6 +4609,34 @@ _("Cancel"), NULL, NULL); } +void +gaim_gtk_blist_toggle_visibility() +{ + if (gtkblist && gtkblist->window) { + if (GTK_WIDGET_VISIBLE(gtkblist->window)) { + gaim_blist_set_visible(GAIM_WINDOW_ICONIFIED(gtkblist->window) || gtk_blist_obscured); + } else { + gaim_blist_set_visible(TRUE); + } + } +} + +void +gaim_gtk_blist_visibility_manager_add() +{ + visibility_manager_count++; +} + +void +gaim_gtk_blist_visibility_manager_remove() +{ + if (visibility_manager_count) + visibility_manager_count--; + if (!visibility_manager_count) + gaim_blist_set_visible(TRUE); +} + + static GaimBlistUiOps blist_ui_ops = { gaim_gtk_blist_new_list, @@ -4691,6 +4759,14 @@ gaim_prefs_add_int("/gaim/gtk/blist/tooltip_delay", 500); /* Register our signals */ + gaim_signal_register(gtk_blist_handle, "gtkblist-hiding", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_POINTER)); + + gaim_signal_register(gtk_blist_handle, "gtkblist-unhiding", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_SUBTYPE)); + gaim_signal_register(gtk_blist_handle, "gtkblist-created", gaim_marshal_VOID__POINTER, NULL, 1, gaim_value_new(GAIM_TYPE_SUBTYPE,