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