2 * @file gntgf.c Minimal toaster plugin in Gnt.
4 * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
24 #define PLUGIN_STATIC_NAME "GntGf"
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"
37 #define PREFS_URGENT PREFS_PREFIX "/urgent"
40 #include <X11/Xutil.h>
48 #include <conversation.h>
54 #include <gntbutton.h>
55 #include <gntcheckbox.h>
59 #include "gntplugin.h"
69 static GList
*toasters
;
70 static int gpsy
[MAX_COLS
];
71 static int gpsw
[MAX_COLS
];
74 destroy_toaster(GntToast
*toast
)
76 toasters
= g_list_remove(toasters
, toast
);
77 gnt_widget_destroy(toast
->window
);
78 g_source_remove(toast
->timer
);
83 remove_toaster(GntToast
*toast
)
90 gnt_widget_get_size(toast
->window
, NULL
, &h
);
91 gpsy
[toast
->column
] -= h
;
94 memset(&nwin
, 0, sizeof(nwin
));
95 destroy_toaster(toast
);
97 for (iter
= toasters
; iter
; iter
= iter
->next
)
101 nwin
[toast
->column
]++;
102 if (toast
->column
!= col
) continue;
103 gnt_widget_get_position(toast
->window
, &x
, &y
);
105 gnt_screen_move_widget(toast
->window
, x
, y
);
116 error_handler(Display
*dpy
, XErrorEvent
*error
)
119 XGetErrorText(dpy
, error
->error_code
, buffer
, sizeof(buffer
));
120 purple_debug_error("gntgf", "Could not set urgent to the window: %s.\n", buffer
);
127 /* This is from deryni/tuomov's urgent_test.c */
133 ids
= getenv("WINDOWID");
139 dpy
= XOpenDisplay(NULL
);
143 XSetErrorHandler(error_handler
);
144 hints
= XGetWMHints(dpy
, id
);
146 hints
->flags
|=XUrgencyHint
;
147 XSetWMHints(dpy
, id
, hints
);
150 XSetErrorHandler(NULL
);
158 notify(PurpleConversation
*conv
, const char *fmt
, ...)
166 if (purple_prefs_get_bool(PREFS_BEEP
))
170 FinchConv
*fc
= conv
->ui_data
;
171 if (gnt_widget_has_focus(fc
->window
))
176 if (purple_prefs_get_bool(PREFS_URGENT
))
180 window
= gnt_vbox_new(FALSE
);
181 GNT_WIDGET_SET_FLAGS(window
, GNT_WIDGET_TRANSIENT
);
182 GNT_WIDGET_UNSET_FLAGS(window
, GNT_WIDGET_NO_BORDER
);
185 str
= g_strdup_vprintf(fmt
, args
);
188 gnt_box_add_widget(GNT_BOX(window
),
189 gnt_label_new_with_format(str
, GNT_TEXT_FLAG_HIGHLIGHT
));
192 gnt_widget_size_request(window
);
193 gnt_widget_get_size(window
, &w
, &h
);
194 for (i
= 0; i
< MAX_COLS
&& gpsy
[i
] + h
>= getmaxy(stdscr
) ; ++i
)
197 purple_debug_warning("GntGf", "Dude, that's way too many popups\n");
198 gnt_widget_destroy(window
);
202 toast
= g_new0(GntToast
, 1);
203 toast
->window
= window
;
210 gpsw
[i
] = gpsw
[i
- 1] + w
+ 1;
213 if (i
== 0 || (w
+ gpsw
[i
- 1] >= getmaxx(stdscr
))) {
214 /* if it's going to be too far left, overlap. */
215 gnt_widget_set_position(window
, getmaxx(stdscr
) - w
- 1,
216 getmaxy(stdscr
) - gpsy
[i
] - 1);
218 gnt_widget_set_position(window
, getmaxx(stdscr
) - gpsw
[i
- 1] - w
- 1,
219 getmaxy(stdscr
) - gpsy
[i
] - 1);
221 gnt_widget_draw(window
);
223 toast
->timer
= g_timeout_add(4000, (GSourceFunc
)remove_toaster
, toast
);
224 toasters
= g_list_prepend(toasters
, toast
);
228 buddy_signed_on(PurpleBuddy
*buddy
, gpointer null
)
230 if (purple_prefs_get_bool(PREFS_EVENT_SIGNONF
))
231 notify(NULL
, _("%s just signed on"), purple_buddy_get_alias(buddy
));
235 buddy_signed_off(PurpleBuddy
*buddy
, gpointer null
)
237 if (purple_prefs_get_bool(PREFS_EVENT_SIGNONF
))
238 notify(NULL
, _("%s just signed off"), purple_buddy_get_alias(buddy
));
242 received_im_msg(PurpleAccount
*account
, const char *sender
, const char *msg
,
243 PurpleConversation
*conv
, PurpleMessageFlags flags
, gpointer null
)
245 if (purple_prefs_get_bool(PREFS_EVENT_IM_MSG
))
246 notify(conv
, _("%s sent you a message"), sender
);
250 received_chat_msg(PurpleAccount
*account
, const char *sender
, const char *msg
,
251 PurpleConversation
*conv
, PurpleMessageFlags flags
, gpointer null
)
255 if (flags
& PURPLE_MESSAGE_WHISPER
)
258 nick
= PURPLE_CONV_CHAT(conv
)->nick
;
260 if (g_utf8_collate(sender
, nick
) == 0)
263 if (purple_prefs_get_bool(PREFS_EVENT_CHAT_NICK
) &&
264 (purple_utf8_has_word(msg
, nick
)))
265 notify(conv
, _("%s said your nick in %s"), sender
, purple_conversation_get_name(conv
));
266 else if (purple_prefs_get_bool(PREFS_EVENT_CHAT_MSG
))
267 notify(conv
, _("%s sent a message in %s"), sender
, purple_conversation_get_name(conv
));
271 plugin_load(PurplePlugin
*plugin
)
273 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", plugin
,
274 PURPLE_CALLBACK(buddy_signed_on
), NULL
);
275 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", plugin
,
276 PURPLE_CALLBACK(buddy_signed_off
), NULL
);
277 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", plugin
,
278 PURPLE_CALLBACK(received_im_msg
), NULL
);
279 purple_signal_connect(purple_conversations_get_handle(), "received-chat-msg", plugin
,
280 PURPLE_CALLBACK(received_chat_msg
), NULL
);
282 memset(&gpsy
, 0, sizeof(gpsy
));
283 memset(&gpsw
, 0, sizeof(gpsw
));
289 plugin_unload(PurplePlugin
*plugin
)
293 GntToast
*toast
= toasters
->data
;
294 destroy_toaster(toast
);
305 {PREFS_EVENT_SIGNONF
, N_("Buddy signs on/off")},
306 {PREFS_EVENT_IM_MSG
, N_("You receive an IM")},
307 {PREFS_EVENT_CHAT_MSG
, N_("Someone speaks in a chat")},
308 {PREFS_EVENT_CHAT_NICK
, N_("Someone says your name in a chat")},
313 pref_toggled(GntTree
*tree
, char *key
, gpointer null
)
315 purple_prefs_set_bool(key
, gnt_tree_get_choice(tree
, key
));
319 toggle_option(GntCheckBox
*check
, gpointer str
)
321 purple_prefs_set_bool(str
, gnt_check_box_get_checked(check
));
327 GntWidget
*window
, *tree
, *check
;
330 window
= gnt_vbox_new(FALSE
);
331 gnt_box_set_pad(GNT_BOX(window
), 0);
332 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
333 gnt_box_set_fill(GNT_BOX(window
), TRUE
);
335 gnt_box_add_widget(GNT_BOX(window
),
336 gnt_label_new(_("Notify with a toaster when")));
338 tree
= gnt_tree_new();
339 gnt_box_add_widget(GNT_BOX(window
), tree
);
341 for (i
= 0; prefs
[i
].pref
; i
++)
343 gnt_tree_add_choice(GNT_TREE(tree
), prefs
[i
].pref
,
344 gnt_tree_create_row(GNT_TREE(tree
), prefs
[i
].display
), NULL
, NULL
);
345 gnt_tree_set_choice(GNT_TREE(tree
), prefs
[i
].pref
,
346 purple_prefs_get_bool(prefs
[i
].pref
));
348 gnt_tree_set_col_width(GNT_TREE(tree
), 0, 40);
349 g_signal_connect(G_OBJECT(tree
), "toggled", G_CALLBACK(pref_toggled
), NULL
);
351 check
= gnt_check_box_new(_("Beep too!"));
352 gnt_check_box_set_checked(GNT_CHECK_BOX(check
), purple_prefs_get_bool(PREFS_BEEP
));
353 g_signal_connect(G_OBJECT(check
), "toggled", G_CALLBACK(toggle_option
), PREFS_BEEP
);
354 gnt_box_add_widget(GNT_BOX(window
), check
);
357 check
= gnt_check_box_new(_("Set URGENT for the terminal window."));
358 gnt_check_box_set_checked(GNT_CHECK_BOX(check
), purple_prefs_get_bool(PREFS_URGENT
));
359 g_signal_connect(G_OBJECT(check
), "toggled", G_CALLBACK(toggle_option
), PREFS_URGENT
);
360 gnt_box_add_widget(GNT_BOX(window
), check
);
366 static PurplePluginInfo info
=
369 PURPLE_MAJOR_VERSION
,
370 PURPLE_MINOR_VERSION
,
371 PURPLE_PLUGIN_STANDARD
,
375 PURPLE_PRIORITY_DEFAULT
,
379 N_("Toaster plugin"),
380 N_("Toaster plugin"),
381 "Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
399 init_plugin(PurplePlugin
*plugin
)
401 purple_prefs_add_none("/plugins");
402 purple_prefs_add_none("/plugins/gnt");
404 purple_prefs_add_none("/plugins/gnt/gntgf");
405 purple_prefs_add_none(PREFS_EVENT
);
407 purple_prefs_add_bool(PREFS_EVENT_SIGNONF
, TRUE
);
408 purple_prefs_add_bool(PREFS_EVENT_IM_MSG
, TRUE
);
409 purple_prefs_add_bool(PREFS_EVENT_CHAT_MSG
, TRUE
);
410 purple_prefs_add_bool(PREFS_EVENT_CHAT_NICK
, TRUE
);
412 purple_prefs_add_bool(PREFS_BEEP
, TRUE
);
414 purple_prefs_add_bool(PREFS_URGENT
, FALSE
);
418 PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME
, init_plugin
, info
)