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