Mercurial > pidgin.yaz
comparison plugins/docklet/docklet.c @ 6208:3e3ee3cba192
[gaim-migrate @ 6694]
Robot101: I fixed the docklet stuff, little buglet with not redrawing after a redisplay, and I spiffed everything up and moved code around for no reason
committer: Tailor Script <tailor@pidgin.im>
author | Herman Bloggs <hermanator12002@yahoo.com> |
---|---|
date | Fri, 18 Jul 2003 03:45:39 +0000 |
parents | 16e384bb7fbf |
children | 9fd7716068d9 |
comparison
equal
deleted
inserted
replaced
6207:f78a42ef3101 | 6208:3e3ee3cba192 |
---|---|
1 /* System tray icon (aka docklet) plugin for Gaim | 1 /* |
2 * Copyright (C) 2002 Robert McQueen <robot101@debian.org> | 2 * System tray icon (aka docklet) plugin for Gaim |
3 * | |
4 * Copyright (C) 2002-3 Robert McQueen <robot101@debian.org> | |
3 * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com> | 5 * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com> |
4 * Inspired by a similar plugin by: | 6 * Inspired by a similar plugin by: |
5 * John (J5) Palmieri <johnp@martianrock.com> | 7 * John (J5) Palmieri <johnp@martianrock.com> |
6 * | 8 * |
7 * This program is free software; you can redistribute it and/or | 9 * This program is free software; you can redistribute it and/or |
25 - handle and update tooltips to show your current accounts/queued messages? | 27 - handle and update tooltips to show your current accounts/queued messages? |
26 - show a count of queued messages in the unified queue | 28 - show a count of queued messages in the unified queue |
27 - dernyi's account status menu in the right click | 29 - dernyi's account status menu in the right click |
28 - optional pop up notices when GNOME2's system-tray-applet supports it */ | 30 - optional pop up notices when GNOME2's system-tray-applet supports it */ |
29 | 31 |
30 /* includes */ | |
31 #include "internal.h" | 32 #include "internal.h" |
32 | 33 |
33 #include "core.h" | 34 #include "core.h" |
34 #include "debug.h" | 35 #include "debug.h" |
35 #include "prefs.h" | 36 #include "prefs.h" |
46 #include "docklet.h" | 47 #include "docklet.h" |
47 | 48 |
48 #include "gaim.h" | 49 #include "gaim.h" |
49 #include "ui.h" | 50 #include "ui.h" |
50 | 51 |
51 #define DOCKLET_PLUGIN_ID "gtk-docklet" | |
52 | |
53 /* globals */ | 52 /* globals */ |
54 static struct gaim_tray_ops *tray_ops = NULL; | 53 |
55 static enum docklet_status status=offline; | 54 GaimPlugin *handle = NULL; |
56 static enum docklet_status icon=offline; | 55 static struct docklet_ui_ops *ui_ops = NULL; |
56 static enum docklet_status status = offline; | |
57 static enum docklet_status icon = offline; | |
57 #ifdef _WIN32 | 58 #ifdef _WIN32 |
58 __declspec(dllimport) GSList *unread_message_queue; | 59 __declspec(dllimport) GSList *unread_message_queue; |
59 __declspec(dllimport) GSList *away_messages; | 60 __declspec(dllimport) GSList *away_messages; |
60 __declspec(dllimport) struct away_message *awaymessage; | 61 __declspec(dllimport) struct away_message *awaymessage; |
61 __declspec(dllimport) GSList *message_queue; | 62 __declspec(dllimport) GSList *message_queue; |
62 #endif | 63 #endif |
63 | 64 |
64 /* functions */ | 65 /* private functions */ |
65 extern void trayicon_init(); | 66 |
66 static gboolean docklet_update_status(); | 67 static void |
67 static gboolean plugin_unload(GaimPlugin *plugin); | 68 docklet_toggle_mute(GtkWidget *toggle, void *data) |
68 | 69 { |
69 static void docklet_toggle_mute(GtkWidget *toggle, void *data) { | |
70 gaim_gtk_sound_set_mute(GTK_CHECK_MENU_ITEM(toggle)->active); | 70 gaim_gtk_sound_set_mute(GTK_CHECK_MENU_ITEM(toggle)->active); |
71 } | 71 } |
72 | 72 |
73 static void docklet_set_bool(GtkWidget *widget, const char *key) { | 73 static void |
74 docklet_set_bool(GtkWidget *widget, const char *key) | |
75 { | |
74 gaim_prefs_set_bool(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); | 76 gaim_prefs_set_bool(key, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); |
75 } | 77 } |
76 | 78 |
77 static void docklet_auto_login() { | 79 static void |
80 docklet_auto_login() | |
81 { | |
78 gaim_accounts_auto_login(GAIM_GTK_UI); | 82 gaim_accounts_auto_login(GAIM_GTK_UI); |
79 } | 83 } |
80 | 84 |
81 #ifdef _WIN32 | 85 #ifdef _WIN32 |
82 /* This is a workaround for a bug in windows GTK+.. Clicking outside of the | 86 /* This is a workaround for a bug in windows GTK+.. Clicking outside of the |
83 menu does not get rid of it, so instead we get rid of it as soon as the | 87 menu does not get rid of it, so instead we get rid of it as soon as the |
84 pointer leaves the menu. */ | 88 pointer leaves the menu. */ |
85 static gboolean menu_leave(GtkWidget *menu, | 89 static gboolean |
86 GdkEventCrossing *event, | 90 docklet_menu_leave(GtkWidget *menu, GdkEventCrossing *event, void *data) |
87 gpointer user_data) { | 91 { |
88 if(event->detail == GDK_NOTIFY_ANCESTOR) { | 92 if(event->detail == GDK_NOTIFY_ANCESTOR) { |
89 gaim_debug(GAIM_DEBUG_INFO, "docklet", "leave-notify-event\n"); | 93 gaim_debug(GAIM_DEBUG_INFO, "tray icon", "menu leave-notify-event\n"); |
90 gtk_menu_popdown(GTK_MENU(menu)); | 94 gtk_menu_popdown(GTK_MENU(menu)); |
91 } | 95 } |
92 return FALSE; | 96 return FALSE; |
93 } | 97 } |
94 #endif | 98 #endif |
100 if (menu) { | 104 if (menu) { |
101 gtk_widget_destroy(menu); | 105 gtk_widget_destroy(menu); |
102 } | 106 } |
103 | 107 |
104 menu = gtk_menu_new(); | 108 menu = gtk_menu_new(); |
105 #ifdef _WIN32 | 109 |
106 g_signal_connect(menu, "leave-notify-event", G_CALLBACK(menu_leave), NULL); | |
107 #endif | |
108 switch (status) { | 110 switch (status) { |
109 case offline: | 111 case offline: |
110 case offline_connecting: | 112 case offline_connecting: |
111 gaim_new_item_from_stock(menu, _("Auto-login"), GAIM_STOCK_SIGN_ON, G_CALLBACK(docklet_auto_login), NULL, 0, 0, NULL); | 113 gaim_new_item_from_stock(menu, _("Auto-login"), GAIM_STOCK_SIGN_ON, G_CALLBACK(docklet_auto_login), NULL, 0, 0, NULL); |
112 break; | 114 break; |
181 break; | 183 break; |
182 } | 184 } |
183 | 185 |
184 gaim_new_item_from_stock(menu, _("Quit"), GTK_STOCK_QUIT, G_CALLBACK(gaim_core_quit), NULL, 0, 0, 0); | 186 gaim_new_item_from_stock(menu, _("Quit"), GTK_STOCK_QUIT, G_CALLBACK(gaim_core_quit), NULL, 0, 0, 0); |
185 | 187 |
188 #ifdef _WIN32 | |
189 g_signal_connect(menu, "leave-notify-event", G_CALLBACK(docklet_menu_leave), NULL); | |
190 #endif | |
186 gtk_widget_show_all(menu); | 191 gtk_widget_show_all(menu); |
187 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); | 192 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); |
188 } | 193 } |
189 | 194 |
190 static gboolean docklet_blink_icon() { | 195 static gboolean |
196 docklet_blink_icon() | |
197 { | |
191 if (status == online_pending) { | 198 if (status == online_pending) { |
192 if (status == icon) { | 199 if (status == icon) { |
193 /* last icon was the right one... let's change it */ | 200 /* last icon was the right one... let's change it */ |
194 icon = online; | 201 icon = online; |
195 } else { | 202 } else { |
207 } else { | 214 } else { |
208 /* no messages, stop blinking */ | 215 /* no messages, stop blinking */ |
209 return FALSE; | 216 return FALSE; |
210 } | 217 } |
211 | 218 |
212 if(tray_ops->update_icon) | 219 if (ui_ops->update_icon) |
213 tray_ops->update_icon(icon); | 220 ui_ops->update_icon(icon); |
214 | 221 |
215 return TRUE; /* keep blinking */ | 222 return TRUE; /* keep blinking */ |
216 } | 223 } |
217 | 224 |
218 static gboolean docklet_update_status() { | 225 static gboolean |
226 docklet_update_status() | |
227 { | |
219 enum docklet_status oldstatus; | 228 enum docklet_status oldstatus; |
220 | 229 |
221 oldstatus = status; | 230 oldstatus = status; |
222 | 231 |
223 if (gaim_connections_get_all()) { | 232 if (gaim_connections_get_all()) { |
243 } | 252 } |
244 | 253 |
245 /* update the icon if we changed status */ | 254 /* update the icon if we changed status */ |
246 if (status != oldstatus) { | 255 if (status != oldstatus) { |
247 icon = status; | 256 icon = status; |
248 if(tray_ops->update_icon) | 257 if (ui_ops->update_icon) |
249 tray_ops->update_icon(icon); | 258 ui_ops->update_icon(icon); |
250 | 259 |
251 /* and schedule the blinker function if messages are pending */ | 260 /* and schedule the blinker function if messages are pending */ |
252 if (status == online_pending || status == away_pending) { | 261 if (status == online_pending || status == away_pending) { |
253 g_timeout_add(500, docklet_blink_icon, NULL); | 262 g_timeout_add(500, docklet_blink_icon, NULL); |
254 } | 263 } |
255 } | 264 } |
265 | |
256 return FALSE; /* for when we're called by the glib idle handler */ | 266 return FALSE; /* for when we're called by the glib idle handler */ |
257 } | 267 } |
258 | 268 |
259 static void gaim_signon(GaimConnection *gc, void *data) { | 269 void |
260 docklet_update_status(); | 270 docklet_flush_queue() |
261 } | 271 { |
262 | 272 if (unread_message_queue) { |
263 static void gaim_signoff(GaimConnection *gc, void *data) { | 273 purge_away_queue(&unread_message_queue); |
264 /* do this when idle so that if the prpl was connecting | 274 } |
265 and was cancelled, we register that connecting_count | 275 } |
266 has returned to 0 */ | 276 |
267 /* no longer necessary because Chip decided that us plugins | 277 void |
268 * didn't need to know if an account was connecting or not | 278 docklet_remove_callbacks() |
269 * g_idle_add(docklet_update_status, &docklet); */ | 279 { |
270 docklet_update_status(); | 280 gaim_debug(GAIM_DEBUG_INFO, "tray icon", "removing callbacks"); |
271 } | 281 |
272 | 282 while (g_source_remove_by_user_data(&handle)) { |
273 static void gaim_connecting(GaimAccount *account, void *data) { | 283 gaim_debug(GAIM_DEBUG_INFO, NULL, "."); |
274 docklet_update_status(); | 284 } |
275 } | 285 |
276 | 286 gaim_debug(GAIM_DEBUG_INFO, NULL, "\n"); |
277 static void gaim_away(GaimConnection *gc, char *state, char *message, void *data) { | 287 } |
278 /* we only support global away. this is the way it is, ok? */ | 288 |
279 docklet_update_status(); | 289 /* public code */ |
280 } | 290 |
281 | 291 void |
282 static void gaim_im_recv(GaimConnection *gc, char **who, char **what, void *data) { | 292 docklet_clicked(int button_type) |
283 /* if message queuing while away is enabled, this event could be the first | 293 { |
284 message so we need to see if the status (and hence icon) needs changing. | |
285 do this when idle so that all message processing is completed, queuing | |
286 etc, before we run. */ | |
287 g_idle_add(docklet_update_status, NULL); | |
288 } | |
289 | |
290 /* static void gaim_buddy_signon(GaimConnection *gc, char *who, void *data) { | |
291 } | |
292 | |
293 static void gaim_buddy_signoff(GaimConnection *gc, char *who, void *data) { | |
294 } | |
295 | |
296 static void gaim_buddy_away(GaimConnection *gc, char *who, void *data) { | |
297 } | |
298 | |
299 static void gaim_buddy_back(GaimConnection *gc, char *who, void *data) { | |
300 } | |
301 | |
302 static void gaim_new_conversation(char *who, void *data) { | |
303 } */ | |
304 | |
305 /* | |
306 * Public Code | |
307 */ | |
308 void docklet_clicked(int button_type) { | |
309 switch (button_type) { | 294 switch (button_type) { |
310 case 1: | 295 case 1: |
311 if (unread_message_queue) { | 296 if (unread_message_queue) { |
312 docklet_flush_queue(); | 297 docklet_flush_queue(); |
313 docklet_update_status(); | 298 g_idle_add(docklet_update_status, &handle); |
314 } else { | 299 } else { |
315 gaim_gtk_blist_docklet_toggle(); | 300 gaim_gtk_blist_docklet_toggle(); |
316 } | 301 } |
317 break; | 302 break; |
318 case 2: | 303 case 2: |
329 docklet_menu(); | 314 docklet_menu(); |
330 break; | 315 break; |
331 } | 316 } |
332 } | 317 } |
333 | 318 |
334 void docklet_embedded() { | 319 void |
335 gaim_debug(GAIM_DEBUG_INFO, "docklet", "Tray Icon: embedded\n"); | 320 docklet_embedded() |
321 { | |
336 gaim_gtk_blist_docklet_add(); | 322 gaim_gtk_blist_docklet_add(); |
337 } | 323 |
338 | 324 docklet_update_status(); |
339 void docklet_flush_queue() { | 325 if (ui_ops->update_icon) |
340 if (unread_message_queue) { | 326 ui_ops->update_icon(icon); |
341 purge_away_queue(&unread_message_queue); | 327 } |
342 } | 328 |
343 } | 329 void |
344 | 330 docklet_remove(gboolean visible) |
345 | 331 { |
346 /* Set Platform Dependent Code */ | 332 if (visible) |
347 void docklet_set_tray_ops(struct gaim_tray_ops *ops) { | 333 gaim_gtk_blist_docklet_remove(); |
348 tray_ops = ops; | 334 |
349 } | 335 docklet_flush_queue(); |
350 | 336 } |
351 | 337 |
352 /* | 338 void |
353 * PLUGIN CODE | 339 docklet_set_ui_ops(struct docklet_ui_ops *ops) |
354 */ | 340 { |
341 ui_ops = ops; | |
342 } | |
343 | |
344 /* callbacks */ | |
345 | |
346 static void | |
347 gaim_signon(GaimConnection *gc, void *data) | |
348 { | |
349 docklet_update_status(); | |
350 } | |
351 | |
352 static void | |
353 gaim_signoff(GaimConnection *gc, void *data) | |
354 { | |
355 /* do this when idle so that if the prpl was connecting | |
356 and was cancelled, we register that connecting_count | |
357 has returned to 0 */ | |
358 /* no longer necessary because Chip decided that us plugins | |
359 didn't need to know if an account was connecting or not | |
360 g_idle_add(docklet_update_status, &docklet); */ | |
361 docklet_update_status(); | |
362 } | |
363 | |
364 static void | |
365 gaim_connecting(GaimAccount *account, void *data) | |
366 { | |
367 docklet_update_status(); | |
368 } | |
369 | |
370 static void | |
371 gaim_away(GaimConnection *gc, char *state, char *message, void *data) | |
372 { | |
373 /* we only support global away. this is the way it is, ok? */ | |
374 docklet_update_status(); | |
375 } | |
376 | |
377 static void | |
378 gaim_im_recv(GaimConnection *gc, char **who, char **what, void *data) | |
379 { | |
380 /* if message queuing while away is enabled, this event could be the first | |
381 message so we need to see if the status (and hence icon) needs changing. | |
382 do this when idle so that all message processing is completed, queuing | |
383 etc, before we run. */ | |
384 g_idle_add(docklet_update_status, &handle); | |
385 } | |
386 | |
387 /* static void gaim_buddy_signon(GaimConnection *gc, char *who, void *data) { | |
388 } | |
389 | |
390 static void gaim_buddy_signoff(GaimConnection *gc, char *who, void *data) { | |
391 } | |
392 | |
393 static void gaim_buddy_away(GaimConnection *gc, char *who, void *data) { | |
394 } | |
395 | |
396 static void gaim_buddy_back(GaimConnection *gc, char *who, void *data) { | |
397 } | |
398 | |
399 static void gaim_new_conversation(char *who, void *data) { | |
400 } */ | |
401 | |
402 /* plugin glue */ | |
403 | |
404 #define DOCKLET_PLUGIN_ID "gtk-docklet" | |
355 | 405 |
356 static gboolean | 406 static gboolean |
357 plugin_load(GaimPlugin *plugin) | 407 plugin_load(GaimPlugin *plugin) |
358 { | 408 { |
359 trayicon_init(); | 409 gaim_debug(GAIM_DEBUG_INFO, "tray icon", "plugin loaded\n"); |
360 if(tray_ops->create) | 410 |
361 tray_ops->create(); | 411 handle = plugin; |
362 | 412 |
363 gaim_prefs_add_none("/plugins/gtk/docklet"); | 413 docklet_ui_init(); |
364 gaim_prefs_add_bool("/plugins/gtk/docklet/queue_messages", FALSE); | 414 if (ui_ops->create) |
365 | 415 ui_ops->create(); |
366 docklet_update_status(); | |
367 if(tray_ops->update_icon) | |
368 tray_ops->update_icon(icon); | |
369 | 416 |
370 gaim_signal_connect(plugin, event_signon, gaim_signon, NULL); | 417 gaim_signal_connect(plugin, event_signon, gaim_signon, NULL); |
371 gaim_signal_connect(plugin, event_signoff, gaim_signoff, NULL); | 418 gaim_signal_connect(plugin, event_signoff, gaim_signoff, NULL); |
372 gaim_signal_connect(plugin, event_connecting, gaim_connecting, NULL); | 419 gaim_signal_connect(plugin, event_connecting, gaim_connecting, NULL); |
373 gaim_signal_connect(plugin, event_away, gaim_away, NULL); | 420 gaim_signal_connect(plugin, event_away, gaim_away, NULL); |
376 gaim_signal_connect(plugin, event_buddy_signoff, gaim_buddy_signoff, NULL); | 423 gaim_signal_connect(plugin, event_buddy_signoff, gaim_buddy_signoff, NULL); |
377 gaim_signal_connect(plugin, event_buddy_away, gaim_buddy_away, NULL); | 424 gaim_signal_connect(plugin, event_buddy_away, gaim_buddy_away, NULL); |
378 gaim_signal_connect(plugin, event_buddy_back, gaim_buddy_back, NULL); | 425 gaim_signal_connect(plugin, event_buddy_back, gaim_buddy_back, NULL); |
379 gaim_signal_connect(plugin, event_new_conversation, gaim_new_conversation, NULL); */ | 426 gaim_signal_connect(plugin, event_new_conversation, gaim_new_conversation, NULL); */ |
380 | 427 |
381 gaim_debug(GAIM_DEBUG_INFO, "docklet", "Plugin loaded\n"); | 428 gaim_prefs_add_none("/plugins/gtk/docklet"); |
429 gaim_prefs_add_bool("/plugins/gtk/docklet/queue_messages", FALSE); | |
382 | 430 |
383 return TRUE; | 431 return TRUE; |
384 } | 432 } |
385 | 433 |
386 static gboolean | 434 static gboolean |
387 plugin_unload(GaimPlugin *plugin) | 435 plugin_unload(GaimPlugin *plugin) |
388 { | 436 { |
389 gaim_gtk_blist_docklet_remove(); | 437 if (ui_ops->destroy) |
390 docklet_flush_queue(); | 438 ui_ops->destroy(); |
439 | |
391 /* XXX: do this while gaim has no other way to toggle the global mute */ | 440 /* XXX: do this while gaim has no other way to toggle the global mute */ |
392 gaim_gtk_sound_set_mute(FALSE); | 441 gaim_gtk_sound_set_mute(FALSE); |
393 | 442 docklet_remove_callbacks(); |
394 if(tray_ops->destroy) | 443 |
395 tray_ops->destroy(); | 444 gaim_debug(GAIM_DEBUG_INFO, "tray icon", "plugin unloaded\n"); |
396 | |
397 gaim_debug(GAIM_DEBUG_INFO, "docklet", "Plugin unloaded\n"); | |
398 | 445 |
399 return TRUE; | 446 return TRUE; |
400 } | 447 } |
401 | 448 |
402 static GtkWidget * | 449 static GtkWidget * |
403 get_config_frame(GaimPlugin *plugin) | 450 plugin_config_frame(GaimPlugin *plugin) |
404 { | 451 { |
405 GtkWidget *frame; | 452 GtkWidget *frame; |
406 GtkWidget *vbox, *hbox; | 453 GtkWidget *vbox, *hbox; |
407 GtkWidget *toggle; | 454 GtkWidget *toggle; |
408 static const char *qmpref = "/plugins/gtk/docklet/queue_messages"; | 455 static const char *qmpref = "/plugins/gtk/docklet/queue_messages"; |
423 return frame; | 470 return frame; |
424 } | 471 } |
425 | 472 |
426 static GaimGtkPluginUiInfo ui_info = | 473 static GaimGtkPluginUiInfo ui_info = |
427 { | 474 { |
428 get_config_frame | 475 plugin_config_frame |
429 }; | 476 }; |
430 | 477 |
431 static GaimPluginInfo info = | 478 static GaimPluginInfo info = |
432 { | 479 { |
433 2, /**< api_version */ | 480 2, /**< api_version */ |
441 N_("System Tray Icon"), /**< name */ | 488 N_("System Tray Icon"), /**< name */ |
442 VERSION, /**< version */ | 489 VERSION, /**< version */ |
443 /** summary */ | 490 /** summary */ |
444 N_("Displays an icon for Gaim in the system tray."), | 491 N_("Displays an icon for Gaim in the system tray."), |
445 /** description */ | 492 /** description */ |
446 N_("Interacts with a Notification Area applet (in GNOME, KDE or " | 493 N_("Displays a system tray icon (in GNOME, KDE or Windows for example) " |
447 "Windows for example) to display the current status of Gaim, allow " | 494 "to show the current status of Gaim, allow fast access to commonly " |
448 "fast access to commonly used functions, and to toggle display of " | 495 "used functions, and to toggle display of the buddy list or login " |
449 "the buddy list or login window. Also allows messages to be queued " | 496 "window. Also allows messages to be queued until the icon is " |
450 "until the icon is clicked, similar to ICQ."), | 497 "clicked, similar to ICQ."), |
451 "Robert McQueen <robot101@debian.org>", /**< author */ | 498 "Robert McQueen <robot101@debian.org>", /**< author */ |
452 WEBSITE, /**< homepage */ | 499 WEBSITE, /**< homepage */ |
453 | 500 |
454 plugin_load, /**< load */ | 501 plugin_load, /**< load */ |
455 plugin_unload, /**< unload */ | 502 plugin_unload, /**< unload */ |
458 &ui_info, /**< ui_info */ | 505 &ui_info, /**< ui_info */ |
459 NULL /**< extra_info */ | 506 NULL /**< extra_info */ |
460 }; | 507 }; |
461 | 508 |
462 static void | 509 static void |
463 init_plugin(GaimPlugin *plugin) | 510 plugin_init(GaimPlugin *plugin) |
464 { | 511 { |
465 } | 512 } |
466 | 513 |
467 GAIM_INIT_PLUGIN(docklet, init_plugin, info) | 514 GAIM_INIT_PLUGIN(docklet, plugin_init, info) |