pidgin: c469cf45: Remove GtkDocklet abstraction and merge ...
qulogic at pidgin.im
qulogic at pidgin.im
Fri Sep 2 14:18:04 EDT 2011
----------------------------------------------------------------------
Revision: c469cf45e492afd08e45d570192948a6296ede45
Parent: ebc65b7af7f6617c879151b374436c4a5e2128a3
Author: qulogic at pidgin.im
Date: 09/02/11 02:20:24
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/c469cf45e492afd08e45d570192948a6296ede45
Changelog:
Remove GtkDocklet abstraction and merge GtkStatusIcon code into it.
Changes against parent ebc65b7af7f6617c879151b374436c4a5e2128a3
dropped pidgin/gtkdocklet-gtk.c
patched pidgin/Makefile.am
patched pidgin/gtkdocklet.c
patched pidgin/gtkdocklet.h
-------------- next part --------------
============================================================
--- pidgin/gtkdocklet.h 16acb1dd32c2646895f80d34f177dca23aa5e72c
+++ pidgin/gtkdocklet.h d7d5c58d5738247b75c933e739068ad0c5c491ed
@@ -25,31 +25,9 @@
#ifndef _GTKDOCKLET_H_
#define _GTKDOCKLET_H_
-#include "status.h"
-
-struct docklet_ui_ops
-{
- void (*create)(void);
- void (*destroy)(void);
- void (*update_icon)(PurpleStatusPrimitive, gboolean, gboolean);
- void (*blank_icon)(void);
- void (*set_tooltip)(gchar *);
- GtkMenuPositionFunc position_menu;
-};
-
-
-/* functions in gtkdocklet.c */
-void pidgin_docklet_update_icon(void);
-void pidgin_docklet_clicked(int);
-void pidgin_docklet_embedded(void);
-void pidgin_docklet_remove(void);
-void pidgin_docklet_set_ui_ops(struct docklet_ui_ops *);
-void pidgin_docklet_unload(void);
void pidgin_docklet_init(void);
void pidgin_docklet_uninit(void);
void*pidgin_docklet_get_handle(void);
-/* function in gtkdocklet-{gtk,x11,win32}.c */
-void docklet_ui_init(void);
+#endif /* _GTKDOCKLET_H_ */
-#endif /* _GTKDOCKLET_H_ */
============================================================
--- pidgin/Makefile.am d949e7f7c00dac781a6ba44cdc316f80342bb3c9
+++ pidgin/Makefile.am 14b01248a7e0205503780a7d61a18ed319f72c97
@@ -52,7 +52,6 @@ pidgin_SOURCES = \
gtkdialogs.c \
gtkdnd-hints.c \
gtkdocklet.c \
- gtkdocklet-gtk.c \
gtkeventloop.c \
gtkft.c \
gtkicon-theme.c \
@@ -181,3 +180,4 @@ endif # ENABLE_GTK
$(LIBXML_CFLAGS) \
$(INTGG_CFLAGS)
endif # ENABLE_GTK
+
============================================================
--- pidgin/gtkdocklet.c c5c361f658e7e23e643b59e972df0aeb43ad5d61
+++ pidgin/gtkdocklet.c 011bca4285d51004c58eae2030c3de862cb40adb
@@ -30,6 +30,7 @@
#include "prefs.h"
#include "signals.h"
#include "sound.h"
+#include "status.h"
#include "gtkaccount.h"
#include "gtkblist.h"
@@ -48,8 +49,12 @@
#define DOCKLET_TOOLTIP_LINE_LIMIT 5
#endif
+#define SHORT_EMBED_TIMEOUT 5
+#define LONG_EMBED_TIMEOUT 15
+
/* globals */
-static struct docklet_ui_ops *ui_ops = NULL;
+static GtkStatusIcon *docklet = NULL;
+static guint embed_timeout = 0;
static PurpleStatusPrimitive status = PURPLE_STATUS_OFFLINE;
static gboolean pending = FALSE;
static gboolean connecting = FALSE;
@@ -58,9 +63,55 @@ static gboolean visibility_manager = FAL
static gboolean visible = FALSE;
static gboolean visibility_manager = FALSE;
+/* protos */
+static void docklet_gtk_status_create(gboolean);
+static void docklet_gtk_status_destroy(void);
+
/**************************************************************************
* docklet status and utility functions
**************************************************************************/
+static void
+docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
+{
+ const gchar *icon_name = NULL;
+
+ switch (status) {
+ case PURPLE_STATUS_OFFLINE:
+ icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
+ break;
+ case PURPLE_STATUS_AWAY:
+ icon_name = PIDGIN_STOCK_TRAY_AWAY;
+ break;
+ case PURPLE_STATUS_UNAVAILABLE:
+ icon_name = PIDGIN_STOCK_TRAY_BUSY;
+ break;
+ case PURPLE_STATUS_EXTENDED_AWAY:
+ icon_name = PIDGIN_STOCK_TRAY_XA;
+ break;
+ case PURPLE_STATUS_INVISIBLE:
+ icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+ break;
+ default:
+ icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
+ break;
+ }
+
+ if (pending)
+ icon_name = PIDGIN_STOCK_TRAY_PENDING;
+ if (connecting)
+ icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+
+ if (icon_name) {
+ gtk_status_icon_set_from_icon_name(docklet, icon_name);
+ }
+
+ if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) {
+ gtk_status_icon_set_blinking(docklet, (pending && !connecting));
+ } else if (gtk_status_icon_get_blinking(docklet)) {
+ gtk_status_icon_set_blinking(docklet, FALSE);
+ }
+}
+
static gboolean
docklet_blink_icon(gpointer data)
{
@@ -70,11 +121,8 @@ docklet_blink_icon(gpointer data)
blinked = !blinked;
if(pending && !connecting) {
- if (blinked) {
- if (ui_ops && ui_ops->blank_icon)
- ui_ops->blank_icon();
- } else {
- pidgin_docklet_update_icon();
+ if (!blinked) {
+ docklet_gtk_status_update_icon(status, connecting, pending);
}
ret = TRUE; /* keep blinking */
} else {
@@ -126,12 +174,12 @@ docklet_update_status(void)
convs = get_pending_list(DOCKLET_TOOLTIP_LINE_LIMIT);
if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) {
- if (convs && ui_ops->create && !visible) {
+ if (convs && !visible) {
g_list_free(convs);
- ui_ops->create();
+ docklet_gtk_status_create(FALSE);
return FALSE;
- } else if (!convs && ui_ops->destroy && visible) {
- ui_ops->destroy();
+ } else if (!convs && visible) {
+ docklet_gtk_status_destroy();
return FALSE;
}
}
@@ -142,46 +190,43 @@ docklet_update_status(void)
}
if (convs != NULL) {
+ /* set tooltip if messages are pending */
+ GString *tooltip_text = g_string_new("");
newpending = TRUE;
- /* set tooltip if messages are pending */
- if (ui_ops->set_tooltip) {
- GString *tooltip_text = g_string_new("");
- for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) {
- PurpleConversation *conv = (PurpleConversation *)l->data;
- PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+ for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) {
+ PurpleConversation *conv = (PurpleConversation *)l->data;
+ PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) {
- g_string_append(tooltip_text, _("Right-click for more unread messages...\n"));
- } else if(gtkconv) {
- g_string_append_printf(tooltip_text,
- ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count),
- gtkconv->unseen_count,
- purple_conversation_get_title(conv));
- } else {
- g_string_append_printf(tooltip_text,
- ngettext("%d unread message from %s\n", "%d unread messages from %s\n",
- GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))),
- GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")),
- purple_conversation_get_title(conv));
- }
+ if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) {
+ g_string_append(tooltip_text, _("Right-click for more unread messages...\n"));
+ } else if(gtkconv) {
+ g_string_append_printf(tooltip_text,
+ ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count),
+ gtkconv->unseen_count,
+ purple_conversation_get_title(conv));
+ } else {
+ g_string_append_printf(tooltip_text,
+ ngettext("%d unread message from %s\n", "%d unread messages from %s\n",
+ GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))),
+ GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")),
+ purple_conversation_get_title(conv));
}
+ }
- /* get rid of the last newline */
- if (tooltip_text->len > 0)
- tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1);
+ /* get rid of the last newline */
+ if (tooltip_text->len > 0)
+ tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1);
- ui_ops->set_tooltip(tooltip_text->str);
+ gtk_status_icon_set_tooltip(docklet, tooltip_text->str);
- g_string_free(tooltip_text, TRUE);
- }
-
+ g_string_free(tooltip_text, TRUE);
g_list_free(convs);
- } else if (ui_ops->set_tooltip) {
+ } else {
char *tooltip_text = g_strconcat(PIDGIN_NAME, " - ",
purple_savedstatus_get_title(saved_status), NULL);
- ui_ops->set_tooltip(tooltip_text);
+ gtk_status_icon_set_tooltip(docklet, tooltip_text);
g_free(tooltip_text);
}
@@ -207,7 +252,7 @@ docklet_update_status(void)
pending = newpending;
connecting = newconnecting;
- pidgin_docklet_update_icon();
+ docklet_gtk_status_update_icon(status, connecting, pending);
/* and schedule the blinker function if messages are pending */
if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")
@@ -286,17 +331,15 @@ docklet_show_pref_changed_cb(const char
{
const char *val = value;
if (!strcmp(val, "always")) {
- if (ui_ops->create) {
- if (!visible)
- ui_ops->create();
- else if (!visibility_manager) {
- pidgin_blist_visibility_manager_add();
- visibility_manager = TRUE;
- }
+ if (!visible)
+ docklet_gtk_status_create(FALSE);
+ else if (!visibility_manager) {
+ pidgin_blist_visibility_manager_add();
+ visibility_manager = TRUE;
}
} else if (!strcmp(val, "never")) {
- if (visible && ui_ops->destroy)
- ui_ops->destroy();
+ if (visible)
+ docklet_gtk_status_destroy();
} else {
if (visibility_manager) {
pidgin_blist_visibility_manager_remove();
@@ -750,21 +793,11 @@ docklet_menu(void)
#endif
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
- ui_ops->position_menu,
- NULL, 0, gtk_get_current_event_time());
+ gtk_status_icon_position_menu,
+ docklet, 0, gtk_get_current_event_time());
}
-/**************************************************************************
- * public api for ui_ops
- **************************************************************************/
-void
-pidgin_docklet_update_icon()
-{
- if (ui_ops && ui_ops->update_icon)
- ui_ops->update_icon(status, connecting, pending);
-}
-
-void
+static void
pidgin_docklet_clicked(int button_type)
{
switch (button_type) {
@@ -785,8 +818,8 @@ pidgin_docklet_clicked(int button_type)
}
}
-void
-pidgin_docklet_embedded()
+static void
+pidgin_docklet_embedded(void)
{
if (!visibility_manager
&& strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) {
@@ -795,11 +828,11 @@ pidgin_docklet_embedded()
}
visible = TRUE;
docklet_update_status();
- pidgin_docklet_update_icon();
+ docklet_gtk_status_update_icon(status, connecting, pending);
}
-void
-pidgin_docklet_remove()
+static void
+pidgin_docklet_remove(void)
{
if (visible) {
if (visibility_manager) {
@@ -815,12 +848,179 @@ pidgin_docklet_remove()
}
}
-void
-pidgin_docklet_set_ui_ops(struct docklet_ui_ops *ops)
+static gboolean
+docklet_gtk_recreate_cb(gpointer data)
{
- ui_ops = ops;
+ docklet_gtk_status_create(TRUE);
+
+ return FALSE;
}
+static gboolean
+docklet_gtk_embed_timeout_cb(gpointer data)
+{
+#if !GTK_CHECK_VERSION(2,12,0)
+ if (gtk_status_icon_is_embedded(docklet)) {
+ /* Older GTK+ (<2.12) don't implement the embedded signal, but the
+ information is still accessible through the above function. */
+ purple_debug_info("docklet", "embedded\n");
+
+ pidgin_docklet_embedded();
+ purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+ }
+ else
+#endif
+ {
+ /* The docklet was not embedded within the timeout.
+ * Remove it as a visibility manager, but leave the plugin
+ * loaded so that it can embed automatically if/when a notification
+ * area becomes available.
+ */
+ purple_debug_info("docklet", "failed to embed within timeout\n");
+ pidgin_docklet_remove();
+ purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+ }
+
+#if GTK_CHECK_VERSION(2,12,0)
+ embed_timeout = 0;
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+
+#if GTK_CHECK_VERSION(2,12,0)
+static gboolean
+docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data)
+{
+ if (embed_timeout) {
+ purple_timeout_remove(embed_timeout);
+ embed_timeout = 0;
+ }
+
+ if (gtk_status_icon_is_embedded(docklet)) {
+ purple_debug_info("docklet", "embedded\n");
+
+ pidgin_docklet_embedded();
+ purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+ } else {
+ purple_debug_info("docklet", "detached\n");
+
+ pidgin_docklet_remove();
+ purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+ }
+
+ return TRUE;
+}
+#endif
+
+static void
+docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data)
+{
+ purple_debug_info("docklet", "destroyed\n");
+
+ pidgin_docklet_remove();
+
+ g_object_unref(G_OBJECT(docklet));
+ docklet = NULL;
+
+ g_idle_add(docklet_gtk_recreate_cb, NULL);
+}
+
+static void
+docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data)
+{
+ pidgin_docklet_clicked(1);
+}
+
+static void
+docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
+{
+ purple_debug_info("docklet", "The button is %u\n", button);
+#ifdef GDK_WINDOWING_QUARTZ
+ /* You can only click left mouse button on MacOSX native GTK. Let that be the menu */
+ pidgin_docklet_clicked(3);
+#else
+ pidgin_docklet_clicked(button);
+#endif
+}
+
+static void
+docklet_gtk_status_destroy(void)
+{
+ g_return_if_fail(docklet != NULL);
+
+ pidgin_docklet_remove();
+
+ if (embed_timeout) {
+ purple_timeout_remove(embed_timeout);
+ embed_timeout = 0;
+ }
+
+ gtk_status_icon_set_visible(docklet, FALSE);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
+ g_object_unref(G_OBJECT(docklet));
+ docklet = NULL;
+
+ purple_debug_info("docklet", "GTK+ destroyed\n");
+}
+
+static void
+docklet_gtk_status_create(gboolean recreate)
+{
+ if (docklet) {
+ /* if this is being called when a tray icon exists, it's because
+ something messed up. try destroying it before we proceed,
+ although docklet_refcount may be all hosed. hopefully won't happen. */
+ purple_debug_warning("docklet", "trying to create icon but it already exists?\n");
+ docklet_gtk_status_destroy();
+ }
+
+ docklet = gtk_status_icon_new();
+ g_return_if_fail(docklet != NULL);
+
+ g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL);
+ g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL);
+#if GTK_CHECK_VERSION(2,12,0)
+ g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL);
+#endif
+ g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
+
+ gtk_status_icon_set_visible(docklet, TRUE);
+
+ /* This is a hack to avoid a race condition between the docklet getting
+ * embedded in the notification area and the gtkblist restoring its
+ * previous visibility state. If the docklet does not get embedded within
+ * the timeout, it will be removed as a visibility manager until it does
+ * get embedded. Ideally, we would only call docklet_embedded() when the
+ * icon was actually embedded. This only happens when the docklet is first
+ * created, not when being recreated.
+ *
+ * The gtk docklet tracks whether it successfully embedded in a pref and
+ * allows for a longer timeout period if it successfully embedded the last
+ * time it was run. This should hopefully solve problems with the buddy
+ * list not properly starting hidden when Pidgin is started on login.
+ */
+ if (!recreate) {
+ pidgin_docklet_embedded();
+#if GTK_CHECK_VERSION(2,12,0)
+ if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) {
+ embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+ } else {
+ embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+ }
+#else
+ embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
+#endif
+ }
+
+ purple_debug_info("docklet", "GTK+ created\n");
+}
+
+/**************************************************************************
+ * public api
+ **************************************************************************/
+
void*
pidgin_docklet_get_handle()
{
@@ -843,10 +1043,20 @@ pidgin_docklet_init()
purple_prefs_connect_callback(docklet_handle, PIDGIN_PREFS_ROOT "/docklet/show",
docklet_show_pref_changed_cb, NULL);
- docklet_ui_init();
- if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always") && ui_ops && ui_ops->create)
- ui_ops->create();
+ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk");
+ if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) {
+ purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
+ purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded");
+ } else {
+ purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
+ }
+ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
+ DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray");
+
+ if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always"))
+ docklet_gtk_status_create(FALSE);
+
purple_signal_connect(conn_handle, "signed-on",
docklet_handle, PURPLE_CALLBACK(docklet_signed_on_cb), NULL);
purple_signal_connect(conn_handle, "signed-off",
@@ -874,6 +1084,7 @@ pidgin_docklet_uninit()
void
pidgin_docklet_uninit()
{
- if (visible && ui_ops && ui_ops->destroy)
- ui_ops->destroy();
+ if (visible)
+ docklet_gtk_status_destroy();
}
+
============================================================
--- pidgin/gtkdocklet-gtk.c 174469e45524ecfb6afcabdcc55bdd07664839ae
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * System tray icon (aka docklet) plugin for Purple
- *
- * Copyright (C) 2007 Anders Hasselqvist
- *
- * 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 "internal.h"
-#include "pidgin.h"
-#include "debug.h"
-#include "prefs.h"
-#include "pidginstock.h"
-#include "gtkdocklet.h"
-
-#define SHORT_EMBED_TIMEOUT 5
-#define LONG_EMBED_TIMEOUT 15
-
-/* globals */
-static GtkStatusIcon *docklet = NULL;
-static guint embed_timeout = 0;
-
-/* protos */
-static void docklet_gtk_status_create(gboolean);
-
-static gboolean
-docklet_gtk_recreate_cb(gpointer data)
-{
- docklet_gtk_status_create(TRUE);
-
- return FALSE;
-}
-
-static gboolean
-docklet_gtk_embed_timeout_cb(gpointer data)
-{
-#if !GTK_CHECK_VERSION(2,12,0)
- if (gtk_status_icon_is_embedded(docklet)) {
- /* Older GTK+ (<2.12) don't implement the embedded signal, but the
- information is still accessable through the above function. */
- purple_debug_info("docklet", "embedded\n");
-
- pidgin_docklet_embedded();
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
- }
- else
-#endif
- {
- /* The docklet was not embedded within the timeout.
- * Remove it as a visibility manager, but leave the plugin
- * loaded so that it can embed automatically if/when a notification
- * area becomes available.
- */
- purple_debug_info("docklet", "failed to embed within timeout\n");
- pidgin_docklet_remove();
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
- }
-
-#if GTK_CHECK_VERSION(2,12,0)
- embed_timeout = 0;
- return FALSE;
-#else
- return TRUE;
-#endif
-}
-
-#if GTK_CHECK_VERSION(2,12,0)
-static gboolean
-docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data)
-{
- if (embed_timeout) {
- purple_timeout_remove(embed_timeout);
- embed_timeout = 0;
- }
-
- if (gtk_status_icon_is_embedded(docklet)) {
- purple_debug_info("docklet", "embedded\n");
-
- pidgin_docklet_embedded();
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
- } else {
- purple_debug_info("docklet", "detached\n");
-
- pidgin_docklet_remove();
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
- }
-
- return TRUE;
-}
-#endif
-
-static void
-docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data)
-{
- purple_debug_info("docklet", "destroyed\n");
-
- pidgin_docklet_remove();
-
- g_object_unref(G_OBJECT(docklet));
- docklet = NULL;
-
- g_idle_add(docklet_gtk_recreate_cb, NULL);
-}
-
-static void
-docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data)
-{
- pidgin_docklet_clicked(1);
-}
-
-static void
-docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
-{
- purple_debug_info("docklet", "The button is %u\n", button);
-#ifdef GDK_WINDOWING_QUARTZ
- /* You can only click left mouse button on MacOSX native GTK. Let that be the menu */
- pidgin_docklet_clicked(3);
-#else
- pidgin_docklet_clicked(button);
-#endif
-}
-
-static void
-docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
-{
- const gchar *icon_name = NULL;
-
- switch (status) {
- case PURPLE_STATUS_OFFLINE:
- icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
- break;
- case PURPLE_STATUS_AWAY:
- icon_name = PIDGIN_STOCK_TRAY_AWAY;
- break;
- case PURPLE_STATUS_UNAVAILABLE:
- icon_name = PIDGIN_STOCK_TRAY_BUSY;
- break;
- case PURPLE_STATUS_EXTENDED_AWAY:
- icon_name = PIDGIN_STOCK_TRAY_XA;
- break;
- case PURPLE_STATUS_INVISIBLE:
- icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
- break;
- default:
- icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
- break;
- }
-
- if (pending)
- icon_name = PIDGIN_STOCK_TRAY_PENDING;
- if (connecting)
- icon_name = PIDGIN_STOCK_TRAY_CONNECT;
-
- if (icon_name) {
- gtk_status_icon_set_from_icon_name(docklet, icon_name);
- }
-
- if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) {
- gtk_status_icon_set_blinking(docklet, (pending && !connecting));
- } else if (gtk_status_icon_get_blinking(docklet)) {
- gtk_status_icon_set_blinking(docklet, FALSE);
- }
-}
-
-static void
-docklet_gtk_status_set_tooltip(gchar *tooltip)
-{
- gtk_status_icon_set_tooltip(docklet, tooltip);
-}
-
-static void
-docklet_gtk_status_position_menu(GtkMenu *menu,
- int *x, int *y, gboolean *push_in,
- gpointer user_data)
-{
- gtk_status_icon_position_menu(menu, x, y, push_in, docklet);
-}
-
-static void
-docklet_gtk_status_destroy(void)
-{
- g_return_if_fail(docklet != NULL);
-
- pidgin_docklet_remove();
-
- if (embed_timeout) {
- purple_timeout_remove(embed_timeout);
- embed_timeout = 0;
- }
-
- gtk_status_icon_set_visible(docklet, FALSE);
- g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
- g_object_unref(G_OBJECT(docklet));
- docklet = NULL;
-
- purple_debug_info("docklet", "GTK+ destroyed\n");
-}
-
-static void
-docklet_gtk_status_create(gboolean recreate)
-{
- if (docklet) {
- /* if this is being called when a tray icon exists, it's because
- something messed up. try destroying it before we proceed,
- although docklet_refcount may be all hosed. hopefully won't happen. */
- purple_debug_warning("docklet", "trying to create icon but it already exists?\n");
- docklet_gtk_status_destroy();
- }
-
- docklet = gtk_status_icon_new();
- g_return_if_fail(docklet != NULL);
-
- g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL);
- g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL);
-#if GTK_CHECK_VERSION(2,12,0)
- g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL);
-#endif
- g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL);
-
- gtk_status_icon_set_visible(docklet, TRUE);
-
- /* This is a hack to avoid a race condition between the docklet getting
- * embedded in the notification area and the gtkblist restoring its
- * previous visibility state. If the docklet does not get embedded within
- * the timeout, it will be removed as a visibility manager until it does
- * get embedded. Ideally, we would only call docklet_embedded() when the
- * icon was actually embedded. This only happens when the docklet is first
- * created, not when being recreated.
- *
- * The gtk docklet tracks whether it successfully embedded in a pref and
- * allows for a longer timeout period if it successfully embedded the last
- * time it was run. This should hopefully solve problems with the buddy
- * list not properly starting hidden when Pidgin is started on login.
- */
- if (!recreate) {
- pidgin_docklet_embedded();
-#if GTK_CHECK_VERSION(2,12,0)
- if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) {
- embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
- } else {
- embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
- }
-#else
- embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL);
-#endif
- }
-
- purple_debug_info("docklet", "GTK+ created\n");
-}
-
-static void
-docklet_gtk_status_create_ui_op(void)
-{
- docklet_gtk_status_create(FALSE);
-}
-
-static struct docklet_ui_ops ui_ops =
-{
- docklet_gtk_status_create_ui_op,
- docklet_gtk_status_destroy,
- docklet_gtk_status_update_icon,
- NULL,
- docklet_gtk_status_set_tooltip,
- docklet_gtk_status_position_menu
-};
-
-void
-docklet_ui_init(void)
-{
- pidgin_docklet_set_ui_ops(&ui_ops);
-
- purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk");
- if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) {
- purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE);
- purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded");
- } else {
- purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE);
- }
-
- gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
- DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray");
-}
-
More information about the Commits
mailing list