window: Implement animated cursors (using pointer surfaces)
[platform/upstream/weston.git] / clients / desktop-shell.c
1 /*
2  * Copyright © 2011 Kristian Høgsberg
3  * Copyright © 2011 Collabora, Ltd.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <math.h>
31 #include <cairo.h>
32 #include <sys/wait.h>
33 #include <sys/timerfd.h>
34 #include <sys/epoll.h> 
35 #include <linux/input.h>
36 #include <libgen.h>
37 #include <time.h>
38
39 #include <wayland-client.h>
40 #include "window.h"
41 #include "../shared/cairo-util.h"
42 #include "../shared/config-parser.h"
43
44 #include "desktop-shell-client-protocol.h"
45
46 struct desktop {
47         struct display *display;
48         struct desktop_shell *shell;
49         struct unlock_dialog *unlock_dialog;
50         struct task unlock_task;
51         struct wl_list outputs;
52
53         struct window *busy_window;
54         struct widget *busy_widget;
55 };
56
57 struct surface {
58         void (*configure)(void *data,
59                           struct desktop_shell *desktop_shell,
60                           uint32_t edges, struct window *window,
61                           int32_t width, int32_t height);
62 };
63
64 struct panel {
65         struct surface base;
66         struct window *window;
67         struct widget *widget;
68         struct wl_list launcher_list;
69         struct panel_clock *clock;
70 };
71
72 struct background {
73         struct surface base;
74         struct window *window;
75         struct widget *widget;
76 };
77
78 struct output {
79         struct wl_output *output;
80         struct wl_list link;
81
82         struct panel *panel;
83         struct background *background;
84 };
85
86 struct panel_launcher {
87         struct widget *widget;
88         struct panel *panel;
89         cairo_surface_t *icon;
90         int focused, pressed;
91         const char *path;
92         struct wl_list link;
93 };
94
95 struct panel_clock {
96         struct widget *widget;
97         struct panel *panel;
98         struct task clock_task;
99         int clock_fd;
100 };
101
102 struct unlock_dialog {
103         struct window *window;
104         struct widget *widget;
105         struct widget *button;
106         int button_focused;
107         int closing;
108         struct desktop *desktop;
109 };
110
111 static char *key_background_image = DATADIR "/weston/pattern.png";
112 static char *key_background_type = "tile";
113 static uint32_t key_panel_color = 0xaa000000;
114 static uint32_t key_background_color = 0xff002244;
115 static char *key_launcher_icon;
116 static char *key_launcher_path;
117 static void launcher_section_done(void *data);
118 static int key_locking = 1;
119
120 static const struct config_key shell_config_keys[] = {
121         { "background-image", CONFIG_KEY_STRING, &key_background_image },
122         { "background-type", CONFIG_KEY_STRING, &key_background_type },
123         { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
124         { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
125         { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
126 };
127
128 static const struct config_key launcher_config_keys[] = {
129         { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
130         { "path", CONFIG_KEY_STRING, &key_launcher_path },
131 };
132
133 static const struct config_section config_sections[] = {
134         { "shell",
135           shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
136         { "launcher",
137           launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
138           launcher_section_done }
139 };
140
141 static void
142 sigchild_handler(int s)
143 {
144         int status;
145         pid_t pid;
146
147         while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
148                 fprintf(stderr, "child %d exited\n", pid);
149 }
150
151 static void
152 menu_func(struct window *window, int index, void *data)
153 {
154         printf("Selected index %d from a panel menu.\n", index);
155 }
156
157 static void
158 show_menu(struct panel *panel, struct input *input, uint32_t time)
159 {
160         int32_t x, y;
161         static const char *entries[] = {
162                 "Roy", "Pris", "Leon", "Zhora"
163         };
164
165         input_get_position(input, &x, &y);
166         window_show_menu(window_get_display(panel->window),
167                          input, time, panel->window,
168                          x - 10, y - 10, menu_func, entries, 4);
169 }
170
171 static void
172 panel_launcher_activate(struct panel_launcher *widget)
173 {
174         pid_t pid;
175
176         pid = fork();
177         if (pid < 0) {
178                 fprintf(stderr, "fork failed: %m\n");
179                 return;
180         }
181
182         if (pid)
183                 return;
184
185         if (execl(widget->path, widget->path, NULL) < 0) {
186                 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
187                 exit(1);
188         }
189 }
190
191 static void
192 panel_launcher_redraw_handler(struct widget *widget, void *data)
193 {
194         struct panel_launcher *launcher = data;
195         cairo_surface_t *surface;
196         struct rectangle allocation;
197         cairo_t *cr;
198
199         surface = window_get_surface(launcher->panel->window);
200         cr = cairo_create(surface);
201
202         widget_get_allocation(widget, &allocation);
203         if (launcher->pressed) {
204                 allocation.x++;
205                 allocation.y++;
206         }
207
208         cairo_set_source_surface(cr, launcher->icon,
209                                  allocation.x, allocation.y);
210         cairo_paint(cr);
211
212         if (launcher->focused) {
213                 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
214                 cairo_mask_surface(cr, launcher->icon,
215                                    allocation.x, allocation.y);
216         }
217
218         cairo_destroy(cr);
219 }
220
221 static int
222 panel_launcher_motion_handler(struct widget *widget, struct input *input,
223                               uint32_t time, float x, float y, void *data)
224 {
225         struct panel_launcher *launcher = data;
226
227         widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
228
229         return CURSOR_LEFT_PTR;
230 }
231
232 static void
233 set_hex_color(cairo_t *cr, uint32_t color)
234 {
235         cairo_set_source_rgba(cr, 
236                               ((color >> 16) & 0xff) / 255.0,
237                               ((color >>  8) & 0xff) / 255.0,
238                               ((color >>  0) & 0xff) / 255.0,
239                               ((color >> 24) & 0xff) / 255.0);
240 }
241
242 static void
243 panel_redraw_handler(struct widget *widget, void *data)
244 {
245         cairo_surface_t *surface;
246         cairo_t *cr;
247         struct panel *panel = data;
248
249         surface = window_get_surface(panel->window);
250         cr = cairo_create(surface);
251         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
252         set_hex_color(cr, key_panel_color);
253         cairo_paint(cr);
254
255         cairo_destroy(cr);
256         cairo_surface_destroy(surface);
257 }
258
259 static int
260 panel_launcher_enter_handler(struct widget *widget, struct input *input,
261                              float x, float y, void *data)
262 {
263         struct panel_launcher *launcher = data;
264
265         launcher->focused = 1;
266         widget_schedule_redraw(widget);
267
268         return CURSOR_LEFT_PTR;
269 }
270
271 static void
272 panel_launcher_leave_handler(struct widget *widget,
273                              struct input *input, void *data)
274 {
275         struct panel_launcher *launcher = data;
276
277         launcher->focused = 0;
278         widget_destroy_tooltip(widget);
279         widget_schedule_redraw(widget);
280 }
281
282 static void
283 panel_launcher_button_handler(struct widget *widget,
284                               struct input *input, uint32_t time,
285                               uint32_t button,
286                               enum wl_pointer_button_state state, void *data)
287 {
288         struct panel_launcher *launcher;
289
290         launcher = widget_get_user_data(widget);
291         widget_schedule_redraw(widget);
292         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
293                 panel_launcher_activate(launcher);
294 }
295
296 static void
297 clock_func(struct task *task, uint32_t events)
298 {
299         struct panel_clock *clock =
300                 container_of(task, struct panel_clock, clock_task);
301         uint64_t exp;
302
303         read(clock->clock_fd, &exp, sizeof exp);
304         widget_schedule_redraw(clock->widget);
305 }
306
307 static void
308 panel_clock_redraw_handler(struct widget *widget, void *data)
309 {
310         cairo_surface_t *surface;
311         struct panel_clock *clock = data;
312         cairo_t *cr;
313         struct rectangle allocation;
314         cairo_text_extents_t extents;
315         cairo_font_extents_t font_extents;
316         time_t rawtime;
317         struct tm * timeinfo;
318         char string[128];
319
320         time(&rawtime);
321         timeinfo = localtime(&rawtime);
322         strftime(string, sizeof string, "%a %b %d, %I:%M %p", timeinfo);
323
324         widget_get_allocation(widget, &allocation);
325         if (allocation.width == 0)
326                 return;
327
328         surface = window_get_surface(clock->panel->window);
329         cr = cairo_create(surface);
330         cairo_select_font_face(cr, "sans",
331                                CAIRO_FONT_SLANT_NORMAL,
332                                CAIRO_FONT_WEIGHT_NORMAL);
333         cairo_set_font_size(cr, 14);
334         cairo_text_extents(cr, string, &extents);
335         cairo_font_extents (cr, &font_extents);
336         cairo_move_to(cr, allocation.x + 5,
337                       allocation.y + 3 * (allocation.height >> 2) + 1);
338         cairo_set_source_rgb(cr, 0, 0, 0);
339         cairo_show_text(cr, string);
340         cairo_move_to(cr, allocation.x + 4,
341                       allocation.y + 3 * (allocation.height >> 2));
342         cairo_set_source_rgb(cr, 1, 1, 1);
343         cairo_show_text(cr, string);
344         cairo_destroy(cr);
345 }
346
347 static int
348 clock_timer_reset(struct panel_clock *clock)
349 {
350         struct itimerspec its;
351
352         its.it_interval.tv_sec = 60;
353         its.it_interval.tv_nsec = 0;
354         its.it_value.tv_sec = 60;
355         its.it_value.tv_nsec = 0;
356         if (timerfd_settime(clock->clock_fd, 0, &its, NULL) < 0) {
357                 fprintf(stderr, "could not set timerfd\n: %m");
358                 return -1;
359         }
360
361         return 0;
362 }
363
364 static void
365 panel_add_clock(struct panel *panel)
366 {
367         struct panel_clock *clock;
368         int timerfd;
369
370         timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
371         if (timerfd < 0) {
372                 fprintf(stderr, "could not create timerfd\n: %m");
373                 return;
374         }
375
376         clock = malloc(sizeof *clock);
377         memset(clock, 0, sizeof *clock);
378         clock->panel = panel;
379         panel->clock = clock;
380         clock->clock_fd = timerfd;
381
382         clock->clock_task.run = clock_func;
383         display_watch_fd(window_get_display(panel->window), clock->clock_fd,
384                          EPOLLIN, &clock->clock_task);
385         clock_timer_reset(clock);
386
387         clock->widget = widget_add_widget(panel->widget, clock);
388         widget_set_redraw_handler(clock->widget, panel_clock_redraw_handler);
389 }
390
391 static void
392 panel_button_handler(struct widget *widget,
393                      struct input *input, uint32_t time,
394                      uint32_t button,
395                      enum wl_pointer_button_state state, void *data)
396 {
397         struct panel *panel = data;
398
399         if (button == BTN_RIGHT && state == WL_POINTER_BUTTON_STATE_PRESSED)
400                 show_menu(panel, input, time);
401 }
402
403 static void
404 panel_resize_handler(struct widget *widget,
405                      int32_t width, int32_t height, void *data)
406 {
407         struct panel_launcher *launcher;
408         struct panel *panel = data;
409         int x, y, w, h;
410         
411         x = 10;
412         y = 16;
413         wl_list_for_each(launcher, &panel->launcher_list, link) {
414                 w = cairo_image_surface_get_width(launcher->icon);
415                 h = cairo_image_surface_get_height(launcher->icon);
416                 widget_set_allocation(launcher->widget,
417                                       x, y - h / 2, w + 1, h + 1);
418                 x += w + 10;
419         }
420         h=20;
421         w=170;
422
423         if (panel->clock)
424                 widget_set_allocation(panel->clock->widget,
425                                       width - w - 8, y - h / 2, w + 1, h + 1);
426 }
427
428 static void
429 panel_configure(void *data,
430                 struct desktop_shell *desktop_shell,
431                 uint32_t edges, struct window *window,
432                 int32_t width, int32_t height)
433 {
434         struct surface *surface = window_get_user_data(window);
435         struct panel *panel = container_of(surface, struct panel, base);
436
437         window_schedule_resize(panel->window, width, 32);
438 }
439
440 static struct panel *
441 panel_create(struct display *display)
442 {
443         struct panel *panel;
444
445         panel = malloc(sizeof *panel);
446         memset(panel, 0, sizeof *panel);
447
448         panel->base.configure = panel_configure;
449         panel->window = window_create(display);
450         panel->widget = window_add_widget(panel->window, panel);
451         wl_list_init(&panel->launcher_list);
452
453         window_set_title(panel->window, "panel");
454         window_set_custom(panel->window);
455         window_set_user_data(panel->window, panel);
456
457         widget_set_redraw_handler(panel->widget, panel_redraw_handler);
458         widget_set_resize_handler(panel->widget, panel_resize_handler);
459         widget_set_button_handler(panel->widget, panel_button_handler);
460         
461         panel_add_clock(panel);
462
463         return panel;
464 }
465
466 static void
467 panel_add_launcher(struct panel *panel, const char *icon, const char *path)
468 {
469         struct panel_launcher *launcher;
470
471         launcher = malloc(sizeof *launcher);
472         memset(launcher, 0, sizeof *launcher);
473         launcher->icon = cairo_image_surface_create_from_png(icon);
474         launcher->path = strdup(path);
475         launcher->panel = panel;
476         wl_list_insert(panel->launcher_list.prev, &launcher->link);
477
478         launcher->widget = widget_add_widget(panel->widget, launcher);
479         widget_set_enter_handler(launcher->widget,
480                                  panel_launcher_enter_handler);
481         widget_set_leave_handler(launcher->widget,
482                                    panel_launcher_leave_handler);
483         widget_set_button_handler(launcher->widget,
484                                     panel_launcher_button_handler);
485         widget_set_redraw_handler(launcher->widget,
486                                   panel_launcher_redraw_handler);
487         widget_set_motion_handler(launcher->widget,
488                                   panel_launcher_motion_handler);
489 }
490
491 enum {
492         BACKGROUND_SCALE,
493         BACKGROUND_TILE
494 };
495
496 static void
497 background_draw(struct widget *widget, void *data)
498 {
499         struct background *background = data;
500         cairo_surface_t *surface, *image;
501         cairo_pattern_t *pattern;
502         cairo_matrix_t matrix;
503         cairo_t *cr;
504         double sx, sy;
505         struct rectangle allocation;
506         int type = -1;
507
508         surface = window_get_surface(background->window);
509
510         cr = cairo_create(surface);
511         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
512         cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
513         cairo_paint(cr);
514
515         widget_get_allocation(widget, &allocation);
516         image = NULL;
517         if (key_background_image)
518                 image = load_cairo_surface(key_background_image);
519
520         if (strcmp(key_background_type, "scale") == 0)
521                 type = BACKGROUND_SCALE;
522         else if (strcmp(key_background_type, "tile") == 0)
523                 type = BACKGROUND_TILE;
524         else
525                 fprintf(stderr, "invalid background-type: %s\n",
526                         key_background_type);
527
528         if (image && type != -1) {
529                 pattern = cairo_pattern_create_for_surface(image);
530                 switch (type) {
531                 case BACKGROUND_SCALE:
532                         sx = (double) cairo_image_surface_get_width(image) /
533                                 allocation.width;
534                         sy = (double) cairo_image_surface_get_height(image) /
535                                 allocation.height;
536                         cairo_matrix_init_scale(&matrix, sx, sy);
537                         cairo_pattern_set_matrix(pattern, &matrix);
538                         break;
539                 case BACKGROUND_TILE:
540                         cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
541                         break;
542                 }
543                 cairo_set_source(cr, pattern);
544                 cairo_pattern_destroy (pattern);
545                 cairo_surface_destroy(image);
546         } else {
547                 set_hex_color(cr, key_background_color);
548         }
549
550         cairo_paint(cr);
551         cairo_destroy(cr);
552         cairo_surface_destroy(surface);
553 }
554
555 static void
556 background_configure(void *data,
557                      struct desktop_shell *desktop_shell,
558                      uint32_t edges, struct window *window,
559                      int32_t width, int32_t height)
560 {
561         struct background *background =
562                 (struct background *) window_get_user_data(window);
563
564         widget_schedule_resize(background->widget, width, height);
565 }
566
567 static void
568 unlock_dialog_redraw_handler(struct widget *widget, void *data)
569 {
570         struct unlock_dialog *dialog = data;
571         struct rectangle allocation;
572         cairo_t *cr;
573         cairo_surface_t *surface;
574         cairo_pattern_t *pat;
575         double cx, cy, r, f;
576
577         surface = window_get_surface(dialog->window);
578         cr = cairo_create(surface);
579
580         widget_get_allocation(dialog->widget, &allocation);
581         cairo_rectangle(cr, allocation.x, allocation.y,
582                         allocation.width, allocation.height);
583         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
584         cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
585         cairo_fill(cr);
586
587         cairo_translate(cr, allocation.x, allocation.y);
588         if (dialog->button_focused)
589                 f = 1.0;
590         else
591                 f = 0.7;
592
593         cx = allocation.width / 2.0;
594         cy = allocation.height / 2.0;
595         r = (cx < cy ? cx : cy) * 0.4;
596         pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
597         cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
598         cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
599         cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
600         cairo_set_source(cr, pat);
601         cairo_pattern_destroy(pat);
602         cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
603         cairo_fill(cr);
604
605         widget_set_allocation(dialog->button,
606                               allocation.x + cx - r,
607                               allocation.y + cy - r, 2 * r, 2 * r);
608
609         cairo_destroy(cr);
610
611         cairo_surface_destroy(surface);
612 }
613
614 static void
615 unlock_dialog_button_handler(struct widget *widget,
616                              struct input *input, uint32_t time,
617                              uint32_t button,
618                              enum wl_pointer_button_state state, void *data)
619 {
620         struct unlock_dialog *dialog = data;
621         struct desktop *desktop = dialog->desktop;
622
623         if (button == BTN_LEFT) {
624                 if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
625                     !dialog->closing) {
626                         display_defer(desktop->display, &desktop->unlock_task);
627                         dialog->closing = 1;
628                 }
629         }
630 }
631
632 static void
633 unlock_dialog_keyboard_focus_handler(struct window *window,
634                                      struct input *device, void *data)
635 {
636         window_schedule_redraw(window);
637 }
638
639 static int
640 unlock_dialog_widget_enter_handler(struct widget *widget,
641                                    struct input *input,
642                                    float x, float y, void *data)
643 {
644         struct unlock_dialog *dialog = data;
645
646         dialog->button_focused = 1;
647         widget_schedule_redraw(widget);
648
649         return CURSOR_LEFT_PTR;
650 }
651
652 static void
653 unlock_dialog_widget_leave_handler(struct widget *widget,
654                                    struct input *input, void *data)
655 {
656         struct unlock_dialog *dialog = data;
657
658         dialog->button_focused = 0;
659         widget_schedule_redraw(widget);
660 }
661
662 static struct unlock_dialog *
663 unlock_dialog_create(struct desktop *desktop)
664 {
665         struct display *display = desktop->display;
666         struct unlock_dialog *dialog;
667
668         dialog = malloc(sizeof *dialog);
669         if (!dialog)
670                 return NULL;
671         memset(dialog, 0, sizeof *dialog);
672
673         dialog->window = window_create(display);
674         dialog->widget = frame_create(dialog->window, dialog);
675         window_set_title(dialog->window, "Unlock your desktop");
676         window_set_custom(dialog->window);
677
678         window_set_user_data(dialog->window, dialog);
679         window_set_keyboard_focus_handler(dialog->window,
680                                           unlock_dialog_keyboard_focus_handler);
681         dialog->button = widget_add_widget(dialog->widget, dialog);
682         widget_set_redraw_handler(dialog->widget,
683                                   unlock_dialog_redraw_handler);
684         widget_set_enter_handler(dialog->button,
685                                  unlock_dialog_widget_enter_handler);
686         widget_set_leave_handler(dialog->button,
687                                  unlock_dialog_widget_leave_handler);
688         widget_set_button_handler(dialog->button,
689                                   unlock_dialog_button_handler);
690
691         desktop_shell_set_lock_surface(desktop->shell,
692                window_get_wl_shell_surface(dialog->window));
693
694         window_schedule_resize(dialog->window, 260, 230);
695
696         return dialog;
697 }
698
699 static void
700 unlock_dialog_destroy(struct unlock_dialog *dialog)
701 {
702         window_destroy(dialog->window);
703         free(dialog);
704 }
705
706 static void
707 unlock_dialog_finish(struct task *task, uint32_t events)
708 {
709         struct desktop *desktop =
710                 container_of(task, struct desktop, unlock_task);
711
712         desktop_shell_unlock(desktop->shell);
713         unlock_dialog_destroy(desktop->unlock_dialog);
714         desktop->unlock_dialog = NULL;
715 }
716
717 static void
718 desktop_shell_configure(void *data,
719                         struct desktop_shell *desktop_shell,
720                         uint32_t edges,
721                         struct wl_shell_surface *shell_surface,
722                         int32_t width, int32_t height)
723 {
724         struct window *window = wl_shell_surface_get_user_data(shell_surface);
725         struct surface *s = window_get_user_data(window);
726
727         s->configure(data, desktop_shell, edges, window, width, height);
728 }
729
730 static void
731 desktop_shell_prepare_lock_surface(void *data,
732                                    struct desktop_shell *desktop_shell)
733 {
734         struct desktop *desktop = data;
735
736         if (!key_locking) {
737                 desktop_shell_unlock(desktop->shell);
738                 return;
739         }
740
741         if (!desktop->unlock_dialog) {
742                 desktop->unlock_dialog = unlock_dialog_create(desktop);
743                 desktop->unlock_dialog->desktop = desktop;
744         }
745 }
746
747 static const struct desktop_shell_listener listener = {
748         desktop_shell_configure,
749         desktop_shell_prepare_lock_surface
750 };
751
752 static struct background *
753 background_create(struct desktop *desktop)
754 {
755         struct background *background;
756
757         background = malloc(sizeof *background);
758         memset(background, 0, sizeof *background);
759
760         background->base.configure = background_configure;
761         background->window = window_create(desktop->display);
762         background->widget = window_add_widget(background->window, background);
763         window_set_custom(background->window);
764         window_set_user_data(background->window, background);
765         widget_set_redraw_handler(background->widget, background_draw);
766
767         return background;
768 }
769
770 static int
771 busy_surface_enter_handler(struct widget *widget, struct input *input,
772                            float x, float y, void *data)
773 {
774         return CURSOR_WATCH;
775 }
776
777 static void
778 busy_surface_create(struct desktop *desktop)
779 {
780         struct wl_surface *s;
781
782         desktop->busy_window = window_create(desktop->display);
783         s = window_get_wl_surface(desktop->busy_window);
784         desktop_shell_set_busy_surface(desktop->shell, s);
785
786         desktop->busy_widget =
787                 window_add_widget(desktop->busy_window, desktop);
788         /* We set the allocation to 1x1 at 0,0 so the fake enter event
789          * at 0,0 will go to this widget. */
790         widget_set_allocation(desktop->busy_widget, 0, 0, 1, 1);
791
792         widget_set_enter_handler(desktop->busy_widget,
793                                  busy_surface_enter_handler);
794 }
795
796 static void
797 create_output(struct desktop *desktop, uint32_t id)
798 {
799         struct output *output;
800
801         output = calloc(1, sizeof *output);
802         if (!output)
803                 return;
804
805         output->output = wl_display_bind(display_get_display(desktop->display),
806                                          id, &wl_output_interface);
807
808         wl_list_insert(&desktop->outputs, &output->link);
809 }
810
811 static void
812 global_handler(struct wl_display *display, uint32_t id,
813                const char *interface, uint32_t version, void *data)
814 {
815         struct desktop *desktop = data;
816
817         if (!strcmp(interface, "desktop_shell")) {
818                 desktop->shell =
819                         wl_display_bind(display, id, &desktop_shell_interface);
820                 desktop_shell_add_listener(desktop->shell, &listener, desktop);
821         } else if (!strcmp(interface, "wl_output")) {
822                 create_output(desktop, id);
823         }
824 }
825
826 static void
827 launcher_section_done(void *data)
828 {
829         struct desktop *desktop = data;
830         struct output *output;
831
832         if (key_launcher_icon == NULL || key_launcher_path == NULL) {
833                 fprintf(stderr, "invalid launcher section\n");
834                 return;
835         }
836
837         wl_list_for_each(output, &desktop->outputs, link) {
838                 panel_add_launcher(output->panel,
839                                    key_launcher_icon, key_launcher_path);
840         }
841
842         free(key_launcher_icon);
843         key_launcher_icon = NULL;
844         free(key_launcher_path);
845         key_launcher_path = NULL;
846 }
847
848 static void
849 add_default_launcher(struct desktop *desktop)
850 {
851         struct output *output;
852
853         wl_list_for_each(output, &desktop->outputs, link)
854                 panel_add_launcher(output->panel,
855                                    DATADIR "/weston/terminal.png",
856                                    BINDIR "/weston-terminal");
857 }
858
859 int main(int argc, char *argv[])
860 {
861         struct desktop desktop = { 0 };
862         char *config_file;
863         struct output *output;
864         int ret;
865
866         desktop.unlock_task.run = unlock_dialog_finish;
867         wl_list_init(&desktop.outputs);
868
869         desktop.display = display_create(argc, argv);
870         if (desktop.display == NULL) {
871                 fprintf(stderr, "failed to create display: %m\n");
872                 return -1;
873         }
874
875         display_set_user_data(desktop.display, &desktop);
876         wl_display_add_global_listener(display_get_display(desktop.display),
877                                        global_handler, &desktop);
878
879         wl_list_for_each(output, &desktop.outputs, link) {
880                 struct wl_shell_surface *s;
881
882                 output->panel = panel_create(desktop.display);
883                 s = window_get_wl_shell_surface(output->panel->window);
884                 desktop_shell_set_panel(desktop.shell, output->output, s);
885
886                 output->background = background_create(&desktop);
887                 s = window_get_wl_shell_surface(output->background->window);
888                 desktop_shell_set_background(desktop.shell, output->output, s);
889         }
890
891         busy_surface_create(&desktop);
892
893         config_file = config_file_path("weston.ini");
894         ret = parse_config_file(config_file,
895                                 config_sections, ARRAY_LENGTH(config_sections),
896                                 &desktop);
897         free(config_file);
898         if (ret < 0)
899                 add_default_launcher(&desktop);
900
901         signal(SIGCHLD, sigchild_handler);
902
903         display_run(desktop.display);
904
905         return 0;
906 }