Mercurial > pidgin
annotate plugins/gestures/stroke-draw.c @ 6016:1e4a574bb46d
[gaim-migrate @ 6466]
Removed move of the #if 0'ed code from gtkprefs.c. I think Chip or
Nathan or whoever left this here so that they could go back later and
make sure all the old #if 0'ed stuff works correctly with the new prefs,
so to reassure whoever did that, I've been verifying that all these prefs
work as they should.
Made the "use server alias" checkbox instantly affect conversation titles.
Fixed a crash caused by trying to enable buddy icon animation for static
images which happened after toggling the "enable buddy icon animation"
preference to the O-N positiO-N.
All you people need to hop on the bug fix bandwagon. It's happy hour.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Fri, 04 Jul 2003 19:12:06 +0000 |
parents | 711db8ff91dd |
children | ea2d07ad05a9 |
rev | line source |
---|---|
4390 | 1 /* |
2 GNOME stroke implementation | |
3 Copyright (c) 2000, 2001 Dan Nicolaescu | |
4 See the file COPYING for distribution information. | |
5 */ | |
6 | |
7 #include "config.h" | |
8 | |
9 #include <unistd.h> | |
10 #include <stdlib.h> | |
11 #include <stdio.h> | |
12 #include <glib.h> | |
13 #include <gtk/gtk.h> | |
14 | |
15 #include <gdk/gdkx.h> | |
16 #include "gstroke.h" | |
17 #include "gstroke-internal.h" | |
18 | |
19 #include <X11/Xlib.h> | |
20 #include <X11/Xutil.h> | |
21 | |
22 | |
23 static void gstroke_invisible_window_init (GtkWidget *widget); | |
24 /*FIXME: Maybe these should be put in a structure, and not static...*/ | |
4529
f630a793b9d4
[gaim-migrate @ 4807]
Christian Hammond <chipx86@chipx86.com>
parents:
4432
diff
changeset
|
25 static Display * gstroke_disp = NULL; |
4390 | 26 static Window gstroke_window; |
27 static GC gstroke_gc; | |
28 static int mouse_button = 2; | |
29 static gboolean draw_strokes = FALSE; | |
30 | |
31 #define GSTROKE_TIMEOUT_DURATION 10 | |
32 | |
33 #define GSTROKE_SIGNALS "gstroke_signals" | |
34 | |
35 struct gstroke_func_and_data { | |
36 void (*func)(GtkWidget *, void *); | |
37 gpointer data; | |
38 }; | |
39 | |
40 | |
41 /*FIXME: maybe it's better to just make 2 static variables, not a | |
42 structure */ | |
43 struct mouse_position { | |
44 struct s_point last_point; | |
45 gboolean invalid; | |
46 }; | |
47 | |
48 | |
49 static struct mouse_position last_mouse_position; | |
50 static guint timer_id; | |
51 | |
52 static void gstroke_execute (GtkWidget *widget, const gchar *name); | |
53 | |
54 static void | |
55 record_stroke_segment (GtkWidget *widget) | |
56 { | |
57 gint x, y; | |
58 struct gstroke_metrics *metrics; | |
59 | |
60 gtk_widget_get_pointer (widget, &x, &y); | |
61 | |
62 if (last_mouse_position.invalid) | |
63 last_mouse_position.invalid = FALSE; | |
64 else if (gstroke_draw_strokes()) | |
65 { | |
66 #if 1 | |
67 XDrawLine (gstroke_disp, gstroke_window, gstroke_gc, | |
68 last_mouse_position.last_point.x, | |
69 last_mouse_position.last_point.y, | |
70 x, y); | |
71 /* XFlush (gstroke_disp); */ | |
72 #else | |
73 /* FIXME: this does not work. It will only work if we create a | |
74 corresponding GDK window for stroke_window and draw on | |
75 that... */ | |
76 gdk_draw_line (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], | |
77 last_mouse_position.last_point.x, | |
78 last_mouse_position.last_point.y, | |
79 x, | |
80 y); | |
81 #endif | |
82 } | |
83 | |
84 if (last_mouse_position.last_point.x != x | |
85 || last_mouse_position.last_point.y != y) | |
86 { | |
87 last_mouse_position.last_point.x = x; | |
88 last_mouse_position.last_point.y = y; | |
89 metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT(widget), | |
90 GSTROKE_METRICS); | |
91 _gstroke_record (x, y, metrics); | |
92 } | |
93 } | |
94 | |
95 static gint | |
96 gstroke_timeout (gpointer data) | |
97 { | |
98 GtkWidget *widget = GTK_WIDGET (data); | |
99 record_stroke_segment (widget); | |
100 | |
101 return TRUE; | |
102 } | |
103 | |
104 static gint | |
105 process_event (GtkWidget *widget, GdkEvent *event, gpointer data G_GNUC_UNUSED) | |
106 { | |
107 static GtkWidget *original_widget = NULL; | |
5861
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
108 static GdkCursor *cursor = NULL; |
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
109 |
4390 | 110 switch (event->type) { |
111 case GDK_BUTTON_PRESS: | |
112 if (event->button.button != gstroke_get_mouse_button()) | |
5861
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
113 break; |
4390 | 114 |
115 original_widget = widget; /* remeber the widget where | |
116 the stroke started */ | |
117 | |
118 gstroke_invisible_window_init (widget); | |
119 | |
120 record_stroke_segment (widget); | |
121 | |
5861
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
122 if (cursor == NULL) |
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
123 cursor = gdk_cursor_new(GDK_PENCIL); |
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
124 |
4390 | 125 gdk_pointer_grab (widget->window, FALSE, |
5861
711db8ff91dd
[gaim-migrate @ 6292]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
126 GDK_BUTTON_RELEASE_MASK, NULL, cursor, |
4390 | 127 event->button.time); |
128 timer_id = gtk_timeout_add (GSTROKE_TIMEOUT_DURATION, | |
129 gstroke_timeout, widget); | |
130 return TRUE; | |
131 | |
132 case GDK_BUTTON_RELEASE: | |
133 if ((event->button.button != gstroke_get_mouse_button()) | |
4399
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
134 || (original_widget == NULL)) { |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
135 |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
136 /* Nice bug when you hold down one button and press another. */ |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
137 /* We'll just cancel the gesture instead. */ |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
138 last_mouse_position.invalid = TRUE; |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
139 original_widget = NULL; |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
140 |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
141 if (timer_id > 0) |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
142 gtk_timeout_remove (timer_id); |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
143 |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
144 gdk_pointer_ungrab (event->button.time); |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
145 timer_id = 0; |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
146 |
4529
f630a793b9d4
[gaim-migrate @ 4807]
Christian Hammond <chipx86@chipx86.com>
parents:
4432
diff
changeset
|
147 if (gstroke_draw_strokes() && gstroke_disp != NULL) { |
4399
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
148 /* get rid of the invisible stroke window */ |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
149 XUnmapWindow (gstroke_disp, gstroke_window); |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
150 XFlush (gstroke_disp); |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
151 } |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
152 |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
153 break; |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
154 |
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
155 } |
4390 | 156 |
157 last_mouse_position.invalid = TRUE; | |
158 original_widget = NULL; | |
159 gtk_timeout_remove (timer_id); | |
160 gdk_pointer_ungrab (event->button.time); | |
161 timer_id = 0; | |
162 | |
163 { | |
164 char result[GSTROKE_MAX_SEQUENCE]; | |
165 struct gstroke_metrics *metrics; | |
166 | |
167 metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT (widget), | |
168 GSTROKE_METRICS); | |
169 if (gstroke_draw_strokes()) { | |
170 /* get rid of the invisible stroke window */ | |
171 XUnmapWindow (gstroke_disp, gstroke_window); | |
172 XFlush (gstroke_disp); | |
173 } | |
174 | |
175 _gstroke_canonical (result, metrics); | |
176 gstroke_execute (widget, result); | |
177 return FALSE; | |
178 } | |
179 return TRUE; | |
180 default: | |
181 break; | |
182 } | |
183 | |
184 return FALSE; | |
185 } | |
186 | |
187 void | |
188 gstroke_set_draw_strokes(gboolean draw) | |
189 { | |
190 draw_strokes = draw; | |
191 } | |
192 | |
193 gboolean | |
194 gstroke_draw_strokes(void) | |
195 { | |
196 return draw_strokes; | |
197 } | |
198 | |
199 void | |
200 gstroke_set_mouse_button(gint button) | |
201 { | |
202 mouse_button = button; | |
203 } | |
204 | |
205 int | |
206 gstroke_get_mouse_button(void) | |
207 { | |
208 return mouse_button; | |
209 } | |
210 | |
211 void | |
212 gstroke_enable (GtkWidget *widget) | |
213 { | |
214 struct gstroke_metrics* | |
215 metrics = (struct gstroke_metrics *)g_object_get_data(G_OBJECT(widget), | |
216 GSTROKE_METRICS); | |
217 if (metrics == NULL) | |
218 { | |
219 metrics = (struct gstroke_metrics *)g_malloc (sizeof | |
220 (struct gstroke_metrics)); | |
221 metrics->pointList = NULL; | |
222 metrics->min_x = 10000; | |
223 metrics->min_y = 10000; | |
224 metrics->max_x = 0; | |
225 metrics->max_y = 0; | |
226 metrics->point_count = 0; | |
227 | |
228 g_object_set_data(G_OBJECT(widget), GSTROKE_METRICS, metrics); | |
229 | |
230 g_signal_connect(G_OBJECT(widget), "event", | |
231 G_CALLBACK(process_event), NULL); | |
232 } | |
233 else | |
234 _gstroke_init (metrics); | |
235 | |
236 last_mouse_position.invalid = TRUE; | |
237 } | |
238 | |
239 guint | |
240 gstroke_signal_connect (GtkWidget *widget, | |
241 const gchar *name, | |
242 void (*func)(GtkWidget *widget, void *data), | |
243 gpointer data) | |
244 { | |
245 struct gstroke_func_and_data *func_and_data; | |
246 GHashTable *hash_table = | |
247 (GHashTable*)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); | |
248 | |
249 if (!hash_table) | |
250 { | |
251 hash_table = g_hash_table_new (g_str_hash, g_str_equal); | |
252 g_object_set_data(G_OBJECT(widget), GSTROKE_SIGNALS, | |
253 (gpointer)hash_table); | |
254 } | |
255 func_and_data = g_new (struct gstroke_func_and_data, 1); | |
256 func_and_data->func = func; | |
257 func_and_data->data = data; | |
258 g_hash_table_insert (hash_table, (gpointer)name, (gpointer)func_and_data); | |
259 return TRUE; | |
260 } | |
261 | |
262 static void | |
263 gstroke_execute (GtkWidget *widget, const gchar *name) | |
264 { | |
265 | |
266 GHashTable *hash_table = | |
267 (GHashTable*)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); | |
268 | |
269 #if 0 | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
4529
diff
changeset
|
270 gaim_debug(GAIM_DEBUG_MISC, "gestures", "gstroke %s\n", name); |
4390 | 271 #endif |
272 | |
273 if (hash_table) | |
274 { | |
275 struct gstroke_func_and_data *fd = | |
276 (struct gstroke_func_and_data*)g_hash_table_lookup (hash_table, name); | |
277 if (fd) | |
278 (*fd->func)(widget, fd->data); | |
279 } | |
280 } | |
281 | |
282 void | |
283 gstroke_cleanup (GtkWidget *widget) | |
284 { | |
285 struct gstroke_metrics *metrics; | |
286 GHashTable *hash_table = | |
287 (GHashTable*)g_object_get_data(G_OBJECT(widget), GSTROKE_SIGNALS); | |
288 if (hash_table) | |
289 /* FIXME: does this delete the elements too? */ | |
290 g_hash_table_destroy (hash_table); | |
291 | |
292 g_object_steal_data(G_OBJECT(widget), GSTROKE_SIGNALS); | |
293 | |
294 metrics = (struct gstroke_metrics*)g_object_get_data(G_OBJECT(widget), | |
295 GSTROKE_METRICS); | |
296 if (metrics) | |
297 g_free (metrics); | |
298 g_object_steal_data(G_OBJECT(widget), GSTROKE_METRICS); | |
299 } | |
300 | |
301 | |
302 /* This function should be written using Gtk+ primitives*/ | |
303 static void | |
304 gstroke_invisible_window_init (GtkWidget *widget) | |
305 { | |
306 XSetWindowAttributes w_attr; | |
307 XWindowAttributes orig_w_attr; | |
308 unsigned long mask, col_border, col_background; | |
309 unsigned int border_width; | |
310 XSizeHints hints; | |
311 Display *disp = GDK_WINDOW_XDISPLAY(widget->window); | |
312 Window wind = GDK_WINDOW_XWINDOW (widget->window); | |
313 int screen = DefaultScreen (disp); | |
314 | |
315 if (!gstroke_draw_strokes()) | |
316 return; | |
317 | |
318 gstroke_disp = disp; | |
319 | |
320 /* X server should save what's underneath */ | |
321 XGetWindowAttributes (gstroke_disp, wind, &orig_w_attr); | |
322 hints.x = orig_w_attr.x; | |
323 hints.y = orig_w_attr.y; | |
324 hints.width = orig_w_attr.width; | |
325 hints.height = orig_w_attr.height; | |
326 mask = CWSaveUnder; | |
327 w_attr.save_under = True; | |
328 | |
329 /* inhibit all the decorations */ | |
330 mask |= CWOverrideRedirect; | |
331 w_attr.override_redirect = True; | |
332 | |
333 /* Don't set a background, transparent window */ | |
334 mask |= CWBackPixmap; | |
335 w_attr.background_pixmap = None; | |
336 | |
337 /* Default input window look */ | |
338 col_background = WhitePixel (gstroke_disp, screen); | |
339 | |
340 /* no border for the window */ | |
4399
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
341 #if 0 |
4390 | 342 border_width = 5; |
4399
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
343 #endif |
4390 | 344 border_width = 0; |
4399
ce8d35b435de
[gaim-migrate @ 4668]
Christian Hammond <chipx86@chipx86.com>
parents:
4390
diff
changeset
|
345 |
4390 | 346 col_border = BlackPixel (gstroke_disp, screen); |
347 | |
348 gstroke_window = XCreateSimpleWindow (gstroke_disp, wind, | |
349 0, 0, | |
350 hints.width - 2 * border_width, | |
351 hints.height - 2 * border_width, | |
352 border_width, | |
353 col_border, col_background); | |
354 | |
355 gstroke_gc = XCreateGC (gstroke_disp, gstroke_window, 0, NULL); | |
356 | |
357 XSetFunction (gstroke_disp, gstroke_gc, GXinvert); | |
358 | |
359 XChangeWindowAttributes (gstroke_disp, gstroke_window, mask, &w_attr); | |
360 | |
361 XSetLineAttributes (gstroke_disp, gstroke_gc, 2, LineSolid, | |
362 CapButt, JoinMiter); | |
363 XMapRaised (gstroke_disp, gstroke_window); | |
364 | |
365 #if 0 | |
366 /*FIXME: is this call really needed? If yes, does it need the real | |
367 argc and argv? */ | |
368 hints.flags = PPosition | PSize; | |
369 XSetStandardProperties (gstroke_disp, gstroke_window, "gstroke_test", NULL, | |
370 (Pixmap)NULL, NULL, 0, &hints); | |
371 | |
372 | |
373 /* Receive the close window client message */ | |
374 { | |
375 /* FIXME: is this really needed? If yes, something should be done | |
376 with wmdelete...*/ | |
377 Atom wmdelete = XInternAtom (gstroke_disp, "WM_DELETE_WINDOW", | |
378 False); | |
379 XSetWMProtocols (gstroke_disp, gstroke_window, &wmdelete, True); | |
380 } | |
381 #endif | |
382 } |