plugins/notify.c

branch
cpw.khc.msnp14
changeset 20472
6a6d2ef151e6
parent 13912
463b4fa9f067
parent 20469
b2836a24d81e
child 20473
91e1b3a49d10
equal deleted inserted replaced
13912:463b4fa9f067 20472:6a6d2ef151e6
1 /*
2 * Gaim buddy notification plugin.
3 *
4 * Copyright (C) 2000-2001, Eric Warmenhoven (original code)
5 * Copyright (C) 2002, Etan Reisner <deryni@eden.rutgers.edu> (rewritten code)
6 * Copyright (C) 2003, Christian Hammond (update for changed API)
7 * Copyright (C) 2003, Brian Tarricone <bjt23@cornell.edu> (mostly rewritten)
8 * Copyright (C) 2003, Mark Doliner (minor cleanup)
9 * Copyright (C) 2003, Etan Reisner (largely rewritten again)
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27 /* TODO
28 * 22:22:17 <seanegan> deryni: speaking of notify.c... you know what else
29 * might be a neat feature?
30 * 22:22:30 <seanegan> Changing the window icon.
31 * 22:23:25 <deryni> seanegan: To what?
32 * 22:23:42 <seanegan> deryni: I dunno. Flash it between the regular icon and
33 * blank or something.
34 * 22:23:53 <deryni> Also I think gaim might re-set that sort of frequently,
35 * but I'd have to look.
36 * 22:25:16 <seanegan> deryni: I keep my conversations in one workspace and am
37 * frequently in an another, and the icon flashing in the pager would be a
38 * neat visual clue.
39 */
40
41 /*
42 * From Etan, 2002:
43 * -Added config dialog
44 * -Added control over notification method
45 * -Added control over when to release notification
46 *
47 * -Added option to get notification for chats also
48 * -Cleaned up code
49 * -Added option to notify on click as it's own option
50 * rather then as what happens when on focus isn't clicked
51 * -Added apply button to change the denotification methods for
52 * open conversation windows
53 * -Fixed apply to conversations, count now keeps count across applies
54 * -Fixed(?) memory leak, and in the process fixed some stupidities
55 * -Hit enter when done editing the title string entry box to save it
56 *
57 * Thanks to Carles Pina i Estany <carles@pinux.info>
58 * for count of new messages option
59 *
60 * From Brian, 20 July 2003:
61 * -Use new xml prefs
62 * -Better handling of notification states tracking
63 * -Better pref change handling
64 * -Fixed a possible memleak and possible crash (rare)
65 * -Use gtk_window_get_title() rather than gtkwin->title
66 * -Other random fixes and cleanups
67 *
68 * Etan again, 12 August 2003:
69 * -Better use of the new xml prefs
70 * -Removed all bitmask stuff
71 * -Even better pref change handling
72 * -Removed unnecessary functions
73 * -Reworking of notification/unnotification stuff
74 * -Header file include cleanup
75 * -General code cleanup
76 *
77 * Etan yet again, 04 April 2004:
78 * -Re-added Urgent option
79 * -Re-added unnotify on focus option (still needs work, as it will only
80 * react to focus-in events when the entry or history widgets are focused)
81 *
82 * Sean, 08 January, 2005:
83 * -Added Raise option, formally in Gaim proper
84 */
85
86 #include "internal.h"
87 #include "gtkgaim.h"
88 #include "gtkprefs.h"
89
90 #include "conversation.h"
91 #include "prefs.h"
92 #include "signals.h"
93 #include "version.h"
94 #include "debug.h"
95
96 #include "gtkplugin.h"
97 #include "gtkutils.h"
98
99 #ifndef _WIN32
100 #include <X11/Xatom.h>
101 #include <X11/Xlib.h>
102 #include <X11/Xutil.h>
103 #endif
104
105 #define NOTIFY_PLUGIN_ID "gtk-x11-notify"
106
107 static GaimPlugin *my_plugin = NULL;
108
109 /* notification set/unset */
110 static int notify(GaimConversation *conv, gboolean increment);
111 static void notify_win(GaimGtkWindow *gaimwin);
112 static void unnotify(GaimConversation *conv, gboolean reset);
113 static int unnotify_cb(GtkWidget *widget, gpointer data, GaimConversation *conv);
114
115 /* gtk widget callbacks for prefs panel */
116 static void type_toggle_cb(GtkWidget *widget, gpointer data);
117 static void method_toggle_cb(GtkWidget *widget, gpointer data);
118 static void notify_toggle_cb(GtkWidget *widget, gpointer data);
119 static gboolean options_entry_cb(GtkWidget *widget, GdkEventFocus *event, gpointer data);
120 static void apply_method(void);
121 static void apply_notify(void);
122
123 /* string function */
124 static void handle_string(GaimGtkWindow *gaimwin);
125
126 /* count function */
127 static void handle_count(GaimGtkWindow *gaimwin);
128
129 /* urgent function */
130 static void handle_urgent(GaimGtkWindow *gaimwin, gboolean add);
131
132 /* raise function */
133 static void handle_raise(GaimGtkWindow *gaimwin);
134
135 /****************************************/
136 /* Begin doing stuff below this line... */
137 /****************************************/
138 static int
139 count_messages(GaimGtkWindow *gaimwin)
140 {
141 gint count = 0;
142 GList *convs = NULL, *l;
143
144 for (convs = gaimwin->gtkconvs; convs != NULL; convs = convs->next) {
145 GaimGtkConversation *conv = convs->data;
146 for (l = conv->convs; l != NULL; l = l->next) {
147 count += GPOINTER_TO_INT(gaim_conversation_get_data(l->data, "notify-message-count"));
148 }
149 }
150
151 return count;
152 }
153
154 static int
155 notify(GaimConversation *conv, gboolean increment)
156 {
157 GaimGtkWindow *gaimwin = NULL;
158 gint count;
159 gboolean has_focus;
160
161 if (conv == NULL)
162 return 0;
163
164 /* We want to remove the notifications, but not reset the counter */
165 unnotify(conv, FALSE);
166
167 gaimwin = GAIM_GTK_CONVERSATION(conv)->win;
168
169 /* If we aren't doing notifications for this type of conversation, return */
170 if (((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM) &&
171 !gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_im")) ||
172 ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT) &&
173 !gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat")))
174 return 0;
175
176 g_object_get(G_OBJECT(gaimwin->window),
177 "has-toplevel-focus", &has_focus, NULL);
178
179 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_focused") ||
180 !has_focus) {
181 if (increment) {
182 count = GPOINTER_TO_INT(gaim_conversation_get_data(conv, "notify-message-count"));
183 count++;
184 gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count));
185 }
186
187 notify_win(gaimwin);
188 }
189
190 return 0;
191 }
192
193 static void
194 notify_win(GaimGtkWindow *gaimwin)
195 {
196 if (count_messages(gaimwin) <= 0)
197 return;
198
199 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count"))
200 handle_count(gaimwin);
201 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string"))
202 handle_string(gaimwin);
203 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_urgent"))
204 handle_urgent(gaimwin, TRUE);
205 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_raise"))
206 handle_raise(gaimwin);
207 }
208
209 static void
210 unnotify(GaimConversation *conv, gboolean reset)
211 {
212 GaimConversation *active_conv = NULL;
213 GaimGtkWindow *gaimwin = NULL;
214
215 g_return_if_fail(conv != NULL);
216
217 gaimwin = GAIM_GTK_CONVERSATION(conv)->win;
218 active_conv = gaim_gtk_conv_window_get_active_conversation(gaimwin);
219
220 /* reset the conversation window title */
221 gaim_conversation_autoset_title(active_conv);
222
223 if (reset) {
224 /* Only need to actually remove the urgent hinting here, since removing it
225 * just to have it readded in re-notify is an unnecessary couple extra RTs
226 * to the server */
227 handle_urgent(gaimwin, FALSE);
228 gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
229 }
230
231 return;
232 }
233
234 static int
235 unnotify_cb(GtkWidget *widget, gpointer data, GaimConversation *conv)
236 {
237 if (GPOINTER_TO_INT(gaim_conversation_get_data(conv, "notify-message-count")) != 0)
238 unnotify(conv, TRUE);
239
240 return 0;
241 }
242
243 static gboolean
244 message_displayed_cb(GaimAccount *account, const char *who, char *message,
245 GaimConversation *conv, GaimMessageFlags flags)
246 {
247 if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT &&
248 gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick") &&
249 !(flags & GAIM_MESSAGE_NICK)))
250 return FALSE;
251
252 if ((flags & GAIM_MESSAGE_RECV) && !(flags & GAIM_MESSAGE_DELAYED))
253 notify(conv, TRUE);
254
255 return FALSE;
256 }
257
258 static void
259 im_sent_im(GaimAccount *account, const char *receiver, const char *message) {
260 GaimConversation *conv = NULL;
261
262 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) {
263 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, receiver, account);
264 unnotify(conv, TRUE);
265 }
266 }
267
268 static void
269 chat_sent_im(GaimAccount *account, const char *message, int id)
270 {
271 GaimConversation *conv = NULL;
272
273 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) {
274 conv = gaim_find_chat(gaim_account_get_connection(account), id);
275 unnotify(conv, TRUE);
276 }
277 }
278
279 static int
280 attach_signals(GaimConversation *conv)
281 {
282 GaimGtkConversation *gtkconv = NULL;
283 GaimGtkWindow *gtkwin = NULL;
284 GSList *imhtml_ids = NULL, *entry_ids = NULL;
285 guint id;
286
287 gtkconv = GAIM_GTK_CONVERSATION(conv);
288 if (!gtkconv) {
289 gaim_debug_misc("notify", "Failed to find gtkconv\n");
290 return 0;
291 }
292
293 gtkwin = gtkconv->win;
294
295 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus")) {
296 /* TODO should really find a way to make this work no matter where the
297 * focus is inside the conv window, without having to bind to
298 * focus-in-event on the g(d|t)kwindow */
299 /* try setting the signal on the focus-in-event for
300 * gtkwin->notebook->container? */
301 id = g_signal_connect(G_OBJECT(gtkconv->entry), "focus-in-event",
302 G_CALLBACK(unnotify_cb), conv);
303 entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
304
305 id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "focus-in-event",
306 G_CALLBACK(unnotify_cb), conv);
307 imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
308 }
309
310 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click")) {
311 /* TODO similarly should really find a way to allow for clicking in other
312 * places of the window */
313 id = g_signal_connect(G_OBJECT(gtkconv->entry), "button-press-event",
314 G_CALLBACK(unnotify_cb), conv);
315 entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
316
317 id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "button-press-event",
318 G_CALLBACK(unnotify_cb), conv);
319 imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id));
320 }
321
322 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_type")) {
323 id = g_signal_connect(G_OBJECT(gtkconv->entry), "key-press-event",
324 G_CALLBACK(unnotify_cb), conv);
325 entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
326 }
327
328 gaim_conversation_set_data(conv, "notify-imhtml-signals", imhtml_ids);
329 gaim_conversation_set_data(conv, "notify-entry-signals", entry_ids);
330
331 return 0;
332 }
333
334 static void
335 detach_signals(GaimConversation *conv)
336 {
337 GaimGtkConversation *gtkconv = NULL;
338 GaimGtkWindow *gtkwin = NULL;
339 GSList *ids = NULL, *l;
340
341 gtkconv = GAIM_GTK_CONVERSATION(conv);
342 if (!gtkconv)
343 return;
344 gtkwin = gtkconv->win;
345
346 ids = gaim_conversation_get_data(conv, "notify-imhtml-signals");
347 for (l = ids; l != NULL; l = l->next)
348 g_signal_handler_disconnect(gtkconv->imhtml, GPOINTER_TO_INT(l->data));
349 g_slist_free(ids);
350
351 ids = gaim_conversation_get_data(conv, "notify-entry-signals");
352 for (l = ids; l != NULL; l = l->next)
353 g_signal_handler_disconnect(gtkconv->entry, GPOINTER_TO_INT(l->data));
354 g_slist_free(ids);
355
356 gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
357
358 gaim_conversation_set_data(conv, "notify-imhtml-signals", NULL);
359 gaim_conversation_set_data(conv, "notify-entry-signals", NULL);
360 }
361
362 static void
363 conv_created(GaimConversation *conv)
364 {
365 gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
366
367 /* always attach the signals, notify() will take care of conversation type
368 * checking */
369 attach_signals(conv);
370 }
371
372 static void
373 conv_switched(GaimConversation *conv)
374 {
375 #if 0
376 GaimGtkWindow *gaimwin = gaim_conversation_get_window(new_conv);
377 #endif
378
379 /*
380 * If the conversation was switched, then make sure we re-notify
381 * because Gaim will have overwritten our custom window title.
382 */
383 notify(conv, FALSE);
384
385 #if 0
386 printf("conv_switched - %p - %p\n", old_conv, new_conv);
387 printf("count - %d\n", count_messages(gaimwin));
388 if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_switch"))
389 unnotify(new_conv, FALSE);
390 else {
391 /* if we don't have notification on the window then we don't want to
392 * re-notify it */
393 if (count_messages(gaimwin))
394 notify_win(gaimwin);
395 }
396 #endif
397 }
398
399 static void
400 deleting_conv(GaimConversation *conv)
401 {
402 GaimGtkWindow *gaimwin = NULL;
403
404 detach_signals(conv);
405
406 gaimwin = GAIM_GTK_CONVERSATION(conv)->win;
407
408 handle_urgent(gaimwin, FALSE);
409 gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
410
411 return;
412
413 #if 0
414 /* i think this line crashes */
415 if (count_messages(gaimwin))
416 notify_win(gaimwin);
417 #endif
418 }
419
420 #if 0
421 static void
422 conversation_dragging(GaimConversation *active_conv,
423 GaimGtkWindow *old_gaimwin,
424 GaimGtkWindow *new_gaimwin)
425 {
426 if (old_gaimwin != new_gaimwin) {
427 if (old_gaimwin == NULL) {
428 /*
429 gaim_conversation_autoset_title(active_conv);
430 handle_urgent(new_gaimwin, FALSE);
431 */
432
433 if (count_messages(new_gaimwin))
434 notify_win(new_gaimwin);
435 } else {
436 printf("if else count = %d\n", count_messages(new_gaimwin));
437 printf("if else count = %d\n", count_messages(old_gaimwin));
438 /*
439 GaimConversation *old_active_conv = NULL;
440 old_active_conv = gaim_conv_window_get_active_conversation(new_gaimwin);
441
442 gaim_conversation_autoset_title(old_active_conv);
443 handle_urgent(old_gaimwin, FALSE);
444
445 if (count_messages(old_gaimwin))
446 notify_win(old_gaimwin);
447
448 gaim_conversation_autoset_title(active_conv);
449 handle_urgent(new_gaimwin, FALSE);
450
451 if (count_messages(new_gaimwin))
452 notify_win(new_gaimwin);
453 */
454 }
455 } else {
456 printf("else count = %d\n", count_messages(new_gaimwin));
457 printf("else count = %d\n", count_messages(old_gaimwin));
458 /*
459 gaim_conversation_autoset_title(active_conv);
460 handle_urgent(old_gaimwin, FALSE);
461
462 if (count_messages(old_gaimwin))
463 notify_win(old_gaimwin);
464 */
465 }
466 }
467 #endif
468
469 static void
470 handle_string(GaimGtkWindow *gaimwin)
471 {
472 GtkWindow *window = NULL;
473 gchar newtitle[256];
474
475 g_return_if_fail(gaimwin != NULL);
476
477 window = GTK_WINDOW(gaimwin->window);
478 g_return_if_fail(window != NULL);
479
480 g_snprintf(newtitle, sizeof(newtitle), "%s%s",
481 gaim_prefs_get_string("/plugins/gtk/X11/notify/title_string"),
482 gtk_window_get_title(window));
483 gtk_window_set_title(window, newtitle);
484 }
485
486 static void
487 handle_count(GaimGtkWindow *gaimwin)
488 {
489 GtkWindow *window;
490 char newtitle[256];
491
492 g_return_if_fail(gaimwin != NULL);
493
494 window = GTK_WINDOW(gaimwin->window);
495 g_return_if_fail(window != NULL);
496
497 g_snprintf(newtitle, sizeof(newtitle), "[%d] %s",
498 count_messages(gaimwin), gtk_window_get_title(window));
499 gtk_window_set_title(window, newtitle);
500 }
501
502 static void
503 handle_urgent(GaimGtkWindow *win, gboolean add)
504 {
505 #ifndef _WIN32
506 XWMHints *hints;
507
508 g_return_if_fail(win != NULL);
509 g_return_if_fail(win->window != NULL);
510 g_return_if_fail(win->window->window != NULL);
511
512 hints = XGetWMHints(GDK_WINDOW_XDISPLAY(win->window->window),
513 GDK_WINDOW_XWINDOW(win->window->window));
514 if(!hints)
515 hints = XAllocWMHints();
516
517 if (add)
518 hints->flags |= XUrgencyHint;
519 else
520 hints->flags &= ~XUrgencyHint;
521 XSetWMHints(GDK_WINDOW_XDISPLAY(win->window->window),
522 GDK_WINDOW_XWINDOW(win->window->window), hints);
523 XFree(hints);
524 #endif
525 }
526
527 static void
528 handle_raise(GaimGtkWindow *gaimwin)
529 {
530 gaim_gtk_conv_window_raise(gaimwin);
531 }
532
533 static void
534 type_toggle_cb(GtkWidget *widget, gpointer data)
535 {
536 gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
537 gchar pref[256];
538
539 g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
540
541 gaim_prefs_set_bool(pref, on);
542 }
543
544 static void
545 method_toggle_cb(GtkWidget *widget, gpointer data)
546 {
547 gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
548 gchar pref[256];
549
550 g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
551
552 gaim_prefs_set_bool(pref, on);
553
554 if (!strcmp(data, "method_string")) {
555 GtkWidget *entry = g_object_get_data(G_OBJECT(widget), "title-entry");
556 gtk_widget_set_sensitive(entry, on);
557
558 gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string", gtk_entry_get_text(GTK_ENTRY(entry)));
559 }
560
561 apply_method();
562 }
563
564 static void
565 notify_toggle_cb(GtkWidget *widget, gpointer data)
566 {
567 gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
568 gchar pref[256];
569
570 g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
571
572 gaim_prefs_set_bool(pref, on);
573
574 apply_notify();
575 }
576
577 static gboolean
578 options_entry_cb(GtkWidget *widget, GdkEventFocus *evt, gpointer data)
579 {
580 if (data == NULL)
581 return FALSE;
582
583 if (!strcmp(data, "method_string")) {
584 gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string", gtk_entry_get_text(GTK_ENTRY(widget)));
585 }
586
587 apply_method();
588
589 return FALSE;
590 }
591
592 static void
593 apply_method() {
594 GList *convs;
595 GaimGtkWindow *gaimwin = NULL;
596
597 for (convs = gaim_get_conversations(); convs != NULL; convs = convs->next) {
598 GaimConversation *conv = (GaimConversation *)convs->data;
599
600 /* remove notifications */
601 unnotify(conv, FALSE);
602
603 gaimwin = GAIM_GTK_CONVERSATION(conv)->win;
604 if (GPOINTER_TO_INT(gaim_conversation_get_data(conv, "notify-message-count")) != 0)
605 /* reattach appropriate notifications */
606 notify(conv, FALSE);
607 }
608 }
609
610 static void
611 apply_notify()
612 {
613 GList *convs = gaim_get_conversations();
614
615 while (convs) {
616 GaimConversation *conv = (GaimConversation *)convs->data;
617
618 /* detach signals */
619 detach_signals(conv);
620 /* reattach appropriate signals */
621 attach_signals(conv);
622
623 convs = convs->next;
624 }
625 }
626
627 static GtkWidget *
628 get_config_frame(GaimPlugin *plugin)
629 {
630 GtkWidget *ret = NULL, *frame = NULL;
631 GtkWidget *vbox = NULL, *hbox = NULL;
632 GtkWidget *toggle = NULL, *entry = NULL, *ref;
633
634 ret = gtk_vbox_new(FALSE, 18);
635 gtk_container_set_border_width(GTK_CONTAINER (ret), 12);
636
637 /*---------- "Notify For" ----------*/
638 frame = gaim_gtk_make_frame(ret, _("Notify For"));
639 vbox = gtk_vbox_new(FALSE, 5);
640 gtk_container_add(GTK_CONTAINER(frame), vbox);
641
642 toggle = gtk_check_button_new_with_mnemonic(_("_IM windows"));
643 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
644 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
645 gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_im"));
646 g_signal_connect(G_OBJECT(toggle), "toggled",
647 G_CALLBACK(type_toggle_cb), "type_im");
648
649 toggle = gtk_check_button_new_with_mnemonic(_("C_hat windows"));
650 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
651 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
652 gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat"));
653 g_signal_connect(G_OBJECT(toggle), "toggled",
654 G_CALLBACK(type_toggle_cb), "type_chat");
655
656 ref = toggle;
657 toggle = gtk_check_button_new_with_mnemonic(_("\t_Only when someone says your screen name"));
658 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
659 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
660 gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick"));
661 g_signal_connect(G_OBJECT(toggle), "toggled",
662 G_CALLBACK(type_toggle_cb), "type_chat_nick");
663 gtk_widget_set_sensitive(toggle, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ref)));
664 g_signal_connect(G_OBJECT(ref), "toggled",
665 G_CALLBACK(gaim_gtk_toggle_sensitive), toggle);
666
667 toggle = gtk_check_button_new_with_mnemonic(_("_Focused windows"));
668 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
669 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
670 gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_focused"));
671 g_signal_connect(G_OBJECT(toggle), "toggled",
672 G_CALLBACK(type_toggle_cb), "type_focused");
673
674 /*---------- "Notification Methods" ----------*/
675 frame = gaim_gtk_make_frame(ret, _("Notification Methods"));
676 vbox = gtk_vbox_new(FALSE, 5);
677 gtk_container_add(GTK_CONTAINER(frame), vbox);
678
679 /* String method button */
680 hbox = gtk_hbox_new(FALSE, 18);
681 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
682 toggle = gtk_check_button_new_with_mnemonic(_("Prepend _string into window title:"));
683 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
684 gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string"));
685 gtk_box_pack_start(GTK_BOX(hbox), toggle, FALSE, FALSE, 0);
686
687 entry = gtk_entry_new();
688 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
689 gtk_entry_set_max_length(GTK_ENTRY(entry), 10);
690 gtk_widget_set_sensitive(GTK_WIDGET(entry),
691 gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string"));
692 gtk_entry_set_text(GTK_ENTRY(entry),
693 gaim_prefs_get_string("/plugins/gtk/X11/notify/title_string"));
694 g_object_set_data(G_OBJECT(toggle), "title-entry", entry);
695 g_signal_connect(G_OBJECT(toggle), "toggled",
696 G_CALLBACK(method_toggle_cb), "method_string");
697 g_signal_connect(G_OBJECT(entry), "focus-out-event",
698 G_CALLBACK(options_entry_cb), "method_string");
699
700 /* Count method button */
701 toggle = gtk_check_button_new_with_mnemonic(_("Insert c_ount of new messages into window title"));
702 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
703 gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count"));
704 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
705 g_signal_connect(G_OBJECT(toggle), "toggled",
706 G_CALLBACK(method_toggle_cb), "method_count");
707
708 #ifndef _WIN32
709 /* Urgent method button */
710 toggle = gtk_check_button_new_with_mnemonic(_("Set window manager \"_URGENT\" hint"));
711 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
712 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
713 gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_urgent"));
714 g_signal_connect(G_OBJECT(toggle), "toggled",
715 G_CALLBACK(method_toggle_cb), "method_urgent");
716 #endif
717
718 /* Raise window method button */
719 toggle = gtk_check_button_new_with_mnemonic(_("R_aise conversation window"));
720 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
721 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
722 gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_raise"));
723 g_signal_connect(G_OBJECT(toggle), "toggled",
724 G_CALLBACK(method_toggle_cb), "method_raise");
725
726 /*---------- "Notification Removals" ----------*/
727 frame = gaim_gtk_make_frame(ret, _("Notification Removal"));
728 vbox = gtk_vbox_new(FALSE, 5);
729 gtk_container_add(GTK_CONTAINER(frame), vbox);
730
731 /* Remove on focus button */
732 toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window _gains focus"));
733 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
734 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
735 gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus"));
736 g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(notify_toggle_cb), "notify_focus");
737
738 /* Remove on click button */
739 toggle = gtk_check_button_new_with_mnemonic(_("Remove when conversation window _receives click"));
740 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
741 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
742 gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click"));
743 g_signal_connect(G_OBJECT(toggle), "toggled",
744 G_CALLBACK(notify_toggle_cb), "notify_click");
745
746 /* Remove on type button */
747 toggle = gtk_check_button_new_with_mnemonic(_("Remove when _typing in conversation window"));
748 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
749 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
750 gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_type"));
751 g_signal_connect(G_OBJECT(toggle), "toggled",
752 G_CALLBACK(notify_toggle_cb), "notify_type");
753
754 /* Remove on message send button */
755 toggle = gtk_check_button_new_with_mnemonic(_("Remove when a _message gets sent"));
756 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
757 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
758 gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_send"));
759 g_signal_connect(G_OBJECT(toggle), "toggled",
760 G_CALLBACK(notify_toggle_cb), "notify_send");
761
762 #if 0
763 /* Remove on conversation switch button */
764 toggle = gtk_check_button_new_with_mnemonic(_("Remove on switch to conversation ta_b"));
765 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
766 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
767 gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_switch"));
768 g_signal_connect(G_OBJECT(toggle), "toggled",
769 G_CALLBACK(notify_toggle_cb), "notify_switch");
770 #endif
771
772 gtk_widget_show_all(ret);
773 return ret;
774 }
775
776 static gboolean
777 plugin_load(GaimPlugin *plugin)
778 {
779 GList *convs = gaim_get_conversations();
780 void *conv_handle = gaim_conversations_get_handle();
781 void *gtk_conv_handle = gaim_gtk_conversations_get_handle();
782
783 my_plugin = plugin;
784
785 gaim_signal_connect(gtk_conv_handle, "displayed-im-msg", plugin,
786 GAIM_CALLBACK(message_displayed_cb), NULL);
787 gaim_signal_connect(gtk_conv_handle, "displayed-chat-msg", plugin,
788 GAIM_CALLBACK(message_displayed_cb), NULL);
789 gaim_signal_connect(gtk_conv_handle, "conversation-switched", plugin,
790 GAIM_CALLBACK(conv_switched), NULL);
791 gaim_signal_connect(conv_handle, "sent-im-msg", plugin,
792 GAIM_CALLBACK(im_sent_im), NULL);
793 gaim_signal_connect(conv_handle, "sent-chat-msg", plugin,
794 GAIM_CALLBACK(chat_sent_im), NULL);
795 gaim_signal_connect(conv_handle, "conversation-created", plugin,
796 GAIM_CALLBACK(conv_created), NULL);
797 gaim_signal_connect(conv_handle, "chat-joined", plugin,
798 GAIM_CALLBACK(conv_created), NULL);
799 gaim_signal_connect(conv_handle, "deleting-conversation", plugin,
800 GAIM_CALLBACK(deleting_conv), NULL);
801 #if 0
802 gaim_signal_connect(gtk_conv_handle, "conversation-dragging", plugin,
803 GAIM_CALLBACK(conversation_dragging), NULL);
804 #endif
805
806 while (convs) {
807 GaimConversation *conv = (GaimConversation *)convs->data;
808
809 /* attach signals */
810 attach_signals(conv);
811
812 convs = convs->next;
813 }
814
815 return TRUE;
816 }
817
818 static gboolean
819 plugin_unload(GaimPlugin *plugin)
820 {
821 GList *convs = gaim_get_conversations();
822
823 while (convs) {
824 GaimConversation *conv = (GaimConversation *)convs->data;
825
826 /* kill signals */
827 detach_signals(conv);
828
829 convs = convs->next;
830 }
831
832 return TRUE;
833 }
834
835 static GaimGtkPluginUiInfo ui_info =
836 {
837 get_config_frame,
838 0 /* page_num (Reserved) */
839 };
840
841 static GaimPluginInfo info =
842 {
843 GAIM_PLUGIN_MAGIC,
844 GAIM_MAJOR_VERSION,
845 GAIM_MINOR_VERSION,
846 GAIM_PLUGIN_STANDARD, /**< type */
847 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */
848 0, /**< flags */
849 NULL, /**< dependencies */
850 GAIM_PRIORITY_DEFAULT, /**< priority */
851
852 NOTIFY_PLUGIN_ID, /**< id */
853 N_("Message Notification"), /**< name */
854 VERSION, /**< version */
855 /** summary */
856 N_("Provides a variety of ways of notifying you of unread messages."),
857 /** description */
858 N_("Provides a variety of ways of notifying you of unread messages."),
859 "Etan Reisner <deryni@eden.rutgers.edu>\n\t\t\tBrian Tarricone <bjt23@cornell.edu>",
860 /**< author */
861 GAIM_WEBSITE, /**< homepage */
862
863 plugin_load, /**< load */
864 plugin_unload, /**< unload */
865 NULL, /**< destroy */
866
867 &ui_info, /**< ui_info */
868 NULL, /**< extra_info */
869 NULL,
870 NULL
871 };
872
873 static void
874 init_plugin(GaimPlugin *plugin)
875 {
876 gaim_prefs_add_none("/plugins/gtk");
877 gaim_prefs_add_none("/plugins/gtk/X11");
878 gaim_prefs_add_none("/plugins/gtk/X11/notify");
879
880 gaim_prefs_add_bool("/plugins/gtk/X11/notify/type_im", TRUE);
881 gaim_prefs_add_bool("/plugins/gtk/X11/notify/type_chat", FALSE);
882 gaim_prefs_add_bool("/plugins/gtk/X11/notify/type_chat_nick", FALSE);
883 gaim_prefs_add_bool("/plugins/gtk/X11/notify/type_focused", FALSE);
884 gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_string", FALSE);
885 gaim_prefs_add_string("/plugins/gtk/X11/notify/title_string", "(*)");
886 gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_urgent", FALSE);
887 gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_count", FALSE);
888 gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_raise", FALSE);
889 gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_focus", FALSE);
890 gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_click", FALSE);
891 gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_type", TRUE);
892 gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_send", TRUE);
893 gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_switch", TRUE);
894 }
895
896 GAIM_INIT_PLUGIN(notify, init_plugin, info)

mercurial