1 /*
2 * (SLIK) SimpLIstic sKin functions
3 * (C) 2005 John Ellis
4 *
5 * Author: John Ellis
6 *
7 * This software is released under the GNU General Public License (GNU GPL).
8 * Please read the included file COPYING for more information.
9 * This software comes with no warranty of any kind, use at your own risk!
10 */
11
12 #include "ui2_includes.h"
13 #include "ui2_typedefs.h"
14 #include "ui2_display.h"
15
16 #include "ui2_main.h"
17 #include "ui2_skin.h"
18 #include "ui2_tooltip.h"
19 #include "ui2_util.h"
20 #include "ui2_widget.h"
21 #include "ui_pixbuf_ops.h"
22
23 #include <gdk/gdkkeysyms.h> /* for key values */
24
25 #include <math.h>
26
27
28 /*
29 *-----------------------------------------------------------------------------
30 * Screen refreshing
31 *-----------------------------------------------------------------------------
32 */
33
34 /* ok, so the freeze is ugly, but does help when first loading a skin */
35
ui_display_render_freeze(UIData * ui)36 static void ui_display_render_freeze(UIData *ui)
37 {
38 ui->frozen = TRUE;
39 }
40
ui_display_render_thaw(UIData * ui)41 static void ui_display_render_thaw(UIData *ui)
42 {
43 ui->frozen = FALSE;
44 }
45
ui_display_render_area(UIData * ui,gint x,gint y,gint w,gint h,WidgetData * wd)46 void ui_display_render_area(UIData *ui, gint x, gint y, gint w, gint h, WidgetData *wd)
47 {
48 GdkPixbuf *pixbuf;
49 GdkPixmap *pixmap;
50
51 if (ui->frozen) return;
52 if (w < 1 || h < 1) return;
53
54 pixbuf = skin_get_pixbuf(ui->skin);
55 pixmap = skin_get_buffer(ui->skin);
56
57 if (!pixbuf || !pixmap || !ui->display->window) return;
58
59 if (wd && wd == ui->focus_widget && (slik_focus_enable || ui->focus_enable) &&
60 GTK_WIDGET_HAS_FOCUS(ui->display))
61 {
62 gint wx, wy, ww, wh;
63 if (!ui_widget_focus_draw(ui, wd, x, y, w, h) &&
64 ui_widget_get_geometry(wd, &wx, &wy, &ww, &wh))
65 {
66 ui_display_draw_focus(ui, pixbuf, wx, wy, ww, wh, x, y, w, h, NULL);
67 }
68 }
69
70 if (debug_mode) printf("render: %d, %d (%d x %d)\n", x, y, w, h);
71
72 gdk_draw_pixbuf(pixmap, ui->display->style->fg_gc[GTK_WIDGET_STATE(ui->display)],
73 pixbuf,
74 x, y, x, y, w, h,
75 GDK_RGB_DITHER_NONE, 1, 1); /* FIXME: no dithering */
76
77 gdk_draw_drawable(ui->display->window, ui->display->style->fg_gc[GTK_WIDGET_STATE(ui->display)],
78 pixmap, x, y, x, y, w, h);
79 }
80
ui_display_redraw_area(UIData * ui,gint x,gint y,gint w,gint h,gint update)81 void ui_display_redraw_area(UIData *ui, gint x, gint y, gint w, gint h, gint update)
82 {
83 GList *work;
84
85 pixbuf_copy_area(ui->skin->overlay, x, y,
86 ui->skin->pixbuf, x, y, w, h, FALSE);
87 ui_display_render_freeze(ui);
88
89 work = ui->skin->widget_list;
90 while(work)
91 {
92 WidgetData *wd = work->data;
93 if (ui_widget_contacts_area(wd, x, y, w, h))
94 {
95 ui_widget_draw(ui, wd, update, TRUE);
96 }
97 work = work->next;
98 }
99
100 ui_display_render_thaw(ui);
101 ui_display_render_area(ui, x, y, w, h, ui->focus_widget);
102 }
103
ui_display_draw_focus(UIData * ui,GdkPixbuf * pixbuf,gint x,gint y,gint w,gint h,gint clip_x,gint clip_y,gint clip_w,gint clip_h,GdkPixbuf * clip_pb)104 void ui_display_draw_focus(UIData *ui, GdkPixbuf *pixbuf, gint x, gint y, gint w, gint h,
105 gint clip_x, gint clip_y, gint clip_w, gint clip_h, GdkPixbuf *clip_pb)
106 {
107 gint rx, ry, rw, rh;
108 SkinData *skin;
109
110 if (!util_clip_region(x, y, w, h,
111 clip_x, clip_y, clip_w, clip_h,
112 &rx, &ry, &rw, &rh)) return;
113
114 skin = ui->skin;
115
116 if (skin->focus_overlay)
117 {
118 if (skin->focus_has_border)
119 {
120 util_pixbuf_copy_border_clipped(skin->focus_overlay,
121 skin->focus_border_left, skin->focus_border_right,
122 skin->focus_border_top, skin->focus_border_bottom,
123 pixbuf, x, y, w, h,
124 clip_x, clip_y, clip_w, clip_h,
125 skin->focus_box_alpha);
126 }
127 else
128 {
129 gint fx, fy, fw, fh;
130 gint bx, by, bw, bh;
131
132 fw = gdk_pixbuf_get_width(skin->focus_overlay);
133 fh = gdk_pixbuf_get_height(skin->focus_overlay);
134
135 fx = (skin->focus_anchor_right) ? MAX((x + w - fw), 0) : x;
136 fy = (skin->focus_anchor_bottom) ? MAX((y + h - fh), 0) : y;
137
138 if (util_clip_region(rx, ry, rw, rh, fx, fy, fw, fh,
139 &bx, &by, &bw, &bh))
140 {
141 pixbuf_copy_area_alpha(skin->focus_overlay, 0, 0,
142 pixbuf, bx, by, bw, bh, skin->focus_box_alpha);
143 }
144 }
145 }
146 else
147 {
148 guint8 r, g, b, a;
149
150 r = skin->focus_box_r;
151 g = skin->focus_box_g;
152 b = skin->focus_box_b;
153 a = skin->focus_box_alpha;
154
155 if (skin->focus_box_filled)
156 {
157 /* filled */
158 pixbuf_draw_rect_fill(pixbuf, rx, ry, rw, rh, r, g, b, a);
159 }
160 else
161 {
162 gint bx, by, bw, bh;
163 if (util_clip_region(rx, ry, rw, rh, x, y, w, 2,
164 &bx, &by, &bw, &bh))
165 {
166 pixbuf_draw_rect_fill(pixbuf, bx, by, bw, bh, r, g, b, a);
167 }
168 if (util_clip_region(rx, ry, rw, rh, x, y + h - 2, w, 2,
169 &bx, &by, &bw, &bh))
170 {
171 pixbuf_draw_rect_fill(pixbuf, bx, by, bw, bh, r, g, b, a);
172 }
173 if (util_clip_region(rx, ry, rw, rh, x, y + 2, 2, h - 4,
174 &bx, &by, &bw, &bh))
175 {
176 pixbuf_draw_rect_fill(pixbuf, bx, by, bw, bh, r, g, b, a);
177 }
178 if (util_clip_region(rx, ry, rw, rh, x + w - 2, y + 2, 2, h - 4,
179 &bx, &by, &bw, &bh))
180 {
181 pixbuf_draw_rect_fill(pixbuf, bx, by, bw, bh, r, g, b, a);
182 }
183 }
184 }
185 }
186
187 /*
188 *-----------------------------------------------------------------------------
189 * misc
190 *-----------------------------------------------------------------------------
191 */
192
ui_display_sync_shape(UIData * ui)193 void ui_display_sync_shape(UIData *ui)
194 {
195 if (!ui->skin) return;
196
197 if (ui->window)
198 {
199 if (slik_allow_shapes)
200 {
201 gtk_widget_shape_combine_mask(ui->window, ui->skin->mask_buffer, 0, 0);
202 }
203 gtk_widget_set_size_request(ui->display, ui->skin->width, ui->skin->height);
204 gtk_window_resize(GTK_WINDOW(ui->window), ui->skin->width, ui->skin->height);
205
206 /* wonder why this is here? Try removing it and changing skin to a new size */
207 gdk_window_resize(ui->display->window, ui->skin->width, ui->skin->height);
208 gdk_window_resize(ui->window->window, ui->skin->width, ui->skin->height);
209 }
210 else
211 {
212 if (slik_allow_shapes)
213 {
214 gtk_widget_shape_combine_mask(ui->display, ui->skin->mask_buffer, 0, 0);
215 }
216 gtk_widget_set_size_request(ui->display, ui->skin->width, ui->skin->height);
217 }
218 }
219
ui_display_draw_all(UIData * ui,gint update,gint force)220 void ui_display_draw_all(UIData *ui, gint update, gint force)
221 {
222 GList *work;
223
224 if (!ui->skin) return;
225
226 work = ui->skin->widget_list;
227 while(work)
228 {
229 ui_widget_draw(ui, work->data, update, force);
230 work = work->next;
231 }
232 }
233
ui_display_sync(UIData * ui,gint update)234 void ui_display_sync(UIData *ui, gint update)
235 {
236 if (!ui->skin) return;
237
238 ui_display_render_freeze(ui);
239 ui_display_draw_all(ui, update, TRUE);
240 ui_display_render_thaw(ui);
241
242 /* do it all at once */
243 ui_display_render_area(ui, 0, 0, ui->skin->width, ui->skin->height, ui->focus_widget);
244 }
245
ui_display_sync_all(UIData * ui)246 void ui_display_sync_all(UIData *ui)
247 {
248 if (!ui->skin) return;
249
250 skin_check_bounds(ui->skin);
251
252 skin_sync_buffer(ui->skin, ui);
253 ui_display_sync_shape(ui);
254
255 ui_display_sync(ui, TRUE);
256 }
257
ui_display_expose(GtkWidget * widget,GdkEventExpose * event,gpointer data)258 static void ui_display_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
259 {
260 UIData *ui = data;
261 GdkPixmap *pixmap;
262
263 pixmap = skin_get_buffer(ui->skin);
264 if (!pixmap) return;
265
266 gdk_draw_drawable(ui->display->window, ui->display->style->fg_gc[GTK_WIDGET_STATE(ui->display)],
267 pixmap,
268 (gint)event->area.x, (gint)event->area.y,
269 (gint)event->area.x, (gint)event->area.y,
270 (gint)event->area.width, (gint)event->area.height);
271 }
272
ui_display_move_idle_cb(gpointer data)273 static gint ui_display_move_idle_cb(gpointer data)
274 {
275 UIData *ui = data;
276
277 skin_sync_back(ui->skin, ui);
278 ui_display_sync(ui, FALSE);
279
280 ui->root_win_idle = -1;
281
282 return FALSE;
283 }
284
ui_display_move(GtkWidget * widget,GdkEventConfigure * event,gpointer data)285 static void ui_display_move(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
286 {
287 UIData *ui = data;
288
289 if (debug_mode) printf("move event\n");
290
291 if (ui->root_win_idle == -1 &&
292 (ui->skin->transparent || slik_transparency_force))
293 {
294 ui->root_win_idle = g_idle_add(ui_display_move_idle_cb, ui);
295 }
296 }
297
298 /*
299 *-----------------------------------------------------------------------------
300 * Focus (keyboard stuff)
301 *-----------------------------------------------------------------------------
302 */
303
304 typedef enum {
305 UI_FOCUS_NONE = 0,
306 UI_FOCUS_LEFT,
307 UI_FOCUS_UP,
308 UI_FOCUS_RIGHT,
309 UI_FOCUS_DOWN,
310 UI_FOCUS_TAB_FORWARD,
311 UI_FOCUS_TAB_BACKWARD
312 } UIMoveFocusType;
313
314 #define DIST(x, y) (sqrt(x * x + y * y))
315
ui_display_focus_nearest(UIData * ui,gint x,gint y)316 static WidgetData *ui_display_focus_nearest(UIData *ui, gint x, gint y)
317 {
318 WidgetData *wd = NULL;
319 gint dx, dy;
320 GList *work;
321
322 if (!slik_focus_enable && !ui->focus_enable) return NULL;
323
324 dx = ui->skin->width;
325 dy = ui->skin->height;
326
327 work = ui->skin->widget_list;
328 while (work)
329 {
330 WidgetData *tmp;
331 gint tx, ty, tw, th;
332
333 tmp = work->data;
334 work = work->next;
335 if (ui_widget_can_focus(tmp) &&
336 ui_widget_get_geometry(tmp, &tx, &ty, &tw, &th))
337 {
338 tx = tx + (tw / 2);
339 ty = ty + (th / 2);
340 if (DIST((x - tx), (y - ty)) < DIST(dx, dy))
341 {
342 dx = abs(x - tx);
343 dy = abs(y - ty);
344 wd = tmp;
345 }
346 }
347 }
348
349 return wd;
350 }
351
ui_display_focus_nearest_clipped(UIData * ui,WidgetData * current,gint clip_x,gint clip_y,gint clip_w,gint clip_h)352 static WidgetData *ui_display_focus_nearest_clipped(UIData *ui, WidgetData *current,
353 gint clip_x, gint clip_y, gint clip_w, gint clip_h)
354 {
355 WidgetData *wd = NULL;
356 gint cx, cy, cw, ch;
357
358 if (current && ui_widget_get_geometry(current, &cx, &cy, &cw, &ch))
359 {
360 gint dx, dy;
361 gint px, py;
362 GList *work;
363
364 px = cx + (cw / 2);
365 py = cy + (ch / 2);
366
367 dx = ui->skin->width;
368 dy = ui->skin->height;
369
370 work = ui->skin->widget_list;
371 while (work)
372 {
373 WidgetData *tmp;
374 gint x, y, w, h;
375
376 tmp = work->data;
377 work = work->next;
378 if (current != tmp && ui_widget_can_focus(tmp) &&
379 ui_widget_get_geometry(tmp, &x, &y, &w, &h))
380 {
381 gint dmy;
382 if (util_clip_region(clip_x, clip_y, clip_w, clip_h,
383 x, y, w, h, &dmy, &dmy, &dmy, &dmy))
384 {
385 gint tx, ty;
386 gint ax, ay;
387
388 tx = x + (w / 2);
389 ty = y + (h / 2);
390
391 ax = abs(tx - px);
392 ay = abs(ty - py);
393
394 if (DIST(ax, ay) < DIST(dx, dy))
395 {
396 dy = ay;
397 dx = ax;
398 wd = tmp;
399 }
400 }
401 }
402 }
403 }
404
405 return wd;
406 }
407
ui_display_focus_find(UIData * ui,WidgetData * current,gint x_dir,gint y_dir)408 static WidgetData *ui_display_focus_find(UIData *ui, WidgetData *current, gint x_dir, gint y_dir)
409 {
410 WidgetData *wd = NULL;
411 gint cx, cy, cw, ch;
412
413 if (!slik_focus_enable && !ui->focus_enable) return NULL;
414
415 if (x_dir == 0 && y_dir == 0) return current;
416
417 if (current && ui_widget_get_geometry(current, &cx, &cy, &cw, &ch))
418 {
419 /* create a region that we are (trying to) move into */
420 if (x_dir < 0)
421 {
422 cw = cx - 1;
423 cx = 0;
424 }
425 else if (x_dir > 0)
426 {
427 cx += cw + 1;
428 cw = ui->skin->width - cx;
429 }
430 if (y_dir < 0)
431 {
432 ch = cy - 1;
433 cy = 0;
434 }
435 else if (y_dir > 0)
436 {
437 cy += ch + 1;
438 ch = ui->skin->height - cy;
439 }
440
441 wd = ui_display_focus_nearest_clipped(ui, current, cx, cy, cw, ch);
442
443 if (!wd)
444 {
445 /* try it all again, this time with a broader range */
446 if (x_dir != 0)
447 {
448 cy = 0;
449 ch = ui->skin->height;
450 }
451 if (y_dir != 0)
452 {
453 cx = 0;
454 cw = ui->skin->width;
455 }
456
457 wd = ui_display_focus_nearest_clipped(ui, current, cx, cy, cw, ch);
458 }
459
460 }
461 else
462 {
463 wd = ui_display_focus_nearest(ui, 0, 0);
464 }
465
466 if (!wd) wd = current;
467
468 return wd;
469 }
470
ui_display_focus_next(UIData * ui,WidgetData * current,gint forward)471 static WidgetData *ui_display_focus_next(UIData *ui, WidgetData *current, gint forward)
472 {
473 GList *start = NULL;
474 GList *work;
475
476 if (current)
477 {
478 start = g_list_find(ui->skin->widget_list, current);
479 }
480 if (!start)
481 {
482 if (forward)
483 {
484 start = ui->skin->widget_list;
485 }
486 else
487 {
488 start = g_list_last(ui->skin->widget_list);
489 }
490 }
491 if (!start) return current;
492
493 if (forward)
494 {
495 work = start->next;
496 }
497 else
498 {
499 work = start->prev;
500 }
501
502 while (work)
503 {
504 WidgetData *wd;
505
506 wd = work->data;
507 if (current != wd && ui_widget_can_focus(wd)) return wd;
508
509 if (forward)
510 {
511 work = work->next;
512 }
513 else
514 {
515 work = work->prev;
516 }
517 }
518
519 return current;
520 }
521
ui_display_focus_clear(UIData * ui)522 static void ui_display_focus_clear(UIData *ui)
523 {
524 if (ui->focus_widget)
525 {
526 gint x, y, w, h;
527
528 if (ui_widget_get_geometry(ui->focus_widget, &x, &y, &w, &h))
529 {
530 ui->focus_widget = NULL;
531 ui_display_redraw_area(ui, x, y, w, h, FALSE);
532 }
533 else
534 {
535 ui->focus_widget = NULL;
536 }
537 }
538 }
539
540
ui_display_focus_move(UIData * ui,UIMoveFocusType focus)541 static gint ui_display_focus_move(UIData *ui, UIMoveFocusType focus)
542 {
543 WidgetData *new_widget;
544 gint x, y, w, h;
545
546 if (!slik_focus_enable && !ui->focus_enable) return FALSE;
547
548 new_widget = NULL;
549 switch (focus)
550 {
551 case UI_FOCUS_LEFT:
552 new_widget = ui_display_focus_find(ui, ui->focus_widget, -1, 0);
553 break;
554 case UI_FOCUS_UP:
555 new_widget = ui_display_focus_find(ui, ui->focus_widget, 0, -1);
556 break;
557 case UI_FOCUS_RIGHT:
558 new_widget = ui_display_focus_find(ui, ui->focus_widget, 1, 0);
559 break;
560 case UI_FOCUS_DOWN:
561 new_widget = ui_display_focus_find(ui, ui->focus_widget, 0, 1);
562 break;
563 case UI_FOCUS_TAB_FORWARD:
564 new_widget = ui_display_focus_next(ui, ui->focus_widget, TRUE);
565 break;
566 case UI_FOCUS_TAB_BACKWARD:
567 new_widget = ui_display_focus_next(ui, ui->focus_widget, FALSE);
568 break;
569 case UI_FOCUS_NONE:
570 default:
571 break;
572 }
573
574 if (new_widget == ui->focus_widget) return FALSE;
575
576 ui_display_focus_clear(ui);
577
578 ui->focus_widget = new_widget;
579 if (new_widget &&
580 ui_widget_get_geometry(new_widget, &x, &y, &w, &h))
581 {
582 ui_display_render_area(ui, x, y, w, h, new_widget);
583
584 if (ui->tooltips_enable)
585 {
586 const gchar *message;
587
588 message = ui_tooltip_get(ui, new_widget->key, new_widget->type);
589 ui_tooltip_show(ui, new_widget, message);
590 }
591 }
592
593 return TRUE;
594 }
595
ui_display_key_press(GtkWidget * w,GdkEventKey * event,gpointer data)596 static gint ui_display_key_press(GtkWidget *w, GdkEventKey *event, gpointer data)
597 {
598 UIData *ui = data;
599 gint ret = FALSE;
600
601 if (!ui->skin) return FALSE;
602
603 ui_tooltip_show(ui, NULL, NULL);
604
605 /* pop up menus should work _always_, so test before poss. bail out */
606 if (event->keyval == GDK_F10 ||
607 event->keyval == GDK_Menu)
608 {
609 if (ui->click_func)
610 {
611 /* hmm, perhaps the function table needs a menu callback
612 * instead of synthesizing a button 3 press ?
613 */
614 ui->click_func(ui, 3, event->time, ui->click_data);
615 }
616 return TRUE;
617 }
618
619 if (!slik_focus_enable && !ui->focus_enable) return FALSE;
620
621 if (ui->active_widget) return FALSE;
622
623 if (ui->focus_widget &&
624 ui_widget_focus_key_event(ui, ui->focus_widget, event))
625 {
626 ret = TRUE;
627 }
628 else
629 {
630 switch (event->keyval)
631 {
632 case GDK_Left: case GDK_KP_Left:
633 ret = ui_display_focus_move(ui, UI_FOCUS_LEFT);
634 break;
635 case GDK_Right: case GDK_KP_Right:
636 ret = ui_display_focus_move(ui, UI_FOCUS_RIGHT);
637 break;
638 case GDK_Up: case GDK_KP_Up:
639 ret = ui_display_focus_move(ui, UI_FOCUS_UP);
640 break;
641 case GDK_Down: case GDK_KP_Down:
642 ret = ui_display_focus_move(ui, UI_FOCUS_DOWN);
643 break;
644 case GDK_ISO_Left_Tab:
645 ret = ui_display_focus_move(ui, UI_FOCUS_TAB_BACKWARD);
646 break;
647 case GDK_Tab:
648 ret = ui_display_focus_move(ui, UI_FOCUS_TAB_FORWARD);
649 break;
650 default:
651 break;
652 }
653 }
654
655 #if 0
656 if (ret) gtk_signal_emit_stop_by_name(GTK_OBJECT(w), "key_press_event");
657 #endif
658
659 return ret;
660 }
661
ui_display_scrolled(GtkWidget * widget,GdkEventScroll * event,gpointer data)662 static gint ui_display_scrolled(GtkWidget *widget, GdkEventScroll *event, gpointer data)
663 {
664 UIData *ui = data;
665 gint button = -1;
666
667 if (event->direction == GDK_SCROLL_UP)
668 {
669 button = 4;
670 }
671 else if (event->direction == GDK_SCROLL_DOWN)
672 {
673 button = 5;
674 }
675
676 if (ui->click_func && button > 0)
677 {
678 ui->click_func(ui, button, event->time, ui->click_data);
679 }
680
681 return TRUE;
682 }
683
ui_display_focus_in(GtkWidget * widget,GdkEventFocus * event,gpointer data)684 static gint ui_display_focus_in(GtkWidget *widget, GdkEventFocus *event, gpointer data)
685 {
686 UIData *ui = data;
687
688 GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
689
690 if (!ui->skin || (!slik_focus_enable && !ui->focus_enable)) return FALSE;
691
692 if (!ui->focus_widget) ui->focus_widget = ui_display_focus_next(ui, NULL, TRUE);
693 if (ui->focus_widget)
694 {
695 gint x, y, w, h;
696
697 if (ui_widget_get_geometry(ui->focus_widget, &x, &y, &w, &h))
698 {
699 ui_display_render_area(ui, x, y, w, h, ui->focus_widget);
700 }
701 }
702
703 return FALSE;
704 }
705
ui_display_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer data)706 static gint ui_display_focus_out(GtkWidget *widget, GdkEventFocus *event, gpointer data)
707 {
708 UIData *ui = data;
709
710 GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
711
712 ui_tooltip_show(ui, NULL, NULL);
713
714 if (!ui->skin || (!slik_focus_enable && !ui->focus_enable)) return FALSE;
715
716 if (ui->focus_widget)
717 {
718 gint x, y, w, h;
719
720 if (ui_widget_get_geometry(ui->focus_widget, &x, &y, &w, &h))
721 {
722 ui_display_redraw_area(ui, x, y, w, h, FALSE);
723 }
724 }
725
726 return FALSE;
727 }
728
729 /*
730 *-----------------------------------------------------------------------------
731 * Button motion / press handling
732 *-----------------------------------------------------------------------------
733 */
734
ui_display_motion(GtkWidget * w,GdkEventMotion * event,gpointer data)735 static gint ui_display_motion(GtkWidget *w, GdkEventMotion *event, gpointer data)
736 {
737 UIData *ui = data;
738 gint x = (gint)event->x;
739 gint y = (gint)event->y;
740 GList *work;
741 gint tip_updated = FALSE;
742
743 if (debug_skin) printf("motion:%d x %d\n", x, y);
744
745 if (!ui->skin) return FALSE;
746
747 if (ui->active_widget)
748 {
749 ui_widget_motion(ui, ui->active_widget, x, y);
750 return FALSE;
751 }
752
753 if (ui->in_move)
754 {
755 GdkModifierType modmask;
756 gint px, py;
757
758 if (!ui->window) return FALSE;
759
760 gdk_window_get_pointer (NULL, &px, &py, &modmask);
761 px -= ui->press_x;
762 py -= ui->press_y;
763 if (slik_smart_placement &&
764 !(event->state & GDK_SHIFT_MASK))
765 {
766 gint w = gdk_screen_width();
767 gint h = gdk_screen_height();
768 if (px < 8 && px > -8) px = 0;
769 if (py < 8 && py > -8) py = 0;
770 if (px + ui->skin->width > w - 8 && px + ui->skin->width < w + 8) px = w - ui->skin->width;
771 if (py + ui->skin->height > h - 8 && py + ui->skin->height < h +8) py = h - ui->skin->height;
772 }
773 gdk_window_move(ui->window->window, px, py);
774 return TRUE;
775 }
776
777 work = ui->skin->widget_list;
778 while (work)
779 {
780 WidgetData *wd = work->data;
781 gint wx, wy, ww, wh;
782
783 ui_widget_motion(ui, work->data, x, y);
784
785 if (ui->tooltips_enable &&
786 !tip_updated &&
787 wd->od && wd->od->is_visible && ui_widget_get_geometry(wd, &wx, &wy, &ww, &wh) &&
788 x >= wx && x <= wx+ww && y >= wy && y <= wy+wh)
789 {
790 const gchar *message;
791
792 message = ui_tooltip_get(ui, wd->key, wd->type);
793 if (message)
794 {
795 ui_tooltip_show(ui, wd, message);
796 tip_updated = TRUE;
797 }
798 }
799
800 work = work->next;
801 }
802
803 if (ui->tooltips_enable && !tip_updated) ui_tooltip_show(ui, NULL, NULL);
804
805 return FALSE;
806 }
807
ui_display_pressed(GtkWidget * w,GdkEventButton * event,gpointer data)808 static gint ui_display_pressed(GtkWidget *w, GdkEventButton *event, gpointer data)
809 {
810 UIData *ui = data;
811 GdkModifierType modmask;
812 gint x = (gint)event->x;
813 gint y = (gint)event->y;
814 GList *work;
815
816 if (debug_mode) printf("pressed:%d x %d, %d\n", x, y, event->button);
817
818 if (!ui->skin) return FALSE;
819
820 ui_tooltip_show(ui, NULL, NULL);
821
822 /* edit uis have no window, and we only want button 1 to work on them */
823 if (event->button > 1 && !ui->window) return FALSE;
824
825 if (event->button >= 2)
826 {
827 if (ui->click_func)
828 {
829 ui->click_func(ui, event->button, event->time, ui->click_data);
830 return TRUE;
831 }
832 return FALSE;
833 }
834
835 if (event->type != GDK_BUTTON_PRESS) return FALSE;
836
837 gtk_grab_add(ui->display);
838
839 ui->press_x = x;
840 ui->press_y = y;
841
842 work = ui->skin->widget_list;
843 while (work)
844 {
845 if (ui_widget_press(ui, work->data, x, y))
846 {
847 ui->active_widget = work->data;
848 if (debug_mode) printf("pressed widget: \"%s\" (%d)\n", ui->active_widget->key, ui->active_widget->type);
849
850 if ((slik_focus_enable || ui->focus_enable) &&
851 ui_widget_can_focus(ui->active_widget))
852 {
853 if (ui->focus_widget != ui->active_widget)
854 {
855 gint x, y, w, h;
856 ui_display_focus_clear(ui);
857 ui->focus_widget = ui->active_widget;
858 if (ui_widget_get_geometry(ui->focus_widget, &x, &y, &w, &h))
859 {
860 ui_display_render_area(ui, x, y, w, h, ui->focus_widget);
861 }
862 }
863 if (!GTK_WIDGET_HAS_FOCUS(ui->display))
864 {
865 gtk_widget_grab_focus(ui->display);
866 }
867 }
868
869 return TRUE;
870 }
871 work = work->next;
872 }
873
874 if (ui->allow_move)
875 {
876 ui->in_move = TRUE;
877 gdk_window_get_pointer (NULL, &ui->press_root_x, &ui->press_root_y, &modmask);
878 }
879 ui->in_press = (event->x >= 0 && event->x <= ui->skin->width &&
880 event->y >= 0 && event->y <= ui->skin->height);
881
882 return ui->in_press;
883 }
884
ui_display_released(GtkWidget * w,GdkEventButton * event,gpointer data)885 static gint ui_display_released(GtkWidget *w, GdkEventButton *event, gpointer data)
886 {
887 UIData *ui = data;
888 gint x = (gint)event->x;
889 gint y = (gint)event->y;
890
891 if (debug_mode) printf("released:%d x %d, %d\n", x, y, event->button);
892
893 if (!ui->skin) return FALSE;
894 if (!ui->in_press && !ui->active_widget) return FALSE;
895
896 gtk_grab_remove(ui->display);
897
898 if (ui->active_widget)
899 {
900 if (debug_mode) printf("releasing widget: \"%s\" (%d)\n", ui->active_widget->key, ui->active_widget->type);
901 ui_widget_release(ui, ui->active_widget, x, y);
902 ui->active_widget = NULL;
903 }
904 else
905 {
906 GdkModifierType modmask;
907 gint px;
908 gint py;
909 gdk_window_get_pointer (NULL, &px, &py, &modmask);
910 if (px == ui->press_root_x && py == ui->press_root_y && ui->window)
911 {
912 gdk_window_raise (ui->window->window);
913 }
914 }
915
916 ui->in_press = FALSE;
917 ui->in_move = FALSE;
918
919 return FALSE;
920 }
921
ui_display_leave(GtkWidget * widget,GdkEventCrossing * event,gpointer data)922 static void ui_display_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
923 {
924 UIData *ui = data;
925
926 if (!ui->skin) return;
927
928 if (!ui->active_widget)
929 {
930 GList *work;
931
932 work = ui->skin->widget_list;
933 while(work)
934 {
935 ui_widget_reset(ui, work->data);
936 work = work->next;
937 }
938 }
939 }
940
ui_display_events_init(UIData * ui)941 void ui_display_events_init(UIData *ui)
942 {
943 GTK_WIDGET_SET_FLAGS(ui->display, GTK_CAN_FOCUS);
944
945 gtk_widget_set_events(ui->display, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
946 GDK_POINTER_MOTION_MASK |
947 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
948 g_signal_connect(G_OBJECT(ui->display),"motion_notify_event",
949 G_CALLBACK(ui_display_motion), ui);
950 g_signal_connect(G_OBJECT(ui->display),"button_press_event",
951 G_CALLBACK(ui_display_pressed), ui);
952 g_signal_connect(G_OBJECT(ui->display),"button_release_event",
953 G_CALLBACK(ui_display_released), ui);
954 g_signal_connect(G_OBJECT(ui->display),"leave_notify_event",
955 G_CALLBACK(ui_display_leave), ui);
956
957 g_signal_connect(G_OBJECT(ui->display),"key_press_event",
958 G_CALLBACK(ui_display_key_press), ui);
959 g_signal_connect(G_OBJECT(ui->display),"scroll_event",
960 G_CALLBACK(ui_display_scrolled), ui);
961
962 g_signal_connect(G_OBJECT(ui->display),"focus_in_event",
963 G_CALLBACK(ui_display_focus_in), ui);
964 g_signal_connect(G_OBJECT(ui->display),"focus_out_event",
965 G_CALLBACK(ui_display_focus_out), ui);
966
967 ui->active_widget = NULL;
968 ui->in_press = FALSE;
969 ui->in_move = FALSE;
970
971 /* the expose event */
972 g_signal_connect(GTK_OBJECT(ui->display), "expose_event",
973 G_CALLBACK(ui_display_expose), ui);
974 if (ui->window)
975 {
976 g_signal_connect(GTK_OBJECT(ui->window), "configure_event",
977 G_CALLBACK(ui_display_move), ui);
978 }
979 }
980
981