2 * Copyright © 2011 Kristian Høgsberg
3 * Copyright © 2011 Collabora, Ltd.
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.
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
33 #include <linux/input.h>
35 #include <wayland-client.h>
36 #include <wayland-cursor.h>
38 #include "../shared/cairo-util.h"
39 #include "../shared/config-parser.h"
41 #include "desktop-shell-client-protocol.h"
44 struct display *display;
45 struct desktop_shell *shell;
46 struct unlock_dialog *unlock_dialog;
47 struct task unlock_task;
48 struct wl_list outputs;
52 void (*configure)(void *data,
53 struct desktop_shell *desktop_shell,
54 uint32_t edges, struct window *window,
55 int32_t width, int32_t height);
60 struct window *window;
61 struct widget *widget;
62 struct wl_list launcher_list;
67 struct window *window;
68 struct widget *widget;
72 struct wl_output *output;
76 struct background *background;
79 struct panel_launcher {
80 struct widget *widget;
82 cairo_surface_t *icon;
88 struct unlock_dialog {
89 struct window *window;
90 struct widget *widget;
91 struct widget *button;
95 struct desktop *desktop;
98 static char *key_background_image = DATADIR "/weston/pattern.png";
99 static char *key_background_type = "tile";
100 static uint32_t key_panel_color = 0xaa000000;
101 static uint32_t key_background_color = 0xff002244;
102 static char *key_launcher_icon;
103 static char *key_launcher_path;
104 static void launcher_section_done(void *data);
105 static int key_locking = 1;
107 static const struct config_key shell_config_keys[] = {
108 { "background-image", CONFIG_KEY_STRING, &key_background_image },
109 { "background-type", CONFIG_KEY_STRING, &key_background_type },
110 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
111 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
112 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
115 static const struct config_key launcher_config_keys[] = {
116 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
117 { "path", CONFIG_KEY_STRING, &key_launcher_path },
120 static const struct config_section config_sections[] = {
122 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
124 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
125 launcher_section_done }
129 sigchild_handler(int s)
134 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
135 fprintf(stderr, "child %d exited\n", pid);
139 menu_func(struct window *window, int index, void *data)
141 printf("Selected index %d from a panel menu.\n", index);
145 show_menu(struct panel *panel, struct input *input, uint32_t time)
148 static const char *entries[] = {
149 "Roy", "Pris", "Leon", "Zhora"
152 input_get_position(input, &x, &y);
153 window_show_menu(window_get_display(panel->window),
154 input, time, panel->window,
155 x - 10, y - 10, menu_func, entries, 4);
159 panel_launcher_activate(struct panel_launcher *widget)
165 fprintf(stderr, "fork failed: %m\n");
172 if (execl(widget->path, widget->path, NULL) < 0) {
173 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
179 panel_launcher_redraw_handler(struct widget *widget, void *data)
181 struct panel_launcher *launcher = data;
182 cairo_surface_t *surface;
183 struct rectangle allocation;
186 surface = window_get_surface(launcher->panel->window);
187 cr = cairo_create(surface);
189 widget_get_allocation(widget, &allocation);
190 if (launcher->pressed) {
195 cairo_set_source_surface(cr, launcher->icon,
196 allocation.x, allocation.y);
199 if (launcher->focused) {
200 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
201 cairo_mask_surface(cr, launcher->icon,
202 allocation.x, allocation.y);
209 set_hex_color(cairo_t *cr, uint32_t color)
211 cairo_set_source_rgba(cr,
212 ((color >> 16) & 0xff) / 255.0,
213 ((color >> 8) & 0xff) / 255.0,
214 ((color >> 0) & 0xff) / 255.0,
215 ((color >> 24) & 0xff) / 255.0);
219 panel_redraw_handler(struct widget *widget, void *data)
221 cairo_surface_t *surface;
223 struct panel *panel = data;
225 surface = window_get_surface(panel->window);
226 cr = cairo_create(surface);
227 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
228 set_hex_color(cr, key_panel_color);
232 cairo_surface_destroy(surface);
236 panel_launcher_enter_handler(struct widget *widget, struct input *input,
237 float x, float y, void *data)
239 struct panel_launcher *launcher = data;
241 launcher->focused = 1;
242 widget_schedule_redraw(widget);
244 return WL_CURSOR_LEFT_PTR;
248 panel_launcher_leave_handler(struct widget *widget,
249 struct input *input, void *data)
251 struct panel_launcher *launcher = data;
253 launcher->focused = 0;
254 widget_schedule_redraw(widget);
258 panel_launcher_button_handler(struct widget *widget,
259 struct input *input, uint32_t time,
260 uint32_t button, uint32_t state, void *data)
262 struct panel_launcher *launcher;
264 launcher = widget_get_user_data(widget);
265 widget_schedule_redraw(widget);
267 panel_launcher_activate(launcher);
271 panel_button_handler(struct widget *widget,
272 struct input *input, uint32_t time,
273 uint32_t button, uint32_t state, void *data)
275 struct panel *panel = data;
277 if (button == BTN_RIGHT && state)
278 show_menu(panel, input, time);
282 panel_resize_handler(struct widget *widget,
283 int32_t width, int32_t height, void *data)
285 struct panel_launcher *launcher;
286 struct panel *panel = data;
291 wl_list_for_each(launcher, &panel->launcher_list, link) {
292 w = cairo_image_surface_get_width(launcher->icon);
293 h = cairo_image_surface_get_height(launcher->icon);
294 widget_set_allocation(launcher->widget,
295 x, y - h / 2, w + 1, h + 1);
301 panel_configure(void *data,
302 struct desktop_shell *desktop_shell,
303 uint32_t edges, struct window *window,
304 int32_t width, int32_t height)
306 struct surface *surface = window_get_user_data(window);
307 struct panel *panel = container_of(surface, struct panel, base);
309 window_schedule_resize(panel->window, width, 32);
312 static struct panel *
313 panel_create(struct display *display)
317 panel = malloc(sizeof *panel);
318 memset(panel, 0, sizeof *panel);
320 panel->base.configure = panel_configure;
321 panel->window = window_create(display);
322 panel->widget = window_add_widget(panel->window, panel);
323 wl_list_init(&panel->launcher_list);
325 window_set_title(panel->window, "panel");
326 window_set_custom(panel->window);
327 window_set_user_data(panel->window, panel);
329 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
330 widget_set_resize_handler(panel->widget, panel_resize_handler);
331 widget_set_button_handler(panel->widget, panel_button_handler);
337 panel_add_launcher(struct panel *panel, const char *icon, const char *path)
339 struct panel_launcher *launcher;
341 launcher = malloc(sizeof *launcher);
342 memset(launcher, 0, sizeof *launcher);
343 launcher->icon = cairo_image_surface_create_from_png(icon);
344 launcher->path = strdup(path);
345 launcher->panel = panel;
346 wl_list_insert(panel->launcher_list.prev, &launcher->link);
348 launcher->widget = widget_add_widget(panel->widget, launcher);
349 widget_set_enter_handler(launcher->widget,
350 panel_launcher_enter_handler);
351 widget_set_leave_handler(launcher->widget,
352 panel_launcher_leave_handler);
353 widget_set_button_handler(launcher->widget,
354 panel_launcher_button_handler);
355 widget_set_redraw_handler(launcher->widget,
356 panel_launcher_redraw_handler);
365 background_draw(struct widget *widget, void *data)
367 struct background *background = data;
368 cairo_surface_t *surface, *image;
369 cairo_pattern_t *pattern;
370 cairo_matrix_t matrix;
373 struct rectangle allocation;
376 surface = window_get_surface(background->window);
378 cr = cairo_create(surface);
379 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
380 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
383 widget_get_allocation(widget, &allocation);
385 if (key_background_image)
386 image = load_cairo_surface(key_background_image);
388 if (strcmp(key_background_type, "scale") == 0)
389 type = BACKGROUND_SCALE;
390 else if (strcmp(key_background_type, "tile") == 0)
391 type = BACKGROUND_TILE;
393 fprintf(stderr, "invalid background-type: %s\n",
394 key_background_type);
396 if (image && type != -1) {
397 pattern = cairo_pattern_create_for_surface(image);
399 case BACKGROUND_SCALE:
400 sx = (double) cairo_image_surface_get_width(image) /
402 sy = (double) cairo_image_surface_get_height(image) /
404 cairo_matrix_init_scale(&matrix, sx, sy);
405 cairo_pattern_set_matrix(pattern, &matrix);
407 case BACKGROUND_TILE:
408 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
411 cairo_set_source(cr, pattern);
412 cairo_pattern_destroy (pattern);
413 cairo_surface_destroy(image);
415 set_hex_color(cr, key_background_color);
420 cairo_surface_destroy(surface);
424 background_configure(void *data,
425 struct desktop_shell *desktop_shell,
426 uint32_t edges, struct window *window,
427 int32_t width, int32_t height)
429 struct background *background =
430 (struct background *) window_get_user_data(window);
432 widget_schedule_resize(background->widget, width, height);
436 unlock_dialog_redraw_handler(struct widget *widget, void *data)
438 struct unlock_dialog *dialog = data;
439 struct rectangle allocation;
441 cairo_surface_t *surface;
442 cairo_pattern_t *pat;
445 surface = window_get_surface(dialog->window);
446 cr = cairo_create(surface);
448 widget_get_allocation(dialog->widget, &allocation);
449 cairo_rectangle(cr, allocation.x, allocation.y,
450 allocation.width, allocation.height);
451 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
452 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
455 cairo_translate(cr, allocation.x, allocation.y);
456 if (dialog->button_focused)
461 cx = allocation.width / 2.0;
462 cy = allocation.height / 2.0;
463 r = (cx < cy ? cx : cy) * 0.4;
464 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
465 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
466 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
467 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
468 cairo_set_source(cr, pat);
469 cairo_pattern_destroy(pat);
470 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
473 widget_set_allocation(dialog->button,
474 allocation.x + cx - r,
475 allocation.y + cy - r, 2 * r, 2 * r);
479 cairo_surface_destroy(surface);
483 unlock_dialog_button_handler(struct widget *widget,
484 struct input *input, uint32_t time,
485 uint32_t button, uint32_t state, void *data)
487 struct unlock_dialog *dialog = data;
488 struct desktop *desktop = dialog->desktop;
490 if (button == BTN_LEFT) {
491 if (state == 0 && !dialog->closing) {
492 display_defer(desktop->display, &desktop->unlock_task);
499 unlock_dialog_keyboard_focus_handler(struct window *window,
500 struct input *device, void *data)
502 window_schedule_redraw(window);
506 unlock_dialog_widget_enter_handler(struct widget *widget,
508 float x, float y, void *data)
510 struct unlock_dialog *dialog = data;
512 dialog->button_focused = 1;
513 widget_schedule_redraw(widget);
515 return WL_CURSOR_LEFT_PTR;
519 unlock_dialog_widget_leave_handler(struct widget *widget,
520 struct input *input, void *data)
522 struct unlock_dialog *dialog = data;
524 dialog->button_focused = 0;
525 widget_schedule_redraw(widget);
528 static struct unlock_dialog *
529 unlock_dialog_create(struct desktop *desktop)
531 struct display *display = desktop->display;
532 struct unlock_dialog *dialog;
534 dialog = malloc(sizeof *dialog);
537 memset(dialog, 0, sizeof *dialog);
539 dialog->window = window_create(display);
540 dialog->widget = frame_create(dialog->window, dialog);
541 window_set_title(dialog->window, "Unlock your desktop");
542 window_set_custom(dialog->window);
544 window_set_user_data(dialog->window, dialog);
545 window_set_keyboard_focus_handler(dialog->window,
546 unlock_dialog_keyboard_focus_handler);
547 dialog->button = widget_add_widget(dialog->widget, dialog);
548 widget_set_redraw_handler(dialog->widget,
549 unlock_dialog_redraw_handler);
550 widget_set_enter_handler(dialog->button,
551 unlock_dialog_widget_enter_handler);
552 widget_set_leave_handler(dialog->button,
553 unlock_dialog_widget_leave_handler);
554 widget_set_button_handler(dialog->button,
555 unlock_dialog_button_handler);
557 desktop_shell_set_lock_surface(desktop->shell,
558 window_get_wl_shell_surface(dialog->window));
560 window_schedule_resize(dialog->window, 260, 230);
566 unlock_dialog_destroy(struct unlock_dialog *dialog)
568 window_destroy(dialog->window);
573 unlock_dialog_finish(struct task *task, uint32_t events)
575 struct desktop *desktop =
576 container_of(task, struct desktop, unlock_task);
578 desktop_shell_unlock(desktop->shell);
579 unlock_dialog_destroy(desktop->unlock_dialog);
580 desktop->unlock_dialog = NULL;
584 desktop_shell_configure(void *data,
585 struct desktop_shell *desktop_shell,
587 struct wl_shell_surface *shell_surface,
588 int32_t width, int32_t height)
590 struct window *window = wl_shell_surface_get_user_data(shell_surface);
591 struct surface *s = window_get_user_data(window);
593 s->configure(data, desktop_shell, edges, window, width, height);
597 desktop_shell_prepare_lock_surface(void *data,
598 struct desktop_shell *desktop_shell)
600 struct desktop *desktop = data;
603 desktop_shell_unlock(desktop->shell);
607 if (!desktop->unlock_dialog) {
608 desktop->unlock_dialog = unlock_dialog_create(desktop);
609 desktop->unlock_dialog->desktop = desktop;
613 static const struct desktop_shell_listener listener = {
614 desktop_shell_configure,
615 desktop_shell_prepare_lock_surface
618 static struct background *
619 background_create(struct desktop *desktop)
621 struct background *background;
623 background = malloc(sizeof *background);
624 memset(background, 0, sizeof *background);
626 background->base.configure = background_configure;
627 background->window = window_create(desktop->display);
628 background->widget = window_add_widget(background->window, background);
629 window_set_custom(background->window);
630 window_set_user_data(background->window, background);
631 widget_set_redraw_handler(background->widget, background_draw);
637 create_output(struct desktop *desktop, uint32_t id)
639 struct output *output;
641 output = calloc(1, sizeof *output);
645 output->output = wl_display_bind(display_get_display(desktop->display),
646 id, &wl_output_interface);
648 wl_list_insert(&desktop->outputs, &output->link);
652 global_handler(struct wl_display *display, uint32_t id,
653 const char *interface, uint32_t version, void *data)
655 struct desktop *desktop = data;
657 if (!strcmp(interface, "desktop_shell")) {
659 wl_display_bind(display, id, &desktop_shell_interface);
660 desktop_shell_add_listener(desktop->shell, &listener, desktop);
661 } else if (!strcmp(interface, "wl_output")) {
662 create_output(desktop, id);
667 launcher_section_done(void *data)
669 struct desktop *desktop = data;
670 struct output *output;
672 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
673 fprintf(stderr, "invalid launcher section\n");
677 wl_list_for_each(output, &desktop->outputs, link)
678 panel_add_launcher(output->panel,
679 key_launcher_icon, key_launcher_path);
681 free(key_launcher_icon);
682 key_launcher_icon = NULL;
683 free(key_launcher_path);
684 key_launcher_path = NULL;
688 add_default_launcher(struct desktop *desktop)
690 struct output *output;
692 wl_list_for_each(output, &desktop->outputs, link)
693 panel_add_launcher(output->panel,
694 DATADIR "/weston/terminal.png",
695 BINDIR "/weston-terminal");
698 int main(int argc, char *argv[])
700 struct desktop desktop = { 0 };
702 struct output *output;
705 desktop.unlock_task.run = unlock_dialog_finish;
706 wl_list_init(&desktop.outputs);
708 desktop.display = display_create(argc, argv);
709 if (desktop.display == NULL) {
710 fprintf(stderr, "failed to create display: %m\n");
714 wl_display_add_global_listener(display_get_display(desktop.display),
715 global_handler, &desktop);
717 wl_list_for_each(output, &desktop.outputs, link) {
718 struct wl_shell_surface *s;
720 output->panel = panel_create(desktop.display);
721 s = window_get_wl_shell_surface(output->panel->window);
722 desktop_shell_set_panel(desktop.shell, output->output, s);
724 output->background = background_create(&desktop);
725 s = window_get_wl_shell_surface(output->background->window);
726 desktop_shell_set_background(desktop.shell, output->output, s);
729 config_file = config_file_path("weston.ini");
730 ret = parse_config_file(config_file,
731 config_sections, ARRAY_LENGTH(config_sections),
735 add_default_launcher(&desktop);
737 signal(SIGCHLD, sigchild_handler);
739 display_run(desktop.display);