| |
1 /* |
| |
2 * Pidgin - Transparency plugin |
| |
3 * |
| |
4 * Copyright (C) 1998-2002, Rob Flynn <rob@marko.net> |
| |
5 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com> |
| |
6 * Copyright (C) 2005, Daniel Atallah <daniel_atallah@yahoo.com> |
| |
7 * |
| |
8 * This program is free software; you can redistribute it and/or |
| |
9 * modify it under the terms of the GNU General Public License as |
| |
10 * published by the Free Software Foundation; either version 2 of the |
| |
11 * License, or (at your option) any later version. |
| |
12 * |
| |
13 * This program is distributed in the hope that it will be useful, but |
| |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| |
16 * General Public License for more details. |
| |
17 * |
| |
18 * You should have received a copy of the GNU General Public License |
| |
19 * along with this program; if not, write to the Free Software |
| |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| |
21 * 02111-1301, USA. |
| |
22 * |
| |
23 */ |
| |
24 #include "internal.h" |
| |
25 |
| |
26 #include "core.h" |
| |
27 #include "prefs.h" |
| |
28 #include "debug.h" |
| |
29 |
| |
30 #include "gtkconv.h" |
| |
31 #include "gtkplugin.h" |
| |
32 #include "gtkprefs.h" |
| |
33 #include "gtkblist.h" |
| |
34 #include "gtkutils.h" |
| |
35 #include "signals.h" |
| |
36 #include "version.h" |
| |
37 |
| |
38 /* |
| |
39 * MACROS & DEFINES |
| |
40 */ |
| |
41 /* The plugin name is left unchanged from its WinAPI days in order to keep it |
| |
42 * loading for users who were using it. */ |
| |
43 #define WINTRANS_PLUGIN_ID "gtk-win-trans" |
| |
44 |
| |
45 #define blist (purple_get_blist() \ |
| |
46 ? (PIDGIN_BLIST(purple_get_blist()) \ |
| |
47 ? ((PIDGIN_BLIST(purple_get_blist()))->window) \ |
| |
48 : NULL) \ |
| |
49 : NULL) |
| |
50 |
| |
51 /* |
| |
52 * DATA STRUCTS |
| |
53 */ |
| |
54 typedef struct { |
| |
55 GtkWidget *win; |
| |
56 GtkWidget *slider; |
| |
57 } slider_win; |
| |
58 |
| |
59 /* |
| |
60 * LOCALS |
| |
61 */ |
| |
62 static const char *OPT_WINTRANS_IM_ENABLED= "/plugins/gtk/transparency/im_enabled"; |
| |
63 static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/transparency/im_alpha"; |
| |
64 static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/transparency/im_slider"; |
| |
65 static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/transparency/im_solid_onfocus"; |
| |
66 static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/transparency/im_always_on_top"; |
| |
67 static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/transparency/bl_enabled"; |
| |
68 static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/transparency/bl_alpha"; |
| |
69 static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/transparency/bl_solid_onfocus"; |
| |
70 static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/transparency/bl_always_on_top"; |
| |
71 static GSList *window_list = NULL; |
| |
72 |
| |
73 /* |
| |
74 * CODE |
| |
75 */ |
| |
76 |
| |
77 /* Set window transparency level */ |
| |
78 static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled, |
| |
79 gboolean always_on_top) { |
| |
80 if (enabled) { |
| |
81 gdk_window_set_opacity(window->window, alpha / 255.0); |
| |
82 gdk_window_set_keep_above(window->window, always_on_top); |
| |
83 } else { |
| |
84 gdk_window_set_opacity(window->window, 1); |
| |
85 gdk_window_set_keep_above(window->window, 0); |
| |
86 } |
| |
87 } |
| |
88 |
| |
89 /* When a conv window is focused, if we're only transparent when unfocused, |
| |
90 * deal with transparency */ |
| |
91 static gboolean focus_conv_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) { |
| |
92 if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED) |
| |
93 && purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) { |
| |
94 GtkWidget *window = (GtkWidget *) d; |
| |
95 if (e->in) { /* Focused */ |
| |
96 set_wintrans(window, 0, FALSE, |
| |
97 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
98 } else { |
| |
99 set_wintrans(window, |
| |
100 purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA), |
| |
101 TRUE, |
| |
102 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
103 } |
| |
104 } |
| |
105 return FALSE; |
| |
106 } |
| |
107 |
| |
108 /* When buddy list window is focused, |
| |
109 * if we're only transparent when unfocused, deal with transparency */ |
| |
110 static gboolean focus_blist_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) { |
| |
111 if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED) |
| |
112 && purple_prefs_get_bool(OPT_WINTRANS_BL_ONFOCUS)) { |
| |
113 GtkWidget *window = (GtkWidget *) d; |
| |
114 if (e->in) { /* Focused */ |
| |
115 set_wintrans(window, 0, FALSE, |
| |
116 purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP)); |
| |
117 } else { |
| |
118 set_wintrans(window, |
| |
119 purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA), |
| |
120 TRUE, |
| |
121 purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP)); |
| |
122 } |
| |
123 } |
| |
124 return FALSE; |
| |
125 } |
| |
126 |
| |
127 static void change_alpha(GtkWidget *w, gpointer data) { |
| |
128 int alpha = gtk_range_get_value(GTK_RANGE(w)); |
| |
129 purple_prefs_set_int(OPT_WINTRANS_IM_ALPHA, alpha); |
| |
130 |
| |
131 /* If we're in no-transparency on focus mode, |
| |
132 * don't take effect immediately */ |
| |
133 if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) |
| |
134 set_wintrans(GTK_WIDGET(data), alpha, TRUE, |
| |
135 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
136 } |
| |
137 |
| |
138 |
| |
139 static GtkWidget *wintrans_slider(GtkWidget *win) { |
| |
140 GtkWidget *hbox; |
| |
141 GtkWidget *label, *slider; |
| |
142 GtkWidget *frame; |
| |
143 |
| |
144 int imalpha = purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA); |
| |
145 |
| |
146 frame = gtk_frame_new(NULL); |
| |
147 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); |
| |
148 gtk_widget_show(frame); |
| |
149 |
| |
150 hbox = gtk_hbox_new(FALSE, 5); |
| |
151 gtk_container_add(GTK_CONTAINER(frame), hbox); |
| |
152 |
| |
153 label = gtk_label_new(_("Opacity:")); |
| |
154 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); |
| |
155 gtk_widget_show(hbox); |
| |
156 |
| |
157 slider = gtk_hscale_new_with_range(50, 255, 1); |
| |
158 gtk_range_set_value(GTK_RANGE(slider), imalpha); |
| |
159 gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1); |
| |
160 |
| |
161 /* On slider val change, update window's transparency level */ |
| |
162 g_signal_connect(GTK_OBJECT(slider), "value-changed", |
| |
163 G_CALLBACK(change_alpha), win); |
| |
164 |
| |
165 gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5); |
| |
166 |
| |
167 /* Set the initial transparency level */ |
| |
168 set_wintrans(win, imalpha, TRUE, |
| |
169 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
170 |
| |
171 gtk_widget_show_all(hbox); |
| |
172 |
| |
173 return frame; |
| |
174 } |
| |
175 |
| |
176 static slider_win* find_slidwin(GtkWidget *win) { |
| |
177 GSList *tmp = window_list; |
| |
178 |
| |
179 while (tmp) { |
| |
180 if (((slider_win*) (tmp->data))->win == win) |
| |
181 return (slider_win*) tmp->data; |
| |
182 tmp = tmp->next; |
| |
183 } |
| |
184 return NULL; |
| |
185 } |
| |
186 |
| |
187 /* Clean up transparency stuff for the conv window */ |
| |
188 static void cleanup_conv_window(PidginWindow *win) { |
| |
189 GtkWidget *window = win->window; |
| |
190 slider_win *slidwin = NULL; |
| |
191 |
| |
192 /* Remove window from the window list */ |
| |
193 purple_debug_info(WINTRANS_PLUGIN_ID, |
| |
194 "Conv window destroyed... removing from list\n"); |
| |
195 |
| |
196 if ((slidwin = find_slidwin(window))) { |
| |
197 window_list = g_slist_remove(window_list, slidwin); |
| |
198 g_free(slidwin); |
| |
199 } |
| |
200 |
| |
201 /* Remove the focus cbs */ |
| |
202 g_signal_handlers_disconnect_by_func(G_OBJECT(window), |
| |
203 G_CALLBACK(focus_conv_win_cb), window); |
| |
204 } |
| |
205 |
| |
206 static void |
| |
207 conversation_delete_cb(PurpleConversation *conv) { |
| |
208 PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv)); |
| |
209 /* If it is the last conversation in the window, cleanup */ |
| |
210 if (win != NULL && pidgin_conv_window_get_gtkconv_count(win) == 1) |
| |
211 cleanup_conv_window(win); |
| |
212 } |
| |
213 |
| |
214 static void set_blist_trans(GtkWidget *w, const char *pref) { |
| |
215 gboolean enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); |
| |
216 purple_prefs_set_bool(pref, enabled); |
| |
217 if (blist) { |
| |
218 set_wintrans(blist, purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA), |
| |
219 purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED), |
| |
220 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
221 } |
| |
222 } |
| |
223 |
| |
224 static void add_slider(GtkWidget *win) { |
| |
225 GList *wl, *wl1; |
| |
226 GtkWidget *vbox = NULL; |
| |
227 |
| |
228 /* Look up this window to see if it already has a slider */ |
| |
229 if (!find_slidwin(win)) { |
| |
230 GtkWidget *slider_box = NULL; |
| |
231 slider_win *slidwin = NULL; |
| |
232 GtkRequisition slidereq; |
| |
233 gint width, height; |
| |
234 |
| |
235 /* Get top vbox */ |
| |
236 for (wl1 = wl = gtk_container_get_children( |
| |
237 GTK_CONTAINER(win)); |
| |
238 wl != NULL; |
| |
239 wl = wl->next) { |
| |
240 if (GTK_IS_VBOX(GTK_OBJECT(wl->data))) |
| |
241 vbox = GTK_WIDGET(wl->data); |
| |
242 else { |
| |
243 purple_debug_error(WINTRANS_PLUGIN_ID, |
| |
244 "no vbox found\n"); |
| |
245 return; |
| |
246 } |
| |
247 } |
| |
248 g_list_free(wl1); |
| |
249 |
| |
250 slider_box = wintrans_slider(win); |
| |
251 /* Figure out how tall the slider wants to be */ |
| |
252 gtk_widget_size_request(slider_box, &slidereq); |
| |
253 gtk_window_get_size(GTK_WINDOW(win), &width, &height); |
| |
254 gtk_box_pack_start(GTK_BOX(vbox), |
| |
255 slider_box, FALSE, FALSE, 0); |
| |
256 /* Add window to list, to track that it has a slider */ |
| |
257 slidwin = g_new0(slider_win, 1); |
| |
258 slidwin->win = win; |
| |
259 slidwin->slider = slider_box; |
| |
260 window_list = g_slist_append(window_list, slidwin); |
| |
261 } |
| |
262 } |
| |
263 |
| |
264 static void remove_sliders() { |
| |
265 if (window_list) { |
| |
266 GSList *tmp = window_list; |
| |
267 while (tmp) { |
| |
268 slider_win *slidwin = (slider_win*) tmp->data; |
| |
269 if (slidwin != NULL && |
| |
270 GTK_IS_WINDOW(slidwin->win)) { |
| |
271 gtk_widget_destroy(slidwin->slider); |
| |
272 } |
| |
273 g_free(slidwin); |
| |
274 tmp = tmp->next; |
| |
275 } |
| |
276 g_slist_free(window_list); |
| |
277 window_list = NULL; |
| |
278 } |
| |
279 } |
| |
280 |
| |
281 /* Remove all transparency related aspects from conversation windows */ |
| |
282 static void remove_convs_wintrans(gboolean remove_signal) { |
| |
283 GList *wins; |
| |
284 |
| |
285 for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) { |
| |
286 PidginWindow *win = wins->data; |
| |
287 GtkWidget *window = win->window; |
| |
288 |
| |
289 if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) |
| |
290 set_wintrans(window, 0, FALSE, FALSE); |
| |
291 |
| |
292 /* Remove the focus cbs */ |
| |
293 if (remove_signal) |
| |
294 g_signal_handlers_disconnect_by_func(G_OBJECT(window), |
| |
295 G_CALLBACK(focus_conv_win_cb), window); |
| |
296 } |
| |
297 |
| |
298 remove_sliders(); |
| |
299 } |
| |
300 |
| |
301 static void set_conv_window_trans(PidginWindow *oldwin, PidginWindow *newwin) { |
| |
302 GtkWidget *win = newwin->window; |
| |
303 |
| |
304 /* check prefs to see if we want trans */ |
| |
305 if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) { |
| |
306 set_wintrans(win, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA), |
| |
307 TRUE, purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
308 |
| |
309 if (purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) { |
| |
310 add_slider(win); |
| |
311 } |
| |
312 } |
| |
313 |
| |
314 /* If we're moving from one window to another, |
| |
315 * add the focus listeners to the new window if not already there */ |
| |
316 if (oldwin != NULL && oldwin != newwin) { |
| |
317 if (pidgin_conv_window_get_gtkconv_count(newwin) == 0) { |
| |
318 g_signal_connect(G_OBJECT(win), "focus_in_event", |
| |
319 G_CALLBACK(focus_conv_win_cb), win); |
| |
320 g_signal_connect(G_OBJECT(win), "focus_out_event", |
| |
321 G_CALLBACK(focus_conv_win_cb), win); |
| |
322 } |
| |
323 |
| |
324 /* If we've moved the last conversation, cleanup the window */ |
| |
325 if (pidgin_conv_window_get_gtkconv_count(oldwin) == 1) |
| |
326 cleanup_conv_window(oldwin); |
| |
327 } |
| |
328 } |
| |
329 |
| |
330 static void update_convs_wintrans(GtkWidget *toggle_btn, const char *pref) { |
| |
331 purple_prefs_set_bool(pref, gtk_toggle_button_get_active( |
| |
332 GTK_TOGGLE_BUTTON(toggle_btn))); |
| |
333 |
| |
334 if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) { |
| |
335 GList *wins; |
| |
336 |
| |
337 for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) { |
| |
338 PidginWindow *win = wins->data; |
| |
339 set_conv_window_trans(NULL, win); |
| |
340 } |
| |
341 |
| |
342 if (!purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) |
| |
343 remove_sliders(); |
| |
344 } |
| |
345 else |
| |
346 remove_convs_wintrans(FALSE); |
| |
347 } |
| |
348 |
| |
349 static void |
| |
350 conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) { |
| |
351 PidginConversation *pconv = PIDGIN_CONVERSATION(conv); |
| |
352 PidginWindow *win = pidgin_conv_get_window(pconv); |
| |
353 |
| |
354 if (type == PURPLE_CONV_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv) |
| |
355 && pconv->unseen_state == PIDGIN_UNSEEN_NONE |
| |
356 && pidgin_conv_window_get_gtkconv_count(win) == 1) { |
| |
357 GtkWidget *window = win->window; |
| |
358 gboolean has_focus; |
| |
359 |
| |
360 g_object_get(G_OBJECT(window), "has-toplevel-focus", &has_focus, NULL); |
| |
361 |
| |
362 if (!has_focus || !purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) |
| |
363 set_conv_window_trans(NULL, win); |
| |
364 |
| |
365 if (g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC, |
| |
366 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) { |
| |
367 g_signal_connect(G_OBJECT(window), "focus_in_event", |
| |
368 G_CALLBACK(focus_conv_win_cb), window); |
| |
369 g_signal_connect(G_OBJECT(window), "focus_out_event", |
| |
370 G_CALLBACK(focus_conv_win_cb), window); |
| |
371 } |
| |
372 } |
| |
373 } |
| |
374 |
| |
375 static void |
| |
376 new_conversation_cb(PurpleConversation *conv) { |
| |
377 PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv)); |
| |
378 |
| |
379 /* If it is the first conversation in the window, |
| |
380 * add the sliders, and set transparency */ |
| |
381 if (!pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) && pidgin_conv_window_get_gtkconv_count(win) == 1) { |
| |
382 GtkWidget *window = win->window; |
| |
383 |
| |
384 set_conv_window_trans(NULL, win); |
| |
385 |
| |
386 g_signal_connect(G_OBJECT(window), "focus_in_event", |
| |
387 G_CALLBACK(focus_conv_win_cb), window); |
| |
388 g_signal_connect(G_OBJECT(window), "focus_out_event", |
| |
389 G_CALLBACK(focus_conv_win_cb), window); |
| |
390 } |
| |
391 } |
| |
392 |
| |
393 static void |
| |
394 blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) { |
| |
395 if (blist) { |
| |
396 if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) { |
| |
397 set_wintrans(blist, |
| |
398 purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA), |
| |
399 TRUE, |
| |
400 purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP)); |
| |
401 } |
| |
402 |
| |
403 g_signal_connect(G_OBJECT(blist), "focus_in_event", |
| |
404 G_CALLBACK(focus_blist_win_cb), blist); |
| |
405 g_signal_connect(G_OBJECT(blist), "focus_out_event", |
| |
406 G_CALLBACK(focus_blist_win_cb), blist); |
| |
407 } |
| |
408 } |
| |
409 |
| |
410 static void alpha_change(GtkWidget *w, gpointer data) { |
| |
411 GList *wins; |
| |
412 int imalpha = gtk_range_get_value(GTK_RANGE(w)); |
| |
413 |
| |
414 for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) { |
| |
415 PidginWindow *win = wins->data; |
| |
416 set_wintrans(win->window, imalpha, TRUE, |
| |
417 purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP)); |
| |
418 } |
| |
419 } |
| |
420 |
| |
421 static void alpha_pref_set_int (GtkWidget *w, GdkEventFocus *e, const char *pref) |
| |
422 { |
| |
423 int alpha = gtk_range_get_value(GTK_RANGE(w)); |
| |
424 purple_prefs_set_int(pref, alpha); |
| |
425 } |
| |
426 |
| |
427 static void bl_alpha_change(GtkWidget *w, gpointer data) { |
| |
428 if (blist) |
| |
429 change_alpha(w, blist); |
| |
430 } |
| |
431 |
| |
432 static void update_existing_convs() { |
| |
433 GList *wins; |
| |
434 |
| |
435 for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) { |
| |
436 PidginWindow *win = wins->data; |
| |
437 GtkWidget *window = win->window; |
| |
438 |
| |
439 set_conv_window_trans(NULL, win); |
| |
440 |
| |
441 g_signal_connect(G_OBJECT(window), "focus_in_event", |
| |
442 G_CALLBACK(focus_conv_win_cb), window); |
| |
443 g_signal_connect(G_OBJECT(window), "focus_out_event", |
| |
444 G_CALLBACK(focus_conv_win_cb), window); |
| |
445 } |
| |
446 } |
| |
447 |
| |
448 /* |
| |
449 * EXPORTED FUNCTIONS |
| |
450 */ |
| |
451 static gboolean plugin_load(PurplePlugin *plugin) { |
| |
452 |
| |
453 purple_signal_connect(purple_conversations_get_handle(), |
| |
454 "conversation-created", plugin, |
| |
455 PURPLE_CALLBACK(new_conversation_cb), NULL); |
| |
456 |
| |
457 /* Set callback to remove window from the list, if the window is destroyed */ |
| |
458 purple_signal_connect(purple_conversations_get_handle(), |
| |
459 "deleting-conversation", plugin, |
| |
460 PURPLE_CALLBACK(conversation_delete_cb), NULL); |
| |
461 |
| |
462 purple_signal_connect(pidgin_conversations_get_handle(), |
| |
463 "conversation-dragging", plugin, |
| |
464 PURPLE_CALLBACK(set_conv_window_trans), NULL); |
| |
465 |
| |
466 purple_signal_connect(purple_conversations_get_handle(), |
| |
467 "conversation-updated", plugin, |
| |
468 PURPLE_CALLBACK(conv_updated_cb), NULL); |
| |
469 |
| |
470 update_existing_convs(); |
| |
471 |
| |
472 if (blist) |
| |
473 blist_created_cb(NULL, NULL); |
| |
474 else |
| |
475 purple_signal_connect(pidgin_blist_get_handle(), |
| |
476 "gtkblist-created", plugin, |
| |
477 PURPLE_CALLBACK(blist_created_cb), NULL); |
| |
478 |
| |
479 |
| |
480 return TRUE; |
| |
481 } |
| |
482 |
| |
483 static gboolean plugin_unload(PurplePlugin *plugin) { |
| |
484 purple_debug_info(WINTRANS_PLUGIN_ID, "Unloading transparency plugin\n"); |
| |
485 |
| |
486 remove_convs_wintrans(TRUE); |
| |
487 |
| |
488 if (blist) { |
| |
489 if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) |
| |
490 set_wintrans(blist, 0, FALSE, FALSE); |
| |
491 |
| |
492 /* Remove the focus cbs */ |
| |
493 g_signal_handlers_disconnect_by_func(G_OBJECT(blist), |
| |
494 G_CALLBACK(focus_blist_win_cb), blist); |
| |
495 } |
| |
496 |
| |
497 return TRUE; |
| |
498 } |
| |
499 |
| |
500 static GtkWidget *get_config_frame(PurplePlugin *plugin) { |
| |
501 GtkWidget *ret; |
| |
502 GtkWidget *imtransbox, *bltransbox; |
| |
503 GtkWidget *hbox; |
| |
504 GtkWidget *label, *slider; |
| |
505 GtkWidget *button; |
| |
506 GtkWidget *trans_box; |
| |
507 |
| |
508 ret = gtk_vbox_new(FALSE, 18); |
| |
509 gtk_container_set_border_width(GTK_CONTAINER (ret), 12); |
| |
510 |
| |
511 /* IM Convo trans options */ |
| |
512 imtransbox = pidgin_make_frame(ret, _("IM Conversation Windows")); |
| |
513 button = pidgin_prefs_checkbox(_("_IM window transparency"), |
| |
514 OPT_WINTRANS_IM_ENABLED, imtransbox); |
| |
515 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
516 G_CALLBACK(update_convs_wintrans), |
| |
517 (gpointer) OPT_WINTRANS_IM_ENABLED); |
| |
518 |
| |
519 trans_box = gtk_vbox_new(FALSE, 18); |
| |
520 if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) |
| |
521 gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE); |
| |
522 gtk_widget_show(trans_box); |
| |
523 |
| |
524 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
525 G_CALLBACK(pidgin_toggle_sensitive), trans_box); |
| |
526 |
| |
527 button = pidgin_prefs_checkbox(_("_Show slider bar in IM window"), |
| |
528 OPT_WINTRANS_IM_SLIDER, trans_box); |
| |
529 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
530 G_CALLBACK(update_convs_wintrans), |
| |
531 (gpointer) OPT_WINTRANS_IM_SLIDER); |
| |
532 |
| |
533 button = pidgin_prefs_checkbox( |
| |
534 _("Remove IM window transparency on focus"), |
| |
535 OPT_WINTRANS_IM_ONFOCUS, trans_box); |
| |
536 |
| |
537 button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_IM_ONTOP, |
| |
538 trans_box); |
| |
539 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
540 G_CALLBACK(update_convs_wintrans), |
| |
541 (gpointer) OPT_WINTRANS_IM_ONTOP); |
| |
542 |
| |
543 gtk_box_pack_start(GTK_BOX(imtransbox), trans_box, FALSE, FALSE, 5); |
| |
544 |
| |
545 /* IM transparency slider */ |
| |
546 hbox = gtk_hbox_new(FALSE, 5); |
| |
547 |
| |
548 label = gtk_label_new(_("Opacity:")); |
| |
549 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); |
| |
550 |
| |
551 slider = gtk_hscale_new_with_range(50, 255, 1); |
| |
552 gtk_range_set_value(GTK_RANGE(slider), |
| |
553 purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA)); |
| |
554 gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1); |
| |
555 |
| |
556 g_signal_connect(GTK_OBJECT(slider), "value-changed", |
| |
557 G_CALLBACK(alpha_change), NULL); |
| |
558 g_signal_connect(GTK_OBJECT(slider), "focus-out-event", |
| |
559 G_CALLBACK(alpha_pref_set_int), |
| |
560 (gpointer) OPT_WINTRANS_IM_ALPHA); |
| |
561 |
| |
562 gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5); |
| |
563 |
| |
564 gtk_widget_show_all(hbox); |
| |
565 |
| |
566 gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5); |
| |
567 |
| |
568 /* Buddy List trans options */ |
| |
569 bltransbox = pidgin_make_frame (ret, _("Buddy List Window")); |
| |
570 button = pidgin_prefs_checkbox(_("_Buddy List window transparency"), |
| |
571 OPT_WINTRANS_BL_ENABLED, bltransbox); |
| |
572 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
573 G_CALLBACK(set_blist_trans), |
| |
574 (gpointer) OPT_WINTRANS_BL_ENABLED); |
| |
575 |
| |
576 trans_box = gtk_vbox_new(FALSE, 18); |
| |
577 if (!purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) |
| |
578 gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE); |
| |
579 gtk_widget_show(trans_box); |
| |
580 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
581 G_CALLBACK(pidgin_toggle_sensitive), trans_box); |
| |
582 button = pidgin_prefs_checkbox( |
| |
583 _("Remove Buddy List window transparency on focus"), |
| |
584 OPT_WINTRANS_BL_ONFOCUS, trans_box); |
| |
585 button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_BL_ONTOP, |
| |
586 trans_box); |
| |
587 g_signal_connect(GTK_OBJECT(button), "clicked", |
| |
588 G_CALLBACK(set_blist_trans), |
| |
589 (gpointer) OPT_WINTRANS_BL_ONTOP); |
| |
590 gtk_box_pack_start(GTK_BOX(bltransbox), trans_box, FALSE, FALSE, 5); |
| |
591 |
| |
592 /* IM transparency slider */ |
| |
593 hbox = gtk_hbox_new(FALSE, 5); |
| |
594 |
| |
595 label = gtk_label_new(_("Opacity:")); |
| |
596 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); |
| |
597 |
| |
598 slider = gtk_hscale_new_with_range(50, 255, 1); |
| |
599 gtk_range_set_value(GTK_RANGE(slider), |
| |
600 purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA)); |
| |
601 |
| |
602 gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1); |
| |
603 |
| |
604 g_signal_connect(GTK_OBJECT(slider), "value-changed", |
| |
605 G_CALLBACK(bl_alpha_change), NULL); |
| |
606 g_signal_connect(GTK_OBJECT(slider), "focus-out-event", |
| |
607 G_CALLBACK(alpha_pref_set_int), |
| |
608 (gpointer) OPT_WINTRANS_BL_ALPHA); |
| |
609 |
| |
610 gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5); |
| |
611 |
| |
612 gtk_widget_show_all(hbox); |
| |
613 |
| |
614 gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5); |
| |
615 |
| |
616 gtk_widget_show_all(ret); |
| |
617 return ret; |
| |
618 } |
| |
619 |
| |
620 static PidginPluginUiInfo ui_info = |
| |
621 { |
| |
622 get_config_frame, |
| |
623 0, /* page_num (Reserved) */ |
| |
624 |
| |
625 /* padding */ |
| |
626 NULL, |
| |
627 NULL, |
| |
628 NULL, |
| |
629 NULL |
| |
630 }; |
| |
631 |
| |
632 static PurplePluginInfo info = |
| |
633 { |
| |
634 PURPLE_PLUGIN_MAGIC, |
| |
635 PURPLE_MAJOR_VERSION, |
| |
636 PURPLE_MINOR_VERSION, |
| |
637 PURPLE_PLUGIN_STANDARD, /**< type */ |
| |
638 PIDGIN_PLUGIN_TYPE, /**< ui_requirement */ |
| |
639 0, /**< flags */ |
| |
640 NULL, /**< dependencies */ |
| |
641 PURPLE_PRIORITY_DEFAULT, /**< priority */ |
| |
642 WINTRANS_PLUGIN_ID, /**< id */ |
| |
643 N_("Transparency"), /**< name */ |
| |
644 DISPLAY_VERSION, /**< version */ |
| |
645 /** summary */ |
| |
646 N_("Variable Transparency for the buddy list and conversations."), |
| |
647 /** description */ |
| |
648 N_("This plugin enables variable alpha transparency on conversation windows and the buddy list."), |
| |
649 "Herman Bloggs <hermanator12002@yahoo.com>", /**< author */ |
| |
650 PURPLE_WEBSITE, /**< homepage */ |
| |
651 plugin_load, /**< load */ |
| |
652 plugin_unload, /**< unload */ |
| |
653 NULL, /**< destroy */ |
| |
654 &ui_info, /**< ui_info */ |
| |
655 NULL, /**< extra_info */ |
| |
656 NULL, /**< prefs_info */ |
| |
657 NULL, /**< actions */ |
| |
658 |
| |
659 /* padding */ |
| |
660 NULL, |
| |
661 NULL, |
| |
662 NULL, |
| |
663 NULL |
| |
664 }; |
| |
665 |
| |
666 static void |
| |
667 init_plugin(PurplePlugin *plugin) |
| |
668 { |
| |
669 purple_prefs_add_none("/plugins/gtk"); |
| |
670 purple_prefs_add_none("/plugins/gtk/transparency"); |
| |
671 purple_prefs_add_bool(OPT_WINTRANS_IM_ENABLED, FALSE); |
| |
672 purple_prefs_add_int(OPT_WINTRANS_IM_ALPHA, 255); |
| |
673 purple_prefs_add_bool(OPT_WINTRANS_IM_SLIDER, FALSE); |
| |
674 purple_prefs_add_bool(OPT_WINTRANS_IM_ONFOCUS, FALSE); |
| |
675 purple_prefs_add_bool(OPT_WINTRANS_IM_ONTOP, FALSE); |
| |
676 purple_prefs_add_bool(OPT_WINTRANS_BL_ENABLED, FALSE); |
| |
677 purple_prefs_add_int(OPT_WINTRANS_BL_ALPHA, 255); |
| |
678 purple_prefs_add_bool(OPT_WINTRANS_BL_ONFOCUS, FALSE); |
| |
679 purple_prefs_add_bool(OPT_WINTRANS_BL_ONTOP, FALSE); |
| |
680 purple_prefs_rename("/plugins/gtk/win32/wintrans", "/plugins/gtk/transparency"); |
| |
681 } |
| |
682 |
| |
683 PURPLE_INIT_PLUGIN(wintrans, init_plugin, info) |