1 /*
2 * Mouse gestures plugin for Purple
3 *
4 * Copyright (C) 2003 Christian Hammond.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02111-1301, USA.
20 */
21 #include "internal.h"
22 #include "pidgin.h"
23
24 #include "debug.h"
25 #include "prefs.h"
26 #include "signals.h"
27 #include "version.h"
28
29 #include "gtkconv.h"
30 #include "gtkplugin.h"
31 #include "gtkutils.h"
32
33 #include "gstroke.h"
34
35 #define GESTURES_PLUGIN_ID "gtk-x11-gestures"
36
37 static void
stroke_close(GtkWidget * widget,void * data)38 stroke_close(GtkWidget *widget, void *data)
39 {
40 PurpleConversation *conv;
41 PidginConversation *gtkconv;
42
43 conv = (PurpleConversation *)data;
44
45 /* Double-check */
46 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
47 return;
48
49 gtkconv = PIDGIN_CONVERSATION(conv);
50
51 gstroke_cleanup(gtkconv->imhtml);
52 purple_conversation_destroy(conv);
53 }
54
55 static void
switch_page(PidginWindow * win,GtkDirectionType dir)56 switch_page(PidginWindow *win, GtkDirectionType dir)
57 {
58 int count, current;
59
60 count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook));
61 current = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook));
62
63 if (dir == GTK_DIR_LEFT)
64 {
65 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), current - 1);
66 }
67 else if (dir == GTK_DIR_RIGHT)
68 {
69 if (current == count - 1)
70 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
71 else
72 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), current + 1);
73 }
74 }
75
76 static void
stroke_prev_tab(GtkWidget * widget,void * data)77 stroke_prev_tab(GtkWidget *widget, void *data)
78 {
79 PurpleConversation *conv;
80 PidginConversation *gtkconv;
81 PidginWindow *win;
82
83 conv = (PurpleConversation *)data;
84 gtkconv = PIDGIN_CONVERSATION(conv);
85 win = gtkconv->win;
86
87 switch_page(win, GTK_DIR_LEFT);
88 }
89
90 static void
stroke_next_tab(GtkWidget * widget,void * data)91 stroke_next_tab(GtkWidget *widget, void *data)
92 {
93 PurpleConversation *conv;
94 PidginWindow *win;
95
96 conv = (PurpleConversation *)data;
97 win = PIDGIN_CONVERSATION(conv)->win;
98
99 switch_page(win, GTK_DIR_RIGHT);
100 }
101
102 static void
stroke_new_win(GtkWidget * widget,void * data)103 stroke_new_win(GtkWidget *widget, void *data)
104 {
105 PidginWindow *new_win, *old_win;
106 PurpleConversation *conv;
107
108 conv = (PurpleConversation *)data;
109 old_win = PIDGIN_CONVERSATION(conv)->win;
110
111 if (pidgin_conv_window_get_gtkconv_count(old_win) <= 1)
112 return;
113
114 new_win = pidgin_conv_window_new();
115
116 pidgin_conv_window_remove_gtkconv(old_win, PIDGIN_CONVERSATION(conv));
117 pidgin_conv_window_add_gtkconv(new_win, PIDGIN_CONVERSATION(conv));
118
119 pidgin_conv_window_show(new_win);
120 }
121
122 static void
attach_signals(PurpleConversation * conv)123 attach_signals(PurpleConversation *conv)
124 {
125 PidginConversation *gtkconv;
126
127 gtkconv = PIDGIN_CONVERSATION(conv);
128
129 gstroke_enable(gtkconv->imhtml);
130 gstroke_signal_connect(gtkconv->imhtml, "14789", stroke_close, conv);
131 gstroke_signal_connect(gtkconv->imhtml, "1456", stroke_close, conv);
132 gstroke_signal_connect(gtkconv->imhtml, "1489", stroke_close, conv);
133 gstroke_signal_connect(gtkconv->imhtml, "74123", stroke_next_tab, conv);
134 gstroke_signal_connect(gtkconv->imhtml, "7456", stroke_next_tab, conv);
135 gstroke_signal_connect(gtkconv->imhtml, "96321", stroke_prev_tab, conv);
136 gstroke_signal_connect(gtkconv->imhtml, "9654", stroke_prev_tab, conv);
137 gstroke_signal_connect(gtkconv->imhtml, "25852", stroke_new_win, conv);
138 }
139
140 static void
new_conv_cb(PurpleConversation * conv)141 new_conv_cb(PurpleConversation *conv)
142 {
143 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv))
144 attach_signals(conv);
145 }
146
147 #if 0
148 #if GTK_CHECK_VERSION(2,4,0)
149 static void
150 mouse_button_menu_cb(GtkComboBox *opt, gpointer data)
151 {
152 int button = gtk_combo_box_get_active(opt);
153
154 gstroke_set_mouse_button(button + 2);
155 }
156 #else
157 static void
158 mouse_button_menu_cb(GtkMenuItem *item, gpointer data)
159 {
160 int button = (int)data;
161
162 gstroke_set_mouse_button(button + 2);
163 }
164 #endif
165 #endif
166
167 static void
toggle_draw_cb(GtkToggleButton * toggle,gpointer data)168 toggle_draw_cb(GtkToggleButton *toggle, gpointer data)
169 {
170 purple_prefs_set_bool("/plugins/gtk/X11/gestures/visual",
171 gtk_toggle_button_get_active(toggle));
172 }
173
174 static void
visual_pref_cb(const char * name,PurplePrefType type,gconstpointer value,gpointer data)175 visual_pref_cb(const char *name, PurplePrefType type, gconstpointer value,
176 gpointer data)
177 {
178 gstroke_set_draw_strokes((gboolean) GPOINTER_TO_INT(value) );
179 }
180
181 static gboolean
plugin_load(PurplePlugin * plugin)182 plugin_load(PurplePlugin *plugin)
183 {
184 PurpleConversation *conv;
185 GList *l;
186
187 for (l = purple_get_conversations(); l != NULL; l = l->next) {
188 conv = (PurpleConversation *)l->data;
189
190 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
191 continue;
192
193 attach_signals(conv);
194 }
195
196 purple_signal_connect(purple_conversations_get_handle(),
197 "conversation-created",
198 plugin, PURPLE_CALLBACK(new_conv_cb), NULL);
199
200 return TRUE;
201 }
202
203 static gboolean
plugin_unload(PurplePlugin * plugin)204 plugin_unload(PurplePlugin *plugin)
205 {
206 PurpleConversation *conv;
207 PidginConversation *gtkconv;
208 GList *l;
209
210 for (l = purple_get_conversations(); l != NULL; l = l->next) {
211 conv = (PurpleConversation *)l->data;
212
213 if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
214 continue;
215
216 gtkconv = PIDGIN_CONVERSATION(conv);
217
218 gstroke_cleanup(gtkconv->imhtml);
219 gstroke_disable(gtkconv->imhtml);
220 }
221
222 return TRUE;
223 }
224
225 static GtkWidget *
get_config_frame(PurplePlugin * plugin)226 get_config_frame(PurplePlugin *plugin)
227 {
228 GtkWidget *ret;
229 GtkWidget *vbox;
230 GtkWidget *toggle;
231 #if 0
232 GtkWidget *opt;
233 #if GTK_CHECK_VERSION(2,4,0)
234 GtkWidget *menu, *item;
235 #endif
236 #endif
237
238 /* Outside container */
239 ret = gtk_vbox_new(FALSE, 18);
240 gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
241
242 /* Configuration frame */
243 vbox = pidgin_make_frame(ret, _("Mouse Gestures Configuration"));
244
245 #if 0
246 #if GTK_CHECK_VERSION(2,4,0)
247 /* Mouse button drop-down menu */
248 opt = gtk_combo_box_new_text();
249
250 gtk_combo_box_append_text(_("Middle mouse button"));
251 gtk_combo_box_append_text(_("Right mouse button"));
252 g_signal_connect(G_OBJECT(opt), "changed",
253 G_CALLBACK(mouse_button_menu_cb), NULL);
254
255 gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
256 gtk_combo_box_set_active(GTK_COMBO_BOX(opt),
257 gstroke_get_mouse_button() - 2);
258 #else
259 /* Mouse button drop-down menu */
260 menu = gtk_menu_new();
261 opt = gtk_option_menu_new();
262
263 item = gtk_menu_item_new_with_label(_("Middle mouse button"));
264 g_signal_connect(G_OBJECT(item), "activate",
265 G_CALLBACK(mouse_button_menu_cb), opt);
266 gtk_menu_append(menu, item);
267
268 item = gtk_menu_item_new_with_label(_("Right mouse button"));
269 g_signal_connect(G_OBJECT(item), "activate",
270 G_CALLBACK(mouse_button_menu_cb), opt);
271 gtk_menu_append(menu, item);
272
273 gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
274 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
275 gtk_option_menu_set_history(GTK_OPTION_MENU(opt),
276 gstroke_get_mouse_button() - 2);
277 #endif
278 #endif
279
280 /* "Visual gesture display" checkbox */
281 toggle = gtk_check_button_new_with_mnemonic(_("_Visual gesture display"));
282 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
283 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
284 purple_prefs_get_bool("/plugins/gtk/X11/gestures/visual"));
285 g_signal_connect(G_OBJECT(toggle), "toggled",
286 G_CALLBACK(toggle_draw_cb), NULL);
287
288 gtk_widget_show_all(ret);
289
290 return ret;
291 }
292
293 static PidginPluginUiInfo ui_info =
294 {
295 get_config_frame,
296 0, /* page_num (Reserved) */
297
298 /* padding */
299 NULL,
300 NULL,
301 NULL,
302 NULL
303 };
304
305 static PurplePluginInfo info =
306 {
307 PURPLE_PLUGIN_MAGIC,
308 PURPLE_MAJOR_VERSION,
309 PURPLE_MINOR_VERSION,
310 PURPLE_PLUGIN_STANDARD, /**< type */
311 PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
312 0, /**< flags */
313 NULL, /**< dependencies */
314 PURPLE_PRIORITY_DEFAULT, /**< priority */
315
316 GESTURES_PLUGIN_ID, /**< id */
317 N_("Mouse Gestures"), /**< name */
318 DISPLAY_VERSION, /**< version */
319 /** summary */
320 N_("Provides support for mouse gestures"),
321 /** description */
322 N_("Allows support for mouse gestures in conversation windows. "
323 "Drag the middle mouse button to perform certain actions:\n"
324 " • Drag down and then to the right to close a conversation.\n"
325 " • Drag up and then to the left to switch to the previous "
326 "conversation.\n"
327 " • Drag up and then to the right to switch to the next "
328 "conversation."),
329 "Christian Hammond <chipx86@gnupdate.org>", /**< author */
330 PURPLE_WEBSITE, /**< homepage */
331
332 plugin_load, /**< load */
333 plugin_unload, /**< unload */
334 NULL, /**< destroy */
335
336 &ui_info, /**< ui_info */
337 NULL, /**< extra_info */
338 NULL,
339 NULL,
340
341 /* padding */
342 NULL,
343 NULL,
344 NULL,
345 NULL
346 };
347
348 static void
init_plugin(PurplePlugin * plugin)349 init_plugin(PurplePlugin *plugin)
350 {
351 purple_prefs_add_none("/plugins/gtk");
352 purple_prefs_add_none("/plugins/gtk/X11");
353 purple_prefs_add_none("/plugins/gtk/X11/gestures");
354 purple_prefs_add_bool("/plugins/gtk/X11/gestures/visual", FALSE);
355
356 purple_prefs_connect_callback(plugin, "/plugins/gtk/X11/gestures/visual",
357 visual_pref_cb, NULL);
358 }
359
360 PURPLE_INIT_PLUGIN(gestures, init_plugin, info)
361