| |
1 /* |
| |
2 * Mouse gestures plugin for Gaim |
| |
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., 59 Temple Place - Suite 330, Boston, MA |
| |
19 * 02111-1307, USA. |
| |
20 */ |
| |
21 #include "internal.h" |
| |
22 #include "gtkgaim.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 |
| |
38 stroke_close(GtkWidget *widget, void *data) |
| |
39 { |
| |
40 GaimConversation *conv; |
| |
41 GaimGtkConversation *gtkconv; |
| |
42 |
| |
43 conv = (GaimConversation *)data; |
| |
44 |
| |
45 /* Double-check */ |
| |
46 if (!GAIM_IS_GTK_CONVERSATION(conv)) |
| |
47 return; |
| |
48 |
| |
49 gtkconv = GAIM_GTK_CONVERSATION(conv); |
| |
50 |
| |
51 gstroke_cleanup(gtkconv->imhtml); |
| |
52 gaim_conversation_destroy(conv); |
| |
53 } |
| |
54 |
| |
55 static void |
| |
56 switch_page(GaimGtkWindow *win, GtkDirectionType dir) |
| |
57 { |
| |
58 int count, current; |
| |
59 |
| |
60 #if GTK_CHECK_VERSION(2,2,0) |
| |
61 count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook)); |
| |
62 #else |
| |
63 count = g_list_length(GTK_NOTEBOOK(win->notebook)->children); |
| |
64 #endif |
| |
65 current = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook)); |
| |
66 |
| |
67 if (dir == GTK_DIR_LEFT) |
| |
68 { |
| |
69 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), current - 1); |
| |
70 } |
| |
71 else if (dir == GTK_DIR_RIGHT) |
| |
72 { |
| |
73 if (current == count - 1) |
| |
74 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); |
| |
75 else |
| |
76 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), current + 1); |
| |
77 } |
| |
78 } |
| |
79 |
| |
80 static void |
| |
81 stroke_prev_tab(GtkWidget *widget, void *data) |
| |
82 { |
| |
83 GaimConversation *conv; |
| |
84 GaimGtkConversation *gtkconv; |
| |
85 GaimGtkWindow *win; |
| |
86 |
| |
87 conv = (GaimConversation *)data; |
| |
88 gtkconv = GAIM_GTK_CONVERSATION(conv); |
| |
89 win = gtkconv->win; |
| |
90 |
| |
91 switch_page(win, GTK_DIR_LEFT); |
| |
92 } |
| |
93 |
| |
94 static void |
| |
95 stroke_next_tab(GtkWidget *widget, void *data) |
| |
96 { |
| |
97 GaimConversation *conv; |
| |
98 GaimGtkWindow *win; |
| |
99 |
| |
100 conv = (GaimConversation *)data; |
| |
101 win = GAIM_GTK_CONVERSATION(conv)->win; |
| |
102 |
| |
103 switch_page(win, GTK_DIR_RIGHT); |
| |
104 } |
| |
105 |
| |
106 static void |
| |
107 stroke_new_win(GtkWidget *widget, void *data) |
| |
108 { |
| |
109 GaimGtkWindow *new_win, *old_win; |
| |
110 GaimConversation *conv; |
| |
111 |
| |
112 conv = (GaimConversation *)data; |
| |
113 old_win = GAIM_GTK_CONVERSATION(conv)->win; |
| |
114 |
| |
115 if (gaim_gtk_conv_window_get_gtkconv_count(old_win) <= 1) |
| |
116 return; |
| |
117 |
| |
118 new_win = gaim_gtk_conv_window_new(); |
| |
119 |
| |
120 gaim_gtk_conv_window_remove_gtkconv(old_win, GAIM_GTK_CONVERSATION(conv)); |
| |
121 gaim_gtk_conv_window_add_gtkconv(new_win, GAIM_GTK_CONVERSATION(conv)); |
| |
122 |
| |
123 gaim_gtk_conv_window_show(new_win); |
| |
124 } |
| |
125 |
| |
126 static void |
| |
127 attach_signals(GaimConversation *conv) |
| |
128 { |
| |
129 GaimGtkConversation *gtkconv; |
| |
130 |
| |
131 gtkconv = GAIM_GTK_CONVERSATION(conv); |
| |
132 |
| |
133 gstroke_enable(gtkconv->imhtml); |
| |
134 gstroke_signal_connect(gtkconv->imhtml, "14789", stroke_close, conv); |
| |
135 gstroke_signal_connect(gtkconv->imhtml, "1456", stroke_close, conv); |
| |
136 gstroke_signal_connect(gtkconv->imhtml, "1489", stroke_close, conv); |
| |
137 gstroke_signal_connect(gtkconv->imhtml, "74123", stroke_next_tab, conv); |
| |
138 gstroke_signal_connect(gtkconv->imhtml, "7456", stroke_next_tab, conv); |
| |
139 gstroke_signal_connect(gtkconv->imhtml, "96321", stroke_prev_tab, conv); |
| |
140 gstroke_signal_connect(gtkconv->imhtml, "9654", stroke_prev_tab, conv); |
| |
141 gstroke_signal_connect(gtkconv->imhtml, "25852", stroke_new_win, conv); |
| |
142 } |
| |
143 |
| |
144 static void |
| |
145 new_conv_cb(GaimConversation *conv) |
| |
146 { |
| |
147 if (GAIM_IS_GTK_CONVERSATION(conv)) |
| |
148 attach_signals(conv); |
| |
149 } |
| |
150 |
| |
151 #if 0 |
| |
152 static void |
| |
153 mouse_button_menu_cb(GtkMenuItem *item, gpointer data) |
| |
154 { |
| |
155 int button = (int)data; |
| |
156 |
| |
157 gstroke_set_mouse_button(button + 2); |
| |
158 } |
| |
159 #endif |
| |
160 |
| |
161 static void |
| |
162 toggle_draw_cb(GtkToggleButton *toggle, gpointer data) |
| |
163 { |
| |
164 gaim_prefs_set_bool("/plugins/gtk/X11/gestures/visual", |
| |
165 gtk_toggle_button_get_active(toggle)); |
| |
166 } |
| |
167 |
| |
168 static void |
| |
169 visual_pref_cb(const char *name, GaimPrefType type, gconstpointer value, |
| |
170 gpointer data) |
| |
171 { |
| |
172 gstroke_set_draw_strokes((gboolean) GPOINTER_TO_INT(value) ); |
| |
173 } |
| |
174 |
| |
175 static gboolean |
| |
176 plugin_load(GaimPlugin *plugin) |
| |
177 { |
| |
178 GaimConversation *conv; |
| |
179 GList *l; |
| |
180 |
| |
181 for (l = gaim_get_conversations(); l != NULL; l = l->next) { |
| |
182 conv = (GaimConversation *)l->data; |
| |
183 |
| |
184 if (!GAIM_IS_GTK_CONVERSATION(conv)) |
| |
185 continue; |
| |
186 |
| |
187 attach_signals(conv); |
| |
188 } |
| |
189 |
| |
190 gaim_signal_connect(gaim_conversations_get_handle(), |
| |
191 "conversation-created", |
| |
192 plugin, GAIM_CALLBACK(new_conv_cb), NULL); |
| |
193 |
| |
194 return TRUE; |
| |
195 } |
| |
196 |
| |
197 static gboolean |
| |
198 plugin_unload(GaimPlugin *plugin) |
| |
199 { |
| |
200 GaimConversation *conv; |
| |
201 GaimGtkConversation *gtkconv; |
| |
202 GList *l; |
| |
203 |
| |
204 for (l = gaim_get_conversations(); l != NULL; l = l->next) { |
| |
205 conv = (GaimConversation *)l->data; |
| |
206 |
| |
207 if (!GAIM_IS_GTK_CONVERSATION(conv)) |
| |
208 continue; |
| |
209 |
| |
210 gtkconv = GAIM_GTK_CONVERSATION(conv); |
| |
211 |
| |
212 gstroke_cleanup(gtkconv->imhtml); |
| |
213 gstroke_disable(gtkconv->imhtml); |
| |
214 } |
| |
215 |
| |
216 return TRUE; |
| |
217 } |
| |
218 |
| |
219 static GtkWidget * |
| |
220 get_config_frame(GaimPlugin *plugin) |
| |
221 { |
| |
222 GtkWidget *ret; |
| |
223 GtkWidget *vbox; |
| |
224 GtkWidget *toggle; |
| |
225 #if 0 |
| |
226 GtkWidget *opt; |
| |
227 GtkWidget *menu, *item; |
| |
228 #endif |
| |
229 |
| |
230 /* Outside container */ |
| |
231 ret = gtk_vbox_new(FALSE, 18); |
| |
232 gtk_container_set_border_width(GTK_CONTAINER(ret), 12); |
| |
233 |
| |
234 /* Configuration frame */ |
| |
235 vbox = gaim_gtk_make_frame(ret, _("Mouse Gestures Configuration")); |
| |
236 |
| |
237 #if 0 |
| |
238 /* Mouse button drop-down menu */ |
| |
239 menu = gtk_menu_new(); |
| |
240 opt = gtk_option_menu_new(); |
| |
241 |
| |
242 item = gtk_menu_item_new_with_label(_("Middle mouse button")); |
| |
243 g_signal_connect(G_OBJECT(item), "activate", |
| |
244 G_CALLBACK(mouse_button_menu_cb), opt); |
| |
245 gtk_menu_append(menu, item); |
| |
246 |
| |
247 item = gtk_menu_item_new_with_label(_("Right mouse button")); |
| |
248 g_signal_connect(G_OBJECT(item), "activate", |
| |
249 G_CALLBACK(mouse_button_menu_cb), opt); |
| |
250 gtk_menu_append(menu, item); |
| |
251 |
| |
252 gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0); |
| |
253 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); |
| |
254 gtk_option_menu_set_history(GTK_OPTION_MENU(opt), |
| |
255 gstroke_get_mouse_button() - 2); |
| |
256 #endif |
| |
257 |
| |
258 /* "Visual gesture display" checkbox */ |
| |
259 toggle = gtk_check_button_new_with_mnemonic(_("_Visual gesture display")); |
| |
260 gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); |
| |
261 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), |
| |
262 gaim_prefs_get_bool("/plugins/gtk/X11/gestures/visual")); |
| |
263 g_signal_connect(G_OBJECT(toggle), "toggled", |
| |
264 G_CALLBACK(toggle_draw_cb), NULL); |
| |
265 |
| |
266 gtk_widget_show_all(ret); |
| |
267 |
| |
268 return ret; |
| |
269 } |
| |
270 |
| |
271 static GaimGtkPluginUiInfo ui_info = |
| |
272 { |
| |
273 get_config_frame, |
| |
274 0 /* page_num (Reserved) */ |
| |
275 }; |
| |
276 |
| |
277 static GaimPluginInfo info = |
| |
278 { |
| |
279 GAIM_PLUGIN_MAGIC, |
| |
280 GAIM_MAJOR_VERSION, |
| |
281 GAIM_MINOR_VERSION, |
| |
282 GAIM_PLUGIN_STANDARD, /**< type */ |
| |
283 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ |
| |
284 0, /**< flags */ |
| |
285 NULL, /**< dependencies */ |
| |
286 GAIM_PRIORITY_DEFAULT, /**< priority */ |
| |
287 |
| |
288 GESTURES_PLUGIN_ID, /**< id */ |
| |
289 N_("Mouse Gestures"), /**< name */ |
| |
290 VERSION, /**< version */ |
| |
291 /** summary */ |
| |
292 N_("Provides support for mouse gestures"), |
| |
293 /** description */ |
| |
294 N_("Allows support for mouse gestures in conversation windows.\n" |
| |
295 "Drag the middle mouse button to perform certain actions:\n\n" |
| |
296 "Drag down and then to the right to close a conversation.\n" |
| |
297 "Drag up and then to the left to switch to the previous " |
| |
298 "conversation.\n" |
| |
299 "Drag up and then to the right to switch to the next " |
| |
300 "conversation."), |
| |
301 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ |
| |
302 GAIM_WEBSITE, /**< homepage */ |
| |
303 |
| |
304 plugin_load, /**< load */ |
| |
305 plugin_unload, /**< unload */ |
| |
306 NULL, /**< destroy */ |
| |
307 |
| |
308 &ui_info, /**< ui_info */ |
| |
309 NULL, /**< extra_info */ |
| |
310 NULL, |
| |
311 NULL |
| |
312 }; |
| |
313 |
| |
314 static void |
| |
315 init_plugin(GaimPlugin *plugin) |
| |
316 { |
| |
317 gaim_prefs_add_none("/plugins/gtk"); |
| |
318 gaim_prefs_add_none("/plugins/gtk/X11"); |
| |
319 gaim_prefs_add_none("/plugins/gtk/X11/gestures"); |
| |
320 gaim_prefs_add_bool("/plugins/gtk/X11/gestures/visual", FALSE); |
| |
321 |
| |
322 gaim_prefs_connect_callback(plugin, "/plugins/gtk/X11/gestures/visual", |
| |
323 visual_pref_cb, NULL); |
| |
324 } |
| |
325 |
| |
326 GAIM_INIT_PLUGIN(gestures, init_plugin, info) |