comparison plugins/notify.c @ 3374:3cd2fbddf95a

[gaim-migrate @ 3393] I had terrible days today and yesterday--a really terrible weekend. No cool stuff from me--the prefs away message page works a bit better. Ari and Chip both sent some patches to make things work a bit better in GTK 2, and Etan rewrote the notify plugin so it's really cool now! Thanks, guys! committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Mon, 05 Aug 2002 07:33:09 +0000
parents bd9d403fb15b
children 7931eb8bba19
comparison
equal deleted inserted replaced
3373:0e79bf1d79ea 3374:3cd2fbddf95a
1 /* Reworked by Etan Reisner
2 *
3 * Added config dialog
4 * Added control over notification method
5 * Added control over when to release notification
6 */
7
1 #define GAIM_PLUGINS 8 #define GAIM_PLUGINS
2 #include "gaim.h" 9 #include "gaim.h"
3 10
4 #include <gtk/gtk.h> 11 #include <gtk/gtk.h>
5 #include <string.h> 12 #include <string.h>
13 #include <X11/Xutil.h>
14 #include <X11/Xatom.h>
15 #include <gdk/gdkx.h>
16
17 guint choice;
18 #define REMOVE_FOCUS 0x00000001
19 #define REMOVE_TYPE 0x00000002
20
21 guint method;
22 #define METHOD_STRING 0x00000001
23 #define METHOD_QUOTE 0x00000002
24 #define METHOD_URGENT 0x00000004
6 25
7 void *handle; 26 void *handle;
8 27 GtkWidget *Dialog = NULL;
9 void received_im(struct gaim_connection *gc, char **who, char **what, void *m) { 28 GtkWidget *Click, *Focus, *Type;
29 GtkWidget *String, *Quote, *Urgent, *Entry;
30 gchar *title_string;
31
32 /* predefine some functions, less warnings */
33 void options(GtkWidget *widget, gpointer data);
34 void un_star(GtkWidget *widget, gpointer data);
35 void un_star_window(GtkWidget *widget, gpointer data);
36 void string_remove(GtkWidget *widget);
37 void quote_remove(GtkWidget *widget);
38 void urgent_remove(struct conversation *c);
39
40 int received_im(struct gaim_connection *gc, char **who, char **what, void *m) {
10 char buf[256]; 41 char buf[256];
11 struct conversation *cnv = find_conversation(*who); 42 struct conversation *cnv = find_conversation(*who);
12 GtkWindow *win; 43 GtkWindow *win;
13 char *me = g_strdup(normalize(gc->username)); 44 char *me = g_strdup(normalize(gc->username));
45 int revert_to_return;
46 Window focus_return;
14 47
15 if (!strcmp(me, normalize(*who))) { 48 if (!strcmp(me, normalize(*who))) {
16 g_free(me); 49 g_free(me);
50 return 0;
51 }
52 g_free(me);
53
54 if (cnv == NULL)
55 {
56 if (away_options & OPT_AWAY_QUEUE)
57 return 0;
58
59 cnv = new_conversation(*who);
60 }
61
62 win = (GtkWindow *)cnv->window;
63
64 XGetInputFocus(GDK_WINDOW_XDISPLAY(cnv->window->window), &focus_return, &revert_to_return);
65
66 if (focus_return != GDK_WINDOW_XWINDOW(cnv->window->window)) {
67 if (method & METHOD_STRING) {
68 g_snprintf(buf, sizeof(buf), "%s", win->title);
69 if (!strstr(buf, title_string)) {
70 g_snprintf(buf, sizeof(buf), "%s %s", title_string, win->title);
71 gtk_window_set_title(win, buf);
72 }
73 }
74 if (method & METHOD_QUOTE) {
75 g_snprintf(buf, sizeof(buf), "%s", win->title);
76 if (g_strncasecmp(buf, "\"", 1)) {
77 g_snprintf(buf, sizeof(buf), "\"%s\"", win->title);
78 gtk_window_set_title(win, buf);
79 }
80 }
81 if (method & METHOD_URGENT) {
82 /* do it the gdk way for windows compatibility(?) if I can figure it out */
83 /* gdk_property_change(win->window, WM_HINTS, WM_HINTS, 32, GDK_PROP_MODE_REPLACE, XUrgencyHint, 1); */
84 XWMHints *hints = XGetWMHints(GDK_WINDOW_XDISPLAY(cnv->window->window), GDK_WINDOW_XWINDOW(cnv->window->window));
85 hints->flags |= XUrgencyHint;
86 XSetWMHints(GDK_WINDOW_XDISPLAY(cnv->window->window), GDK_WINDOW_XWINDOW(cnv->window->window), hints);
87 }
88 }
89
90 return 0;
91 }
92
93 int sent_im(struct gaim_connection *gc, char *who, char **what, void *m) {
94 char buf[256];
95 struct conversation *c = find_conversation(who);
96
97 if (method & METHOD_QUOTE)
98 string_remove(c->window);
99 if (method & METHOD_STRING)
100 quote_remove(c->window);
101 if (method & METHOD_URGENT)
102 urgent_remove(c);
103 return 0;
104 }
105
106 int new_conv(char *who) {
107 struct conversation *c = find_conversation(who);
108
109 if (choice & REMOVE_FOCUS) {
110 gtk_signal_connect(GTK_OBJECT(c->window), "focus-in-event", GTK_SIGNAL_FUNC(un_star), NULL);
111 gtk_object_set_user_data(GTK_OBJECT(c->window), c);
112 }
113 else {
114 gtk_signal_connect(GTK_OBJECT(c->window), "button_press_event", GTK_SIGNAL_FUNC(un_star), NULL);
115 gtk_object_set_user_data(GTK_OBJECT(c->window), c);
116 gtk_signal_connect(GTK_OBJECT(c->text), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL);
117 gtk_object_set_user_data(GTK_OBJECT(c->text), c);
118 gtk_signal_connect(GTK_OBJECT(c->entry), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), NULL);
119 gtk_object_set_user_data(GTK_OBJECT(c->entry), c);
120 /* gtk_signal_connect(GTK_OBJECT(c->text), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), c); */
121 /* gtk_signal_connect(GTK_OBJECT(c->entry), "button_press_event", GTK_SIGNAL_FUNC(un_star_window), c); */
122 }
123
124 if (choice & REMOVE_TYPE) {
125 gtk_signal_connect(GTK_OBJECT(c->entry), "key-press-event", GTK_SIGNAL_FUNC(un_star_window), NULL);
126 gtk_object_set_user_data(GTK_OBJECT(c->entry), (gpointer) c);
127 /* gtk_signal_connect(GTK_OBJECT(c->entry), "key-press-event", GTK_SIGNAL_FUNC(un_star_window), c); */
128 }
129 }
130
131 void un_star(GtkWidget *widget, gpointer data) {
132 struct conversation *c = gtk_object_get_user_data(GTK_OBJECT(widget));
133 /* struct conversation *c = data; */
134
135 if (method & METHOD_QUOTE)
136 quote_remove(widget);
137 if (method & METHOD_STRING)
138 string_remove(widget);
139 if (method & METHOD_URGENT)
140 urgent_remove(c);
141 return;
142 }
143
144 void un_star_window(GtkWidget *widget, gpointer data) {
145 GtkWidget *parent = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
146 gtk_object_set_user_data(GTK_OBJECT(parent), gtk_object_get_user_data(GTK_OBJECT(widget)));
147 un_star(parent, data);
148 }
149
150 void string_remove(GtkWidget *widget) {
151 char buf[256];
152 GtkWindow *win = GTK_WINDOW(widget);
153
154 g_snprintf(buf, sizeof(buf), "%s", win->title);
155 if (strstr(buf, title_string)) {
156 g_snprintf(buf, sizeof(buf), "%s", &win->title[strlen(title_string)]);
157 gtk_window_set_title(win, buf);
158 }
159 return;
160 }
161
162 void quote_remove(GtkWidget *widget) {
163 char buf[256];
164 GtkWindow *win = GTK_WINDOW(widget);
165
166 g_snprintf(buf, sizeof(buf), "%s", win->title);
167 if (!g_strncasecmp(buf, "\"", 1)) {
168 g_snprintf(buf, strlen(buf) - 1, "%s", &win->title[1]);
169 gtk_window_set_title(win, buf);
170 }
171 return;
172 }
173
174 void urgent_remove(struct conversation *c) {
175 char buf[256];
176 GdkWindow *win = c->window->window;
177
178 XWMHints *hints = XGetWMHints(GDK_WINDOW_XDISPLAY(c->window->window), GDK_WINDOW_XWINDOW(c->window->window));
179 hints->flags &= ~XUrgencyHint;
180 XSetWMHints(GDK_WINDOW_XDISPLAY(c->window->window), GDK_WINDOW_XWINDOW(c->window->window), hints);
181 return;
182 }
183
184 void save_notify_prefs() {
185 char *buf;
186 FILE *fp;
187
188 buf = malloc(1000);
189 snprintf(buf, 1000, "%s/.gaim/.notify", getenv("HOME"));
190 if (!(fp = fopen(buf, "w"))) {
191 do_error_dialog(_("Unable to write to config file"), _("Notify plugin"));
17 return; 192 return;
18 } 193 }
19 g_free(me); 194 free(buf);
20 195
21 if (cnv == NULL) 196 fprintf(fp, "CHOICE=%d\n", choice);
22 { 197 fprintf(fp, "METHOD=%d\n", method);
23 if (away_options & OPT_AWAY_QUEUE) 198 fprintf(fp, "STRING=%s\n", title_string);
24 return; 199 fclose(fp);
25 200 }
26 cnv = new_conversation(*who); 201
27 } 202 void load_notify_prefs() {
28 203 gchar buf[1000];
29 win = (GtkWindow *)cnv->window; 204 gchar **parsed;
30 205 FILE *fp;
31 g_snprintf(buf, sizeof(buf), "%s", win->title); 206
32 if (!strstr(buf, "(*) ")) { 207 g_snprintf(buf, sizeof(buf), "%s/.gaim/.notify", getenv("HOME"));
33 g_snprintf(buf, sizeof(buf), "(*) %s", win->title); 208 if (!(fp = fopen(buf, "r")))
34 gtk_window_set_title(win, buf); 209 return;
35 } 210
36 } 211 while (fgets(buf, 1000, fp) != NULL) {
37 212 parsed = g_strsplit(g_strchomp(buf), "=", 2);
38 void sent_im(struct gaim_connection *gc, char *who, char **what, void *m) { 213 if (parsed[0] && parsed[1]) {
39 char buf[256]; 214 if (!strcmp(parsed[0], "CHOICE"))
40 struct conversation *c = find_conversation(who); 215 choice = atoi(parsed[1]);
41 GtkWindow *win = (GtkWindow *)c->window; 216 if (!strcmp(parsed[0], "METHOD"))
42 217 method = atoi(parsed[1]);
43 g_snprintf(buf, sizeof(buf), "%s", win->title); 218 if (!strcmp(parsed[0], "STRING"))
44 if (strstr(buf, "(*) ")) { 219 title_string = parsed[1];
45 g_snprintf(buf, sizeof(buf), "%s", &win->title[4]); 220 }
46 gtk_window_set_title(win, buf); 221 }
47 } 222 fclose(fp);
223 return;
224 }
225
226 void options(GtkWidget *widget, gpointer data) {
227 gint option = GPOINTER_TO_INT(data);
228
229 if (option == 0)
230 choice ^= REMOVE_FOCUS;
231 else if (option == 1)
232 choice ^= REMOVE_TYPE;
233 else if (option == 2) {
234 method ^= METHOD_STRING;
235 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
236 gtk_widget_set_sensitive(Entry, TRUE);
237 else
238 gtk_widget_set_sensitive(Entry, FALSE);
239 }
240 else if (option == 3)
241 method ^= METHOD_QUOTE;
242 else if (option == 4)
243 method ^= METHOD_URGENT;
244 }
245
246 void setup_buttons() {
247 if (choice & REMOVE_FOCUS)
248 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Focus), TRUE);
249 else
250 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Click), TRUE);
251 if (choice & REMOVE_TYPE)
252 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Type), TRUE);
253 else
254 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Type), FALSE);
255
256 if (method & METHOD_STRING)
257 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(String), TRUE);
258 else
259 gtk_widget_set_sensitive(Entry, FALSE);
260
261 if (method & METHOD_QUOTE)
262 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Quote), TRUE);
263
264 if (method & METHOD_URGENT)
265 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Urgent), TRUE);
266
267 return;
268 }
269
270 void close_dialog(GtkWidget *widget, gpointer data) {
271 gint option = GPOINTER_TO_INT(data);
272
273 if (option > 0) {
274 title_string = g_strdup(gtk_entry_get_text(GTK_ENTRY(Entry)));
275 save_notify_prefs();
276 }
277 else if (option < 0)
278 load_notify_prefs();
279
280 if (Dialog)
281 gtk_widget_destroy(Dialog);
282 Dialog = NULL;
48 } 283 }
49 284
50 char *gaim_plugin_init(GModule *hndl) { 285 char *gaim_plugin_init(GModule *hndl) {
51 handle = hndl; 286 handle = hndl;
52 287
288 load_notify_prefs();
289
53 gaim_signal_connect(handle, event_im_recv, received_im, NULL); 290 gaim_signal_connect(handle, event_im_recv, received_im, NULL);
54 gaim_signal_connect(handle, event_im_send, sent_im, NULL); 291 gaim_signal_connect(handle, event_im_send, sent_im, NULL);
292 gaim_signal_connect(handle, event_new_conversation, new_conv, NULL);
55 293
56 return NULL; 294 return NULL;
57 } 295 }
58 296
59 char *name() { 297 char *name() {
62 300
63 char *description() { 301 char *description() {
64 return "Puts an asterisk in the title bar of all conversations" 302 return "Puts an asterisk in the title bar of all conversations"
65 " where you have not responded to a message yet."; 303 " where you have not responded to a message yet.";
66 } 304 }
305
306 void gaim_plugin_config() {
307 GtkWidget *dialog_vbox;
308 GtkWidget *button, *label;
309 GtkWidget *box, *box2, *box3, *frame;
310
311 if (Dialog)
312 return;
313
314 /* main config dialog */
315 Dialog = gtk_dialog_new();
316 /* gtk_widget_set_usize(Dialog, 275, -1); */
317 gtk_window_set_title(GTK_WINDOW(Dialog), "Notify plugin configuration");
318 gtk_window_set_policy(GTK_WINDOW(Dialog), FALSE, FALSE, TRUE);
319 gtk_signal_connect(GTK_OBJECT(Dialog), "destroy", GTK_SIGNAL_FUNC(close_dialog), GINT_TO_POINTER(-1));
320
321 dialog_vbox = GTK_DIALOG(Dialog)->vbox;
322
323 /* Ok and Cancel buttons */
324 box = gtk_hbox_new(FALSE, 8);
325 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(Dialog)->action_area), box);
326
327 button = gtk_button_new_with_label(_("Cancel"));
328 gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 0);
329 gtk_widget_set_usize(button, 80, -2);
330 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_dialog), GINT_TO_POINTER(0));
331
332 button = gtk_button_new_with_label(_("Ok"));
333 gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
334 gtk_widget_set_usize(button, 80, -2);
335 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_dialog), GINT_TO_POINTER(1));
336
337 /* main hbox */
338 box = gtk_hbox_new(FALSE, 0);
339 gtk_box_pack_start(GTK_BOX(dialog_vbox), box, FALSE, FALSE, 0);
340
341 /* un-notify choices */
342 frame = gtk_frame_new(_("Remove notification when:"));
343 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
344
345 box2 = gtk_vbox_new(FALSE, 0);
346 gtk_container_add(GTK_CONTAINER(frame), box2);
347
348 Focus = gtk_radio_button_new_with_label(NULL, _("Conversation window gains focus."));
349 gtk_box_pack_start(GTK_BOX(box2), Focus, FALSE, FALSE, 2);
350
351 Click = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(Focus), _("Conversation window gets clicked."));
352 gtk_box_pack_start(GTK_BOX(box2), Click, FALSE, FALSE, 2);
353
354 Type = gtk_check_button_new_with_label(_("Type in conversation window"));
355 gtk_box_pack_start(GTK_BOX(box2), Type, FALSE, FALSE, 2);
356
357 /* notification method choices */
358 /* do I need/want any other notification methods? */
359 frame = gtk_frame_new(_("Notification method:"));
360 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
361
362 box2 = gtk_vbox_new(FALSE, 0);
363 gtk_container_add(GTK_CONTAINER(frame), box2);
364
365 box3 = gtk_hbox_new(FALSE, 0);
366 gtk_box_pack_start(GTK_BOX(box2), box3, FALSE, FALSE, 0);
367
368 String = gtk_check_button_new_with_label(_("Insert string into window title:"));
369 gtk_box_pack_start(GTK_BOX(box3), String, FALSE, FALSE, 0);
370
371 Entry = gtk_entry_new_with_max_length(7);
372 gtk_box_pack_start(GTK_BOX(box3), Entry, FALSE, FALSE, 0);
373 if (!title_string)
374 gtk_entry_set_text(GTK_ENTRY(Entry), "(*) ");
375 else
376 gtk_entry_set_text(GTK_ENTRY(Entry), title_string);
377
378 Quote = gtk_check_button_new_with_label(_("Quote window title."));
379 gtk_box_pack_start(GTK_BOX(box2), Quote, FALSE, FALSE, 0);
380
381 Urgent = gtk_check_button_new_with_label(_("Send URGENT to window manager."));
382 gtk_box_pack_start(GTK_BOX(box2), Urgent, FALSE, FALSE, 0);
383
384 /* setup buttons, then attach signals */
385 setup_buttons();
386 gtk_signal_connect(GTK_OBJECT(Focus), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(0));
387 gtk_signal_connect(GTK_OBJECT(Type), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(1));
388 gtk_signal_connect(GTK_OBJECT(String), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(2));
389 gtk_signal_connect(GTK_OBJECT(Quote), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(3));
390 gtk_signal_connect(GTK_OBJECT(Urgent), "toggled", GTK_SIGNAL_FUNC(options), GINT_TO_POINTER(4));
391
392 gtk_widget_show_all(Dialog);
393 }