1 /*
2 * Copyright © 2008 Kristian Høgsberg
3 * Copyright © 2012-2013 Collabora, Ltd.
4 * Copyright © 2013 Jason Ekstrand
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <wayland-util.h>
33 #include <linux/input.h>
34
35 #include "cairo-util.h"
36
37 enum frame_button_flags {
38 FRAME_BUTTON_ALIGN_RIGHT = 0x1,
39 FRAME_BUTTON_DECORATED = 0x2,
40 FRAME_BUTTON_CLICK_DOWN = 0x4,
41 };
42
43 struct frame_button {
44 struct frame *frame;
45 struct wl_list link; /* buttons_list */
46
47 cairo_surface_t *icon;
48 enum frame_button_flags flags;
49 int hover_count;
50 int press_count;
51
52 struct {
53 int x, y;
54 int width, height;
55 } allocation;
56
57 enum frame_status status_effect;
58 };
59
60 struct frame_pointer_button {
61 struct wl_list link;
62 uint32_t button;
63 enum theme_location press_location;
64 struct frame_button *frame_button;
65 };
66
67 struct frame_pointer {
68 struct wl_list link;
69 void *data;
70
71 int x, y;
72
73 struct frame_button *hover_button;
74 struct wl_list down_buttons;
75 };
76
77 struct frame_touch {
78 struct wl_list link;
79 void *data;
80
81 int x, y;
82
83 struct frame_button *button;
84 };
85
86 struct frame {
87 int32_t width, height;
88 char *title;
89 uint32_t flags;
90 struct theme *theme;
91
92 struct {
93 int32_t x, y;
94 int32_t width, height;
95 } interior;
96 int shadow_margin;
97 int opaque_margin;
98 int geometry_dirty;
99
100 uint32_t status;
101
102 struct wl_list buttons;
103 struct wl_list pointers;
104 struct wl_list touches;
105 };
106
107 static struct frame_button *
frame_button_create(struct frame * frame,const char * icon,enum frame_status status_effect,enum frame_button_flags flags)108 frame_button_create(struct frame *frame, const char *icon,
109 enum frame_status status_effect,
110 enum frame_button_flags flags)
111 {
112 struct frame_button *button;
113
114 button = calloc(1, sizeof *button);
115 if (!button)
116 return NULL;
117
118 button->icon = cairo_image_surface_create_from_png(icon);
119 if (!button->icon) {
120 free(button);
121 return NULL;
122 }
123
124 button->frame = frame;
125 button->flags = flags;
126 button->status_effect = status_effect;
127
128 wl_list_insert(frame->buttons.prev, &button->link);
129
130 return button;
131 }
132
133 static void
frame_button_destroy(struct frame_button * button)134 frame_button_destroy(struct frame_button *button)
135 {
136 cairo_surface_destroy(button->icon);
137 free(button);
138 }
139
140 static void
frame_button_enter(struct frame_button * button)141 frame_button_enter(struct frame_button *button)
142 {
143 if (!button->hover_count)
144 button->frame->status |= FRAME_STATUS_REPAINT;
145 button->hover_count++;
146 }
147
148 static void
frame_button_leave(struct frame_button * button,struct frame_pointer * pointer)149 frame_button_leave(struct frame_button *button, struct frame_pointer *pointer)
150 {
151 button->hover_count--;
152 if (!button->hover_count)
153 button->frame->status |= FRAME_STATUS_REPAINT;
154 }
155
156 static void
frame_button_press(struct frame_button * button)157 frame_button_press(struct frame_button *button)
158 {
159 if (!button->press_count)
160 button->frame->status |= FRAME_STATUS_REPAINT;
161 button->press_count++;
162
163 if (button->flags & FRAME_BUTTON_CLICK_DOWN)
164 button->frame->status |= button->status_effect;
165 }
166
167 static void
frame_button_release(struct frame_button * button)168 frame_button_release(struct frame_button *button)
169 {
170 button->press_count--;
171 if (button->press_count)
172 return;
173
174 button->frame->status |= FRAME_STATUS_REPAINT;
175
176 if (!(button->flags & FRAME_BUTTON_CLICK_DOWN))
177 button->frame->status |= button->status_effect;
178 }
179
180 static void
frame_button_cancel(struct frame_button * button)181 frame_button_cancel(struct frame_button *button)
182 {
183 button->press_count--;
184 if (!button->press_count)
185 button->frame->status |= FRAME_STATUS_REPAINT;
186 }
187
188 static void
frame_button_repaint(struct frame_button * button,cairo_t * cr)189 frame_button_repaint(struct frame_button *button, cairo_t *cr)
190 {
191 int x, y;
192
193 if (!button->allocation.width)
194 return;
195 if (!button->allocation.height)
196 return;
197
198 x = button->allocation.x;
199 y = button->allocation.y;
200
201 cairo_save(cr);
202
203 if (button->flags & FRAME_BUTTON_DECORATED) {
204 cairo_set_line_width(cr, 1);
205
206 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
207 cairo_rectangle(cr, x, y, 25, 16);
208
209 cairo_stroke_preserve(cr);
210
211 if (button->press_count) {
212 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
213 } else if (button->hover_count) {
214 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
215 } else {
216 cairo_set_source_rgb(cr, 0.88, 0.88, 0.88);
217 }
218
219 cairo_fill (cr);
220
221 x += 4;
222 }
223
224 cairo_set_source_surface(cr, button->icon, x, y);
225 cairo_paint(cr);
226
227 cairo_restore(cr);
228 }
229
230 static struct frame_pointer *
frame_pointer_get(struct frame * frame,void * data)231 frame_pointer_get(struct frame *frame, void *data)
232 {
233 struct frame_pointer *pointer;
234
235 wl_list_for_each(pointer, &frame->pointers, link)
236 if (pointer->data == data)
237 return pointer;
238
239 pointer = calloc(1, sizeof *pointer);
240 if (!pointer)
241 return NULL;
242
243 pointer->data = data;
244 wl_list_init(&pointer->down_buttons);
245 wl_list_insert(&frame->pointers, &pointer->link);
246
247 return pointer;
248 }
249
250 static void
frame_pointer_destroy(struct frame_pointer * pointer)251 frame_pointer_destroy(struct frame_pointer *pointer)
252 {
253 wl_list_remove(&pointer->link);
254 free(pointer);
255 }
256
257 static struct frame_touch *
frame_touch_get(struct frame * frame,void * data)258 frame_touch_get(struct frame *frame, void *data)
259 {
260 struct frame_touch *touch;
261
262 wl_list_for_each(touch, &frame->touches, link)
263 if (touch->data == data)
264 return touch;
265
266 touch = calloc(1, sizeof *touch);
267 if (!touch)
268 return NULL;
269
270 touch->data = data;
271 wl_list_insert(&frame->touches, &touch->link);
272
273 return touch;
274 }
275
276 static void
frame_touch_destroy(struct frame_touch * touch)277 frame_touch_destroy(struct frame_touch *touch)
278 {
279 wl_list_remove(&touch->link);
280 free(touch);
281 }
282
283 void
frame_destroy(struct frame * frame)284 frame_destroy(struct frame *frame)
285 {
286 struct frame_button *button, *next;
287 struct frame_touch *touch, *next_touch;
288 struct frame_pointer *pointer, *next_pointer;
289
290 wl_list_for_each_safe(button, next, &frame->buttons, link)
291 frame_button_destroy(button);
292
293 wl_list_for_each_safe(touch, next_touch, &frame->touches, link)
294 frame_touch_destroy(touch);
295
296 wl_list_for_each_safe(pointer, next_pointer, &frame->pointers, link)
297 frame_pointer_destroy(pointer);
298
299 free(frame->title);
300 free(frame);
301 }
302
303 struct frame *
frame_create(struct theme * t,int32_t width,int32_t height,uint32_t buttons,const char * title)304 frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
305 const char *title)
306 {
307 struct frame *frame;
308 struct frame_button *button;
309
310 frame = calloc(1, sizeof *frame);
311 if (!frame)
312 return NULL;
313
314 frame->width = width;
315 frame->height = height;
316 frame->flags = 0;
317 frame->theme = t;
318 frame->status = FRAME_STATUS_REPAINT;
319 frame->geometry_dirty = 1;
320
321 wl_list_init(&frame->buttons);
322 wl_list_init(&frame->pointers);
323 wl_list_init(&frame->touches);
324
325 if (title) {
326 frame->title = strdup(title);
327 if (!frame->title)
328 goto free_frame;
329 }
330
331 if (title) {
332 button = frame_button_create(frame,
333 DATADIR "/weston/icon_window.png",
334 FRAME_STATUS_MENU,
335 FRAME_BUTTON_CLICK_DOWN);
336 if (!button)
337 goto free_frame;
338 }
339
340 if (buttons & FRAME_BUTTON_CLOSE) {
341 button = frame_button_create(frame,
342 DATADIR "/weston/sign_close.png",
343 FRAME_STATUS_CLOSE,
344 FRAME_BUTTON_ALIGN_RIGHT |
345 FRAME_BUTTON_DECORATED);
346 if (!button)
347 goto free_frame;
348 }
349
350 if (buttons & FRAME_BUTTON_MAXIMIZE) {
351 button = frame_button_create(frame,
352 DATADIR "/weston/sign_maximize.png",
353 FRAME_STATUS_MAXIMIZE,
354 FRAME_BUTTON_ALIGN_RIGHT |
355 FRAME_BUTTON_DECORATED);
356 if (!button)
357 goto free_frame;
358 }
359
360 if (buttons & FRAME_BUTTON_MINIMIZE) {
361 button = frame_button_create(frame,
362 DATADIR "/weston/sign_minimize.png",
363 FRAME_STATUS_MINIMIZE,
364 FRAME_BUTTON_ALIGN_RIGHT |
365 FRAME_BUTTON_DECORATED);
366 if (!button)
367 goto free_frame;
368 }
369
370 return frame;
371
372 free_frame:
373 frame_destroy(frame);
374 return NULL;
375 }
376
377 int
frame_set_title(struct frame * frame,const char * title)378 frame_set_title(struct frame *frame, const char *title)
379 {
380 char *dup = NULL;
381
382 if (title) {
383 dup = strdup(title);
384 if (!dup)
385 return -1;
386 }
387
388 free(frame->title);
389 frame->title = dup;
390
391 frame->geometry_dirty = 1;
392 frame->status |= FRAME_STATUS_REPAINT;
393
394 return 0;
395 }
396
397 void
frame_set_flag(struct frame * frame,enum frame_flag flag)398 frame_set_flag(struct frame *frame, enum frame_flag flag)
399 {
400 if (flag & FRAME_FLAG_MAXIMIZED && !(frame->flags & FRAME_FLAG_MAXIMIZED))
401 frame->geometry_dirty = 1;
402
403 frame->flags |= flag;
404 frame->status |= FRAME_STATUS_REPAINT;
405 }
406
407 void
frame_unset_flag(struct frame * frame,enum frame_flag flag)408 frame_unset_flag(struct frame *frame, enum frame_flag flag)
409 {
410 if (flag & FRAME_FLAG_MAXIMIZED && frame->flags & FRAME_FLAG_MAXIMIZED)
411 frame->geometry_dirty = 1;
412
413 frame->flags &= ~flag;
414 frame->status |= FRAME_STATUS_REPAINT;
415 }
416
417 void
frame_resize(struct frame * frame,int32_t width,int32_t height)418 frame_resize(struct frame *frame, int32_t width, int32_t height)
419 {
420 frame->width = width;
421 frame->height = height;
422
423 frame->geometry_dirty = 1;
424 frame->status |= FRAME_STATUS_REPAINT;
425 }
426
427 void
frame_resize_inside(struct frame * frame,int32_t width,int32_t height)428 frame_resize_inside(struct frame *frame, int32_t width, int32_t height)
429 {
430 struct theme *t = frame->theme;
431 int decoration_width, decoration_height, titlebar_height;
432
433 if (frame->title || !wl_list_empty(&frame->buttons))
434 titlebar_height = t->titlebar_height;
435 else
436 titlebar_height = t->width;
437
438 if (frame->flags & FRAME_FLAG_MAXIMIZED) {
439 decoration_width = t->width * 2;
440 decoration_height = t->width + titlebar_height;
441 } else {
442 decoration_width = (t->width + t->margin) * 2;
443 decoration_height = t->width +
444 titlebar_height + t->margin * 2;
445 }
446
447 frame_resize(frame, width + decoration_width,
448 height + decoration_height);
449 }
450
451 int32_t
frame_width(struct frame * frame)452 frame_width(struct frame *frame)
453 {
454 return frame->width;
455 }
456
457 int32_t
frame_height(struct frame * frame)458 frame_height(struct frame *frame)
459 {
460 return frame->height;
461 }
462
463 static void
frame_refresh_geometry(struct frame * frame)464 frame_refresh_geometry(struct frame *frame)
465 {
466 struct frame_button *button;
467 struct theme *t = frame->theme;
468 int x_l, x_r, y, w, h, titlebar_height;
469 int32_t decoration_width, decoration_height;
470
471 if (!frame->geometry_dirty)
472 return;
473
474 if (frame->title || !wl_list_empty(&frame->buttons))
475 titlebar_height = t->titlebar_height;
476 else
477 titlebar_height = t->width;
478
479 if (frame->flags & FRAME_FLAG_MAXIMIZED) {
480 decoration_width = t->width * 2;
481 decoration_height = t->width + titlebar_height;
482
483 frame->interior.x = t->width;
484 frame->interior.y = titlebar_height;
485 frame->interior.width = frame->width - decoration_width;
486 frame->interior.height = frame->height - decoration_height;
487
488 frame->opaque_margin = 0;
489 frame->shadow_margin = 0;
490 } else {
491 decoration_width = (t->width + t->margin) * 2;
492 decoration_height = t->width + titlebar_height + t->margin * 2;
493
494 frame->interior.x = t->width + t->margin;
495 frame->interior.y = titlebar_height + t->margin;
496 frame->interior.width = frame->width - decoration_width;
497 frame->interior.height = frame->height - decoration_height;
498
499 frame->opaque_margin = t->margin + t->frame_radius;
500 frame->shadow_margin = t->margin;
501 }
502
503 x_r = frame->width - t->width - frame->shadow_margin;
504 x_l = t->width + frame->shadow_margin;
505 y = t->width + frame->shadow_margin;
506 wl_list_for_each(button, &frame->buttons, link) {
507 const int button_padding = 4;
508 w = cairo_image_surface_get_width(button->icon);
509 h = cairo_image_surface_get_height(button->icon);
510
511 if (button->flags & FRAME_BUTTON_DECORATED)
512 w += 10;
513
514 if (button->flags & FRAME_BUTTON_ALIGN_RIGHT) {
515 x_r -= w;
516
517 button->allocation.x = x_r;
518 button->allocation.y = y;
519 button->allocation.width = w + 1;
520 button->allocation.height = h + 1;
521
522 x_r -= button_padding;
523 } else {
524 button->allocation.x = x_l;
525 button->allocation.y = y;
526 button->allocation.width = w + 1;
527 button->allocation.height = h + 1;
528
529 x_l += w;
530 x_l += button_padding;
531 }
532 }
533
534 frame->geometry_dirty = 0;
535 }
536
537 void
frame_interior(struct frame * frame,int32_t * x,int32_t * y,int32_t * width,int32_t * height)538 frame_interior(struct frame *frame, int32_t *x, int32_t *y,
539 int32_t *width, int32_t *height)
540 {
541 frame_refresh_geometry(frame);
542
543 if (x)
544 *x = frame->interior.x;
545 if (y)
546 *y = frame->interior.y;
547 if (width)
548 *width = frame->interior.width;
549 if (height)
550 *height = frame->interior.height;
551 }
552
553 void
frame_input_rect(struct frame * frame,int32_t * x,int32_t * y,int32_t * width,int32_t * height)554 frame_input_rect(struct frame *frame, int32_t *x, int32_t *y,
555 int32_t *width, int32_t *height)
556 {
557 frame_refresh_geometry(frame);
558
559 if (x)
560 *x = frame->shadow_margin;
561 if (y)
562 *y = frame->shadow_margin;
563 if (width)
564 *width = frame->width - frame->shadow_margin * 2;
565 if (height)
566 *height = frame->height - frame->shadow_margin * 2;
567 }
568
569 void
frame_opaque_rect(struct frame * frame,int32_t * x,int32_t * y,int32_t * width,int32_t * height)570 frame_opaque_rect(struct frame *frame, int32_t *x, int32_t *y,
571 int32_t *width, int32_t *height)
572 {
573 frame_refresh_geometry(frame);
574
575 if (x)
576 *x = frame->opaque_margin;
577 if (y)
578 *y = frame->opaque_margin;
579 if (width)
580 *width = frame->width - frame->opaque_margin * 2;
581 if (height)
582 *height = frame->height - frame->opaque_margin * 2;
583 }
584
585 int
frame_get_shadow_margin(struct frame * frame)586 frame_get_shadow_margin(struct frame *frame)
587 {
588 frame_refresh_geometry(frame);
589
590 return frame->shadow_margin;
591 }
592
593 uint32_t
frame_status(struct frame * frame)594 frame_status(struct frame *frame)
595 {
596 return frame->status;
597 }
598
599 void
frame_status_clear(struct frame * frame,enum frame_status status)600 frame_status_clear(struct frame *frame, enum frame_status status)
601 {
602 frame->status &= ~status;
603 }
604
605 static struct frame_button *
frame_find_button(struct frame * frame,int x,int y)606 frame_find_button(struct frame *frame, int x, int y)
607 {
608 struct frame_button *button;
609 int rel_x, rel_y;
610
611 wl_list_for_each(button, &frame->buttons, link) {
612 rel_x = x - button->allocation.x;
613 rel_y = y - button->allocation.y;
614
615 if (0 <= rel_x && rel_x < button->allocation.width &&
616 0 <= rel_y && rel_y < button->allocation.height)
617 return button;
618 }
619
620 return NULL;
621 }
622
623 enum theme_location
frame_pointer_enter(struct frame * frame,void * data,int x,int y)624 frame_pointer_enter(struct frame *frame, void *data, int x, int y)
625 {
626 return frame_pointer_motion(frame, data, x, y);
627 }
628
629 enum theme_location
frame_pointer_motion(struct frame * frame,void * data,int x,int y)630 frame_pointer_motion(struct frame *frame, void *data, int x, int y)
631 {
632 struct frame_pointer *pointer = frame_pointer_get(frame, data);
633 struct frame_button *button = frame_find_button(frame, x, y);
634 enum theme_location location;
635
636 location = theme_get_location(frame->theme, x, y,
637 frame->width, frame->height,
638 frame->flags & FRAME_FLAG_MAXIMIZED ?
639 THEME_FRAME_MAXIMIZED : 0);
640 if (!pointer)
641 return location;
642
643 pointer->x = x;
644 pointer->y = y;
645
646 if (pointer->hover_button == button)
647 return location;
648
649 if (pointer->hover_button)
650 frame_button_leave(pointer->hover_button, pointer);
651
652 pointer->hover_button = button;
653
654 if (pointer->hover_button)
655 frame_button_enter(pointer->hover_button);
656
657 return location;
658 }
659
660 static void
frame_pointer_button_destroy(struct frame_pointer_button * button)661 frame_pointer_button_destroy(struct frame_pointer_button *button)
662 {
663 wl_list_remove(&button->link);
664 free(button);
665 }
666
667 static void
frame_pointer_button_press(struct frame * frame,struct frame_pointer * pointer,struct frame_pointer_button * button)668 frame_pointer_button_press(struct frame *frame, struct frame_pointer *pointer,
669 struct frame_pointer_button *button)
670 {
671 if (button->button == BTN_RIGHT) {
672 if (button->press_location == THEME_LOCATION_TITLEBAR)
673 frame->status |= FRAME_STATUS_MENU;
674
675 frame_pointer_button_destroy(button);
676
677 } else if (button->button == BTN_LEFT) {
678 if (pointer->hover_button) {
679 frame_button_press(pointer->hover_button);
680 } else {
681 switch (button->press_location) {
682 case THEME_LOCATION_TITLEBAR:
683 frame->status |= FRAME_STATUS_MOVE;
684
685 frame_pointer_button_destroy(button);
686 break;
687 case THEME_LOCATION_RESIZING_TOP:
688 case THEME_LOCATION_RESIZING_BOTTOM:
689 case THEME_LOCATION_RESIZING_LEFT:
690 case THEME_LOCATION_RESIZING_RIGHT:
691 case THEME_LOCATION_RESIZING_TOP_LEFT:
692 case THEME_LOCATION_RESIZING_TOP_RIGHT:
693 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
694 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
695 frame->status |= FRAME_STATUS_RESIZE;
696
697 frame_pointer_button_destroy(button);
698 break;
699 default:
700 break;
701 }
702 }
703 }
704 }
705
706 static void
frame_pointer_button_release(struct frame * frame,struct frame_pointer * pointer,struct frame_pointer_button * button)707 frame_pointer_button_release(struct frame *frame, struct frame_pointer *pointer,
708 struct frame_pointer_button *button)
709 {
710 if (button->button == BTN_LEFT && button->frame_button) {
711 if (button->frame_button == pointer->hover_button)
712 frame_button_release(button->frame_button);
713 else
714 frame_button_cancel(button->frame_button);
715 }
716 }
717
718 static void
frame_pointer_button_cancel(struct frame * frame,struct frame_pointer * pointer,struct frame_pointer_button * button)719 frame_pointer_button_cancel(struct frame *frame, struct frame_pointer *pointer,
720 struct frame_pointer_button *button)
721 {
722 if (button->frame_button)
723 frame_button_cancel(button->frame_button);
724 }
725
726 void
frame_pointer_leave(struct frame * frame,void * data)727 frame_pointer_leave(struct frame *frame, void *data)
728 {
729 struct frame_pointer *pointer = frame_pointer_get(frame, data);
730 struct frame_pointer_button *button, *next;
731 if (!pointer)
732 return;
733
734 if (pointer->hover_button)
735 frame_button_leave(pointer->hover_button, pointer);
736
737 wl_list_for_each_safe(button, next, &pointer->down_buttons, link) {
738 frame_pointer_button_cancel(frame, pointer, button);
739 frame_pointer_button_destroy(button);
740 }
741
742 frame_pointer_destroy(pointer);
743 }
744
745 enum theme_location
frame_pointer_button(struct frame * frame,void * data,uint32_t btn,enum frame_button_state state)746 frame_pointer_button(struct frame *frame, void *data,
747 uint32_t btn, enum frame_button_state state)
748 {
749 struct frame_pointer *pointer = frame_pointer_get(frame, data);
750 struct frame_pointer_button *button;
751 enum theme_location location = THEME_LOCATION_EXTERIOR;
752
753 if (!pointer)
754 return location;
755
756 location = theme_get_location(frame->theme, pointer->x, pointer->y,
757 frame->width, frame->height,
758 frame->flags & FRAME_FLAG_MAXIMIZED ?
759 THEME_FRAME_MAXIMIZED : 0);
760
761 if (state == FRAME_BUTTON_PRESSED) {
762 button = malloc(sizeof *button);
763 if (!button)
764 return location;
765
766 button->button = btn;
767 button->press_location = location;
768 button->frame_button = pointer->hover_button;
769 wl_list_insert(&pointer->down_buttons, &button->link);
770
771 frame_pointer_button_press(frame, pointer, button);
772 } else if (state == FRAME_BUTTON_RELEASED) {
773 button = NULL;
774 wl_list_for_each(button, &pointer->down_buttons, link)
775 if (button->button == btn)
776 break;
777 /* Make sure we didn't hit the end */
778 if (&button->link == &pointer->down_buttons)
779 return location;
780
781 location = button->press_location;
782 frame_pointer_button_release(frame, pointer, button);
783 frame_pointer_button_destroy(button);
784 }
785
786 return location;
787 }
788
789 void
frame_touch_down(struct frame * frame,void * data,int32_t id,int x,int y)790 frame_touch_down(struct frame *frame, void *data, int32_t id, int x, int y)
791 {
792 struct frame_touch *touch = frame_touch_get(frame, data);
793 struct frame_button *button = frame_find_button(frame, x, y);
794 enum theme_location location;
795
796 if (id > 0)
797 return;
798
799 if (touch && button) {
800 touch->button = button;
801 frame_button_press(touch->button);
802 return;
803 }
804
805 location = theme_get_location(frame->theme, x, y,
806 frame->width, frame->height,
807 frame->flags & FRAME_FLAG_MAXIMIZED ?
808 THEME_FRAME_MAXIMIZED : 0);
809
810 switch (location) {
811 case THEME_LOCATION_TITLEBAR:
812 frame->status |= FRAME_STATUS_MOVE;
813 break;
814 case THEME_LOCATION_RESIZING_TOP:
815 case THEME_LOCATION_RESIZING_BOTTOM:
816 case THEME_LOCATION_RESIZING_LEFT:
817 case THEME_LOCATION_RESIZING_RIGHT:
818 case THEME_LOCATION_RESIZING_TOP_LEFT:
819 case THEME_LOCATION_RESIZING_TOP_RIGHT:
820 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
821 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
822 frame->status |= FRAME_STATUS_RESIZE;
823 break;
824 default:
825 break;
826 }
827 }
828
829 void
frame_touch_up(struct frame * frame,void * data,int32_t id)830 frame_touch_up(struct frame *frame, void *data, int32_t id)
831 {
832 struct frame_touch *touch = frame_touch_get(frame, data);
833
834 if (id > 0)
835 return;
836
837 if (touch && touch->button) {
838 frame_button_release(touch->button);
839 frame_touch_destroy(touch);
840 }
841 }
842
843 enum theme_location
frame_double_click(struct frame * frame,void * data,uint32_t btn,enum frame_button_state state)844 frame_double_click(struct frame *frame, void *data,
845 uint32_t btn, enum frame_button_state state)
846 {
847 struct frame_pointer *pointer = frame_pointer_get(frame, data);
848 struct frame_button *button;
849 enum theme_location location = THEME_LOCATION_EXTERIOR;
850
851 location = theme_get_location(frame->theme, pointer->x, pointer->y,
852 frame->width, frame->height,
853 frame->flags & FRAME_FLAG_MAXIMIZED ?
854 THEME_FRAME_MAXIMIZED : 0);
855
856 button = frame_find_button(frame, pointer->x, pointer->y);
857
858 if (location != THEME_LOCATION_TITLEBAR || btn != BTN_LEFT)
859 return location;
860
861 if (state == FRAME_BUTTON_PRESSED) {
862 if (button)
863 frame_button_press(button);
864 else
865 frame->status |= FRAME_STATUS_MAXIMIZE;
866 } else if (state == FRAME_BUTTON_RELEASED) {
867 if (button)
868 frame_button_release(button);
869 }
870
871 return location;
872 }
873
874 void
frame_double_touch_down(struct frame * frame,void * data,int32_t id,int x,int y)875 frame_double_touch_down(struct frame *frame, void *data, int32_t id,
876 int x, int y)
877 {
878 struct frame_touch *touch = frame_touch_get(frame, data);
879 struct frame_button *button = frame_find_button(frame, x, y);
880 enum theme_location location;
881
882 if (touch && button) {
883 touch->button = button;
884 frame_button_press(touch->button);
885 return;
886 }
887
888 location = theme_get_location(frame->theme, x, y,
889 frame->width, frame->height,
890 frame->flags & FRAME_FLAG_MAXIMIZED ?
891 THEME_FRAME_MAXIMIZED : 0);
892
893 switch (location) {
894 case THEME_LOCATION_TITLEBAR:
895 frame->status |= FRAME_STATUS_MAXIMIZE;
896 break;
897 case THEME_LOCATION_RESIZING_TOP:
898 case THEME_LOCATION_RESIZING_BOTTOM:
899 case THEME_LOCATION_RESIZING_LEFT:
900 case THEME_LOCATION_RESIZING_RIGHT:
901 case THEME_LOCATION_RESIZING_TOP_LEFT:
902 case THEME_LOCATION_RESIZING_TOP_RIGHT:
903 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
904 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
905 frame->status |= FRAME_STATUS_RESIZE;
906 break;
907 default:
908 break;
909 }
910 }
911
912 void
frame_double_touch_up(struct frame * frame,void * data,int32_t id)913 frame_double_touch_up(struct frame *frame, void *data, int32_t id)
914 {
915 struct frame_touch *touch = frame_touch_get(frame, data);
916
917 if (touch && touch->button) {
918 frame_button_release(touch->button);
919 frame_touch_destroy(touch);
920 }
921 }
922
923 void
frame_repaint(struct frame * frame,cairo_t * cr)924 frame_repaint(struct frame *frame, cairo_t *cr)
925 {
926 struct frame_button *button;
927 uint32_t flags = 0;
928
929 frame_refresh_geometry(frame);
930
931 if (frame->flags & FRAME_FLAG_MAXIMIZED)
932 flags |= THEME_FRAME_MAXIMIZED;
933
934 if (frame->flags & FRAME_FLAG_ACTIVE)
935 flags |= THEME_FRAME_ACTIVE;
936
937 cairo_save(cr);
938 theme_render_frame(frame->theme, cr, frame->width, frame->height,
939 frame->title, &frame->buttons, flags);
940 cairo_restore(cr);
941
942 wl_list_for_each(button, &frame->buttons, link)
943 frame_button_repaint(button, cr);
944
945 frame_status_clear(frame, FRAME_STATUS_REPAINT);
946 }
947