15817
|
1 /**
|
|
2 * @file gntgf.c Minimal toaster plugin in Gnt.
|
|
3 *
|
|
4 * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
|
|
5 *
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
9 * (at your option) any later version.
|
|
10 *
|
|
11 * This program is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 * GNU General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License
|
|
17 * along with this program; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 */
|
|
20
|
|
21
|
|
22 #include "internal.h"
|
|
23
|
|
24 #define PLUGIN_STATIC_NAME "GntGf"
|
|
25
|
|
26 #define PREFS_PREFIX "/plugins/gnt/gntgf"
|
|
27 #define PREFS_EVENT PREFS_PREFIX "/events"
|
|
28 #define PREFS_EVENT_SIGNONF PREFS_EVENT "/signonf"
|
|
29 #define PREFS_EVENT_IM_MSG PREFS_EVENT "/immsg"
|
|
30 #define PREFS_EVENT_CHAT_MSG PREFS_EVENT "/chatmsg"
|
|
31 #define PREFS_EVENT_CHAT_NICK PREFS_EVENT "/chatnick"
|
|
32 #define PREFS_BEEP PREFS_PREFIX "/beep"
|
|
33
|
|
34 #define MAX_COLS 3
|
|
35
|
|
36 #ifdef HAVE_X11
|
|
37 #define PREFS_URGENT PREFS_PREFIX "/urgent"
|
|
38
|
|
39 #include <X11/Xlib.h>
|
|
40 #include <X11/Xutil.h>
|
|
41 #endif
|
|
42
|
|
43 #include <glib.h>
|
|
44
|
|
45 #include <plugin.h>
|
|
46 #include <version.h>
|
|
47 #include <blist.h>
|
|
48 #include <conversation.h>
|
|
49 #include <debug.h>
|
|
50 #include <util.h>
|
|
51
|
|
52 #include <gnt.h>
|
|
53 #include <gntbox.h>
|
|
54 #include <gntbutton.h>
|
|
55 #include <gntcheckbox.h>
|
|
56 #include <gntlabel.h>
|
|
57 #include <gnttree.h>
|
|
58
|
|
59 #include <gntplugin.h>
|
|
60
|
|
61 typedef struct
|
|
62 {
|
|
63 GntWidget *window;
|
|
64 int timer;
|
|
65 int column;
|
|
66 } GntToast;
|
|
67
|
|
68 static GList *toasters;
|
|
69 static int gpsy[MAX_COLS];
|
|
70 static int gpsw[MAX_COLS];
|
|
71
|
|
72 static void
|
|
73 destroy_toaster(GntToast *toast)
|
|
74 {
|
|
75 toasters = g_list_remove(toasters, toast);
|
|
76 gnt_widget_destroy(toast->window);
|
|
77 g_source_remove(toast->timer);
|
|
78 g_free(toast);
|
|
79 }
|
|
80
|
|
81 static gboolean
|
|
82 remove_toaster(GntToast *toast)
|
|
83 {
|
|
84 GList *iter;
|
|
85 int h;
|
|
86 int col;
|
|
87 int nwin[MAX_COLS];
|
|
88
|
|
89 gnt_widget_get_size(toast->window, NULL, &h);
|
|
90 gpsy[toast->column] -= h;
|
|
91 col = toast->column;
|
|
92
|
|
93 memset(&nwin, 0, sizeof(nwin));
|
|
94 destroy_toaster(toast);
|
|
95
|
|
96 for (iter = toasters; iter; iter = iter->next)
|
|
97 {
|
|
98 int x, y;
|
|
99 toast = iter->data;
|
|
100 nwin[toast->column]++;
|
|
101 if (toast->column != col) continue;
|
|
102 gnt_widget_get_position(toast->window, &x, &y);
|
|
103 y += h;
|
|
104 gnt_screen_move_widget(toast->window, x, y);
|
|
105 }
|
|
106
|
|
107 if (nwin[col] == 0)
|
|
108 gpsw[col] = 0;
|
|
109
|
|
110 return FALSE;
|
|
111 }
|
|
112
|
|
113 #ifdef HAVE_X11
|
|
114 static void
|
|
115 urgent()
|
|
116 {
|
|
117 /* This is from deryni/tuomov's urgent_test.c */
|
|
118 Display *dpy;
|
|
119 Window id;
|
|
120 const char *ids;
|
|
121 XWMHints *hints;
|
|
122
|
|
123 ids = getenv("WINDOWID");
|
|
124 if (ids == NULL)
|
|
125 return;
|
|
126
|
|
127 id = atoi(ids);
|
|
128
|
|
129 dpy = XOpenDisplay(NULL);
|
|
130 if (dpy == NULL)
|
|
131 return;
|
|
132
|
|
133 hints = XGetWMHints(dpy, id);
|
|
134 hints->flags|=XUrgencyHint;
|
|
135 XSetWMHints(dpy, id, hints);
|
|
136
|
|
137 XFlush(dpy);
|
|
138 XCloseDisplay(dpy);
|
|
139 }
|
|
140 #endif
|
|
141
|
|
142 static void
|
|
143 notify(const char *fmt, ...)
|
|
144 {
|
|
145 GntWidget *window;
|
|
146 GntToast *toast;
|
|
147 char *str;
|
|
148 int h, w, i;
|
|
149 va_list args;
|
|
150
|
15822
|
151 if (purple_prefs_get_bool(PREFS_BEEP))
|
15817
|
152 beep();
|
|
153 #ifdef HAVE_X11
|
15822
|
154 if (purple_prefs_get_bool(PREFS_URGENT))
|
15817
|
155 urgent();
|
|
156 #endif
|
|
157
|
|
158 window = gnt_vbox_new(FALSE);
|
|
159 GNT_WIDGET_SET_FLAGS(window, GNT_WIDGET_TRANSIENT);
|
|
160 GNT_WIDGET_UNSET_FLAGS(window, GNT_WIDGET_NO_BORDER);
|
|
161
|
|
162 va_start(args, fmt);
|
|
163 str = g_strdup_vprintf(fmt, args);
|
|
164 va_end(args);
|
|
165
|
|
166 gnt_box_add_widget(GNT_BOX(window),
|
|
167 gnt_label_new_with_format(str, GNT_TEXT_FLAG_HIGHLIGHT));
|
|
168
|
|
169 g_free(str);
|
|
170 gnt_widget_size_request(window);
|
|
171 gnt_widget_get_size(window, &w, &h);
|
|
172 for (i = 0; i < MAX_COLS && gpsy[i] + h >= getmaxy(stdscr) ; ++i)
|
|
173 ;
|
|
174 if (i >= MAX_COLS) {
|
15822
|
175 purple_debug_warning("GntGf", "Dude, that's way too many popups\n");
|
15817
|
176 gnt_widget_destroy(window);
|
|
177 return;
|
|
178 }
|
|
179
|
|
180 toast = g_new0(GntToast, 1);
|
|
181 toast->window = window;
|
|
182 toast->column = i;
|
|
183 gpsy[i] += h;
|
|
184 if (w > gpsw[i]) {
|
|
185 if (i == 0)
|
|
186 gpsw[i] = w;
|
|
187 else
|
|
188 gpsw[i] = gpsw[i - 1] + w + 1;
|
|
189 }
|
|
190
|
|
191 if (i == 0 || (w + gpsw[i - 1] >= getmaxx(stdscr))) {
|
|
192 /* if it's going to be too far left, overlap. */
|
|
193 gnt_widget_set_position(window, getmaxx(stdscr) - w - 1,
|
|
194 getmaxy(stdscr) - gpsy[i] - 1);
|
|
195 } else {
|
|
196 gnt_widget_set_position(window, getmaxx(stdscr) - gpsw[i - 1] - w - 1,
|
|
197 getmaxy(stdscr) - gpsy[i] - 1);
|
|
198 }
|
|
199 gnt_widget_draw(window);
|
|
200
|
|
201 toast->timer = g_timeout_add(4000, (GSourceFunc)remove_toaster, toast);
|
|
202 toasters = g_list_prepend(toasters, toast);
|
|
203 }
|
|
204
|
|
205 static void
|
15822
|
206 buddy_signed_on(PurpleBuddy *buddy, gpointer null)
|
15817
|
207 {
|
15822
|
208 if (purple_prefs_get_bool(PREFS_EVENT_SIGNONF))
|
|
209 notify(_("%s just signed on"), purple_buddy_get_alias(buddy));
|
15817
|
210 }
|
|
211
|
|
212 static void
|
15822
|
213 buddy_signed_off(PurpleBuddy *buddy, gpointer null)
|
15817
|
214 {
|
15822
|
215 if (purple_prefs_get_bool(PREFS_EVENT_SIGNONF))
|
|
216 notify(_("%s just signed off"), purple_buddy_get_alias(buddy));
|
15817
|
217 }
|
|
218
|
|
219 static void
|
15822
|
220 received_im_msg(PurpleAccount *account, const char *sender, const char *msg,
|
|
221 PurpleConversation *conv, PurpleMessageFlags flags, gpointer null)
|
15817
|
222 {
|
15822
|
223 if (purple_prefs_get_bool(PREFS_EVENT_IM_MSG))
|
15817
|
224 notify(_("%s sent you a message"), sender);
|
|
225 }
|
|
226
|
|
227 static void
|
15822
|
228 received_chat_msg(PurpleAccount *account, const char *sender, const char *msg,
|
|
229 PurpleConversation *conv, PurpleMessageFlags flags, gpointer null)
|
15817
|
230 {
|
|
231 const char *nick;
|
|
232
|
15822
|
233 if (flags & PURPLE_MESSAGE_WHISPER)
|
15817
|
234 return;
|
|
235
|
15822
|
236 nick = PURPLE_CONV_CHAT(conv)->nick;
|
15817
|
237
|
|
238 if (g_utf8_collate(sender, nick) == 0)
|
|
239 return;
|
|
240
|
15822
|
241 if (purple_prefs_get_bool(PREFS_EVENT_CHAT_NICK) &&
|
|
242 (purple_utf8_has_word(msg, nick)))
|
|
243 notify(_("%s said your nick in %s"), sender, purple_conversation_get_name(conv));
|
|
244 else if (purple_prefs_get_bool(PREFS_EVENT_CHAT_MSG))
|
|
245 notify(_("%s sent a message in %s"), sender, purple_conversation_get_name(conv));
|
15817
|
246 }
|
|
247
|
|
248 static gboolean
|
15822
|
249 plugin_load(PurplePlugin *plugin)
|
15817
|
250 {
|
15822
|
251 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", plugin,
|
|
252 PURPLE_CALLBACK(buddy_signed_on), NULL);
|
|
253 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", plugin,
|
|
254 PURPLE_CALLBACK(buddy_signed_off), NULL);
|
|
255 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", plugin,
|
|
256 PURPLE_CALLBACK(received_im_msg), NULL);
|
|
257 purple_signal_connect(purple_conversations_get_handle(), "received-chat-msg", plugin,
|
|
258 PURPLE_CALLBACK(received_chat_msg), NULL);
|
15817
|
259
|
|
260 memset(&gpsy, 0, sizeof(gpsy));
|
|
261 memset(&gpsw, 0, sizeof(gpsw));
|
|
262
|
|
263 return TRUE;
|
|
264 }
|
|
265
|
|
266 static gboolean
|
15822
|
267 plugin_unload(PurplePlugin *plugin)
|
15817
|
268 {
|
|
269 while (toasters)
|
|
270 {
|
|
271 GntToast *toast = toasters->data;
|
|
272 destroy_toaster(toast);
|
|
273 }
|
|
274 return TRUE;
|
|
275 }
|
|
276
|
|
277 static struct
|
|
278 {
|
|
279 char *pref;
|
|
280 char *display;
|
|
281 } prefs[] =
|
|
282 {
|
|
283 {PREFS_EVENT_SIGNONF, N_("Buddy signs on/off")},
|
|
284 {PREFS_EVENT_IM_MSG, N_("You receive an IM")},
|
|
285 {PREFS_EVENT_CHAT_MSG, N_("Someone speaks in a chat")},
|
|
286 {PREFS_EVENT_CHAT_NICK, N_("Someone says your name in a chat")},
|
|
287 {NULL, NULL}
|
|
288 };
|
|
289
|
|
290 static void
|
|
291 pref_toggled(GntTree *tree, char *key, gpointer null)
|
|
292 {
|
15822
|
293 purple_prefs_set_bool(key, gnt_tree_get_choice(tree, key));
|
15817
|
294 }
|
|
295
|
|
296 static void
|
|
297 toggle_option(GntCheckBox *check, gpointer str)
|
|
298 {
|
15822
|
299 purple_prefs_set_bool(str, gnt_check_box_get_checked(check));
|
15817
|
300 }
|
|
301
|
|
302 static GntWidget *
|
|
303 config_frame()
|
|
304 {
|
|
305 GntWidget *window, *tree, *check;
|
|
306 int i;
|
|
307
|
|
308 window = gnt_vbox_new(FALSE);
|
|
309 gnt_box_set_pad(GNT_BOX(window), 0);
|
|
310 gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
|
|
311 gnt_box_set_fill(GNT_BOX(window), TRUE);
|
|
312
|
|
313 gnt_box_add_widget(GNT_BOX(window),
|
|
314 gnt_label_new(_("Notify with a toaster when")));
|
|
315
|
|
316 tree = gnt_tree_new();
|
|
317 gnt_box_add_widget(GNT_BOX(window), tree);
|
|
318
|
|
319 for (i = 0; prefs[i].pref; i++)
|
|
320 {
|
|
321 gnt_tree_add_choice(GNT_TREE(tree), prefs[i].pref,
|
|
322 gnt_tree_create_row(GNT_TREE(tree), prefs[i].display), NULL, NULL);
|
|
323 gnt_tree_set_choice(GNT_TREE(tree), prefs[i].pref,
|
15822
|
324 purple_prefs_get_bool(prefs[i].pref));
|
15817
|
325 }
|
|
326 gnt_tree_set_col_width(GNT_TREE(tree), 0, 40);
|
|
327 g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(pref_toggled), NULL);
|
|
328
|
|
329 check = gnt_check_box_new(_("Beep too!"));
|
15822
|
330 gnt_check_box_set_checked(GNT_CHECK_BOX(check), purple_prefs_get_bool(PREFS_BEEP));
|
15817
|
331 g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_BEEP);
|
|
332 gnt_box_add_widget(GNT_BOX(window), check);
|
|
333
|
|
334 #ifdef HAVE_X11
|
|
335 check = gnt_check_box_new(_("Set URGENT for the terminal window."));
|
15822
|
336 gnt_check_box_set_checked(GNT_CHECK_BOX(check), purple_prefs_get_bool(PREFS_URGENT));
|
15817
|
337 g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(toggle_option), PREFS_URGENT);
|
|
338 gnt_box_add_widget(GNT_BOX(window), check);
|
|
339 #endif
|
|
340
|
|
341 return window;
|
|
342 }
|
|
343
|
15822
|
344 static PurplePluginInfo info =
|
15817
|
345 {
|
15822
|
346 PURPLE_PLUGIN_MAGIC,
|
|
347 PURPLE_MAJOR_VERSION,
|
|
348 PURPLE_MINOR_VERSION,
|
|
349 PURPLE_PLUGIN_STANDARD,
|
|
350 FINCH_PLUGIN_TYPE,
|
15817
|
351 0,
|
|
352 NULL,
|
15822
|
353 PURPLE_PRIORITY_DEFAULT,
|
15817
|
354 "gntgf",
|
|
355 N_("GntGf"),
|
|
356 VERSION,
|
|
357 N_("Toaster plugin"),
|
|
358 N_("Toaster plugin"),
|
|
359 "Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
|
15822
|
360 "http://purple.sourceforge.net",
|
15817
|
361 plugin_load,
|
|
362 plugin_unload,
|
|
363 NULL,
|
|
364 config_frame,
|
|
365 NULL,
|
|
366 NULL,
|
|
367 NULL
|
|
368 };
|
|
369
|
|
370 static void
|
15822
|
371 init_plugin(PurplePlugin *plugin)
|
15817
|
372 {
|
15822
|
373 purple_prefs_add_none("/plugins");
|
|
374 purple_prefs_add_none("/plugins/gnt");
|
15817
|
375
|
15822
|
376 purple_prefs_add_none("/plugins/gnt/gntgf");
|
|
377 purple_prefs_add_none(PREFS_EVENT);
|
15817
|
378
|
15822
|
379 purple_prefs_add_bool(PREFS_EVENT_SIGNONF, TRUE);
|
|
380 purple_prefs_add_bool(PREFS_EVENT_IM_MSG, TRUE);
|
|
381 purple_prefs_add_bool(PREFS_EVENT_CHAT_MSG, TRUE);
|
|
382 purple_prefs_add_bool(PREFS_EVENT_CHAT_NICK, TRUE);
|
15817
|
383
|
15822
|
384 purple_prefs_add_bool(PREFS_BEEP, TRUE);
|
15817
|
385 #ifdef HAVE_X11
|
15822
|
386 purple_prefs_add_bool(PREFS_URGENT, FALSE);
|
15817
|
387 #endif
|
|
388 }
|
|
389
|
15822
|
390 PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
|