2 * Copyright (C) 2006 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include NCURSES_HEADER
23 #define PLUGIN_STATIC_NAME GntGf
25 #define PREFS_PREFIX "/plugins/gnt/gntgf"
26 #define PREFS_EVENT PREFS_PREFIX "/events"
27 #define PREFS_EVENT_SIGNONF PREFS_EVENT "/signonf"
28 #define PREFS_EVENT_IM_MSG PREFS_EVENT "/immsg"
29 #define PREFS_EVENT_CHAT_MSG PREFS_EVENT "/chatmsg"
30 #define PREFS_EVENT_CHAT_NICK PREFS_EVENT "/chatnick"
31 #define PREFS_BEEP PREFS_PREFIX "/beep"
36 #define PREFS_URGENT PREFS_PREFIX "/urgent"
39 #include <X11/Xutil.h>
46 #include <buddylist.h>
47 #include <conversation.h>
49 #include <eventloop.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
= FINCH_CONV(conv
);
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_transient(window
, TRUE
);
182 gnt_widget_set_has_border(window
, TRUE
);
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_seconds(4, (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 PurpleIMConversation
*im
, PurpleMessageFlags flags
, gpointer null
)
245 if (purple_prefs_get_bool(PREFS_EVENT_IM_MSG
))
246 notify(PURPLE_CONVERSATION(im
), _("%s sent you a message"), sender
);
250 received_chat_msg(PurpleAccount
*account
, const char *sender
, const char *msg
,
251 PurpleChatConversation
*chat
, PurpleMessageFlags flags
, gpointer null
)
254 PurpleConversation
*conv
= PURPLE_CONVERSATION(chat
);
256 nick
= purple_chat_conversation_get_nick(chat
);
258 if (g_utf8_collate(sender
, nick
) == 0)
261 if (purple_prefs_get_bool(PREFS_EVENT_CHAT_NICK
) &&
262 (purple_utf8_has_word(msg
, nick
)))
263 notify(conv
, _("%s said your nick in %s"), sender
, purple_conversation_get_name(conv
));
264 else if (purple_prefs_get_bool(PREFS_EVENT_CHAT_MSG
))
265 notify(conv
, _("%s sent a message in %s"), sender
, purple_conversation_get_name(conv
));
274 {PREFS_EVENT_SIGNONF
, N_("Buddy signs on/off")},
275 {PREFS_EVENT_IM_MSG
, N_("You receive an IM")},
276 {PREFS_EVENT_CHAT_MSG
, N_("Someone speaks in a chat")},
277 {PREFS_EVENT_CHAT_NICK
, N_("Someone says your name in a chat")},
282 pref_toggled(GntTree
*tree
, char *key
, gpointer null
)
284 purple_prefs_set_bool(key
, gnt_tree_get_choice(tree
, key
));
288 toggle_option(GntCheckBox
*check
, gpointer str
)
290 purple_prefs_set_bool(str
, gnt_check_box_get_checked(check
));
296 GntWidget
*window
, *tree
, *check
;
299 window
= gnt_vbox_new(FALSE
);
300 gnt_box_set_pad(GNT_BOX(window
), 0);
301 gnt_box_set_alignment(GNT_BOX(window
), GNT_ALIGN_MID
);
302 gnt_box_set_fill(GNT_BOX(window
), TRUE
);
304 gnt_box_add_widget(GNT_BOX(window
),
305 /* Translators: "toaster" here means "pop-up". */
306 gnt_label_new(_("Notify with a toaster when")));
308 tree
= gnt_tree_new();
309 gnt_box_add_widget(GNT_BOX(window
), tree
);
311 for (i
= 0; prefs
[i
].pref
; i
++)
313 gnt_tree_add_choice(GNT_TREE(tree
), prefs
[i
].pref
,
314 gnt_tree_create_row(GNT_TREE(tree
), prefs
[i
].display
), NULL
, NULL
);
315 gnt_tree_set_choice(GNT_TREE(tree
), prefs
[i
].pref
,
316 purple_prefs_get_bool(prefs
[i
].pref
));
318 gnt_tree_set_col_width(GNT_TREE(tree
), 0, 40);
319 g_signal_connect(G_OBJECT(tree
), "toggled", G_CALLBACK(pref_toggled
), NULL
);
321 check
= gnt_check_box_new(_("Beep too!"));
322 gnt_check_box_set_checked(GNT_CHECK_BOX(check
), purple_prefs_get_bool(PREFS_BEEP
));
323 g_signal_connect(G_OBJECT(check
), "toggled", G_CALLBACK(toggle_option
), PREFS_BEEP
);
324 gnt_box_add_widget(GNT_BOX(window
), check
);
327 check
= gnt_check_box_new(_("Set URGENT for the terminal window."));
328 gnt_check_box_set_checked(GNT_CHECK_BOX(check
), purple_prefs_get_bool(PREFS_URGENT
));
329 g_signal_connect(G_OBJECT(check
), "toggled", G_CALLBACK(toggle_option
), PREFS_URGENT
);
330 gnt_box_add_widget(GNT_BOX(window
), check
);
336 static FinchPluginInfo
*
337 plugin_query(GError
**error
)
339 const gchar
* const authors
[] = {
340 "Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
344 return finch_plugin_info_new(
347 "version", DISPLAY_VERSION
,
348 "category", N_("Notification"),
349 "summary", N_("Toaster plugin"),
350 "description", N_("Toaster plugin"),
352 "website", PURPLE_WEBSITE
,
353 "abi-version", PURPLE_ABI_VERSION
,
354 "gnt-pref-frame-cb", config_frame
,
360 plugin_load(PurplePlugin
*plugin
, GError
**error
)
362 purple_prefs_add_none("/plugins");
363 purple_prefs_add_none("/plugins/gnt");
365 purple_prefs_add_none("/plugins/gnt/gntgf");
366 purple_prefs_add_none(PREFS_EVENT
);
368 purple_prefs_add_bool(PREFS_EVENT_SIGNONF
, TRUE
);
369 purple_prefs_add_bool(PREFS_EVENT_IM_MSG
, TRUE
);
370 purple_prefs_add_bool(PREFS_EVENT_CHAT_MSG
, TRUE
);
371 purple_prefs_add_bool(PREFS_EVENT_CHAT_NICK
, TRUE
);
373 purple_prefs_add_bool(PREFS_BEEP
, TRUE
);
375 purple_prefs_add_bool(PREFS_URGENT
, FALSE
);
378 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", plugin
,
379 PURPLE_CALLBACK(buddy_signed_on
), NULL
);
380 purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", plugin
,
381 PURPLE_CALLBACK(buddy_signed_off
), NULL
);
382 purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", plugin
,
383 PURPLE_CALLBACK(received_im_msg
), NULL
);
384 purple_signal_connect(purple_conversations_get_handle(), "received-chat-msg", plugin
,
385 PURPLE_CALLBACK(received_chat_msg
), NULL
);
387 memset(&gpsy
, 0, sizeof(gpsy
));
388 memset(&gpsw
, 0, sizeof(gpsw
));
394 plugin_unload(PurplePlugin
*plugin
, GError
**error
)
398 GntToast
*toast
= toasters
->data
;
399 destroy_toaster(toast
);
404 PURPLE_PLUGIN_INIT(PLUGIN_STATIC_NAME
, plugin_query
, plugin_load
, plugin_unload
);