blob: fde001793d95db7da47a97aa475f470180f05a40 [file] [log] [blame]
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001/*
2 * Copyright © 2011 Kristian Høgsberg
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +02003 * Copyright © 2011 Collabora, Ltd.
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04004 *
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 <linux/input.h>
34
Pekka Paalanen50719bc2011-11-22 14:18:50 +020035#include <wayland-client.h>
Kristian Høgsberg27d38662011-10-20 13:11:12 -040036#include "cairo-util.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040037#include "window.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050038#include "../shared/config-parser.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040039
Pekka Paalanen50719bc2011-11-22 14:18:50 +020040#include "desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040041
42struct desktop {
43 struct display *display;
44 struct desktop_shell *shell;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020045 struct unlock_dialog *unlock_dialog;
46 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010047 struct wl_list outputs;
48};
49
50struct surface {
51 void (*configure)(void *data,
52 struct desktop_shell *desktop_shell,
53 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +020054 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010055 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040056};
57
58struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010059 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040060 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050061 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050062 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040063};
64
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010065struct background {
66 struct surface base;
67 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050068 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010069};
70
71struct output {
72 struct wl_output *output;
73 struct wl_list link;
74
75 struct panel *panel;
76 struct background *background;
77};
78
Kristian Høgsberg53880802012-01-09 11:16:50 -050079struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050080 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040081 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040082 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050083 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040084 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050085 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040086};
87
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020088struct unlock_dialog {
89 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050090 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050091 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050092 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020093 int closing;
94
95 struct desktop *desktop;
96};
97
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -050098static char *key_background_image;
99static uint32_t key_panel_color;
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500100static uint32_t key_background_color;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500101static char *key_launcher_icon;
102static char *key_launcher_path;
103static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200104static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500105
106static const struct config_key shell_config_keys[] = {
107 { "background-image", CONFIG_KEY_STRING, &key_background_image },
108 { "panel-color", CONFIG_KEY_INTEGER, &key_panel_color },
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500109 { "background-color", CONFIG_KEY_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200110 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500111};
112
113static const struct config_key launcher_config_keys[] = {
114 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
115 { "path", CONFIG_KEY_STRING, &key_launcher_path },
116};
117
118static const struct config_section config_sections[] = {
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500119 { "desktop-shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500120 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
121 { "launcher",
122 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
123 launcher_section_done }
124};
125
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400126static void
127sigchild_handler(int s)
128{
129 int status;
130 pid_t pid;
131
132 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
133 fprintf(stderr, "child %d exited\n", pid);
134}
135
136static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200137menu_func(struct window *window, int index, void *data)
138{
139 printf("Selected index %d from a panel menu.\n", index);
140}
141
142static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500143show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400144{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500145 int32_t x, y;
146 static const char *entries[] = {
147 "Roy", "Pris", "Leon", "Zhora"
148 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400149
150 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200151 window_show_menu(window_get_display(panel->window),
152 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200153 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400154}
155
156static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500157panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400158{
159 pid_t pid;
160
161 pid = fork();
162 if (pid < 0) {
163 fprintf(stderr, "fork failed: %m\n");
164 return;
165 }
166
167 if (pid)
168 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100169
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500170 if (execl(widget->path, widget->path, NULL) < 0) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400171 fprintf(stderr, "execl failed: %m\n");
172 exit(1);
173 }
174}
175
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400176static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500177panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400178{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500179 struct panel_launcher *launcher = data;
180 cairo_surface_t *surface;
181 struct rectangle allocation;
182 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400183
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500184 surface = window_get_surface(launcher->panel->window);
185 cr = cairo_create(surface);
186
187 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500188 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500189 allocation.x++;
190 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400191 }
192
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500193 cairo_set_source_surface(cr, launcher->icon,
194 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400195 cairo_paint(cr);
196
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500197 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400198 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500199 cairo_mask_surface(cr, launcher->icon,
200 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400201 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400202
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500203 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400204}
205
206static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500207set_hex_color(cairo_t *cr, uint32_t color)
208{
209 cairo_set_source_rgba(cr,
210 ((color >> 16) & 0xff) / 255.0,
211 ((color >> 8) & 0xff) / 255.0,
212 ((color >> 0) & 0xff) / 255.0,
213 ((color >> 24) & 0xff) / 255.0);
214}
215
216static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500217panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400218{
219 cairo_surface_t *surface;
220 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500221 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400222
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500223 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400224 cr = cairo_create(surface);
225 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500226 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400227 cairo_paint(cr);
228
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400229 cairo_destroy(cr);
230 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400231}
232
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500233static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500234panel_launcher_enter_handler(struct widget *widget, struct input *input,
235 uint32_t time, int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500236{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500237 struct panel_launcher *launcher = data;
238
239 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500240 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500241
242 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500243}
244
245static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500246panel_launcher_leave_handler(struct widget *widget,
247 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400248{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500249 struct panel_launcher *launcher = data;
250
251 launcher->focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500252 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400253}
254
255static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500256panel_launcher_button_handler(struct widget *widget,
257 struct input *input, uint32_t time,
258 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400259{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500260 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400261
Kristian Høgsberg53880802012-01-09 11:16:50 -0500262 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500263 widget_schedule_redraw(widget);
264 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500265 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500266}
267
268static void
269panel_button_handler(struct widget *widget,
270 struct input *input, uint32_t time,
271 int button, int state, void *data)
272{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500273 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500274
275 if (button == BTN_RIGHT && state)
276 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400277}
278
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100279static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500280panel_resize_handler(struct widget *widget,
281 int32_t width, int32_t height, void *data)
282{
283 struct panel_launcher *launcher;
284 struct panel *panel = data;
285 int x, y, w, h;
286
287 x = 10;
288 y = 16;
289 wl_list_for_each(launcher, &panel->launcher_list, link) {
290 w = cairo_image_surface_get_width(launcher->icon);
291 h = cairo_image_surface_get_height(launcher->icon);
292 widget_set_allocation(launcher->widget,
293 x, y - h / 2, w + 1, h + 1);
294 x += w + 10;
295 }
296}
297
298static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100299panel_configure(void *data,
300 struct desktop_shell *desktop_shell,
301 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200302 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100303 int32_t width, int32_t height)
304{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500305 struct surface *surface = window_get_user_data(window);
306 struct panel *panel = container_of(surface, struct panel, base);
307
308 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100309}
310
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400311static struct panel *
312panel_create(struct display *display)
313{
314 struct panel *panel;
315
316 panel = malloc(sizeof *panel);
317 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400318
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100319 panel->base.configure = panel_configure;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400320 panel->window = window_create(display, 0, 0);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500321 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500322 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400323
324 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400325 window_set_custom(panel->window);
326 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500327
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500328 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
329 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500330 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400331
332 return panel;
333}
334
335static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500336panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400337{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500338 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400339
Kristian Høgsberg53880802012-01-09 11:16:50 -0500340 launcher = malloc(sizeof *launcher);
341 memset(launcher, 0, sizeof *launcher);
342 launcher->icon = cairo_image_surface_create_from_png(icon);
343 launcher->path = strdup(path);
344 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500345 wl_list_insert(panel->launcher_list.prev, &launcher->link);
346
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500347 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500348 widget_set_enter_handler(launcher->widget,
349 panel_launcher_enter_handler);
350 widget_set_leave_handler(launcher->widget,
351 panel_launcher_leave_handler);
352 widget_set_button_handler(launcher->widget,
353 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500354 widget_set_redraw_handler(launcher->widget,
355 panel_launcher_redraw_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400356}
357
358static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500359background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400360{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500361 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400362 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400363 cairo_pattern_t *pattern;
364 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400365 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400366 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500367 struct rectangle allocation;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400368
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500369 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400370
371 cr = cairo_create(surface);
372 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
373 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
374 cairo_paint(cr);
375
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500376 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500377 image = NULL;
378 if (key_background_image)
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500379 image = load_jpeg(key_background_image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500380 if (image) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400381 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500382 sx = (double) cairo_image_surface_get_width(image) /
383 allocation.width;
384 sy = (double) cairo_image_surface_get_height(image) /
385 allocation.height;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400386 cairo_matrix_init_scale(&matrix, sx, sy);
387 cairo_pattern_set_matrix(pattern, &matrix);
388 cairo_set_source(cr, pattern);
389 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400390 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500391 } else {
392 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400393 }
394
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500395 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400396 cairo_destroy(cr);
397 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400398}
399
400static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100401background_configure(void *data,
402 struct desktop_shell *desktop_shell,
403 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200404 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100405 int32_t width, int32_t height)
406{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500407 struct background *background =
408 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100409
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500410 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100411}
412
413static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500414unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200415{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500416 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200417 struct rectangle allocation;
418 cairo_t *cr;
419 cairo_surface_t *surface;
420 cairo_pattern_t *pat;
421 double cx, cy, r, f;
422
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200423 surface = window_get_surface(dialog->window);
424 cr = cairo_create(surface);
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500425 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200426 cairo_rectangle(cr, allocation.x, allocation.y,
427 allocation.width, allocation.height);
428 cairo_clip(cr);
429 cairo_push_group(cr);
430 cairo_translate(cr, allocation.x, allocation.y);
431
432 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
433 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
434 cairo_paint(cr);
435
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500436 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200437 f = 1.0;
438 else
439 f = 0.7;
440
441 cx = allocation.width / 2.0;
442 cy = allocation.height / 2.0;
443 r = (cx < cy ? cx : cy) * 0.4;
444 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
445 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
446 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
447 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
448 cairo_set_source(cr, pat);
449 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
450 cairo_fill(cr);
451
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500452 widget_set_allocation(dialog->button,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200453 allocation.x + cx - r,
454 allocation.y + cy - r, 2 * r, 2 * r);
455 cairo_pattern_destroy(pat);
456
457 cairo_pop_group_to_source(cr);
458 cairo_paint(cr);
459 cairo_destroy(cr);
460
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200461 cairo_surface_destroy(surface);
462}
463
464static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500465unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200466 struct input *input, uint32_t time,
467 int button, int state, void *data)
468{
469 struct unlock_dialog *dialog = data;
470 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200471
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500472 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200473 if (state == 0 && !dialog->closing) {
474 display_defer(desktop->display, &desktop->unlock_task);
475 dialog->closing = 1;
476 }
477 }
478}
479
480static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200481unlock_dialog_keyboard_focus_handler(struct window *window,
482 struct input *device, void *data)
483{
484 window_schedule_redraw(window);
485}
486
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500487static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500488unlock_dialog_widget_enter_handler(struct widget *widget,
489 struct input *input, uint32_t time,
490 int32_t x, int32_t y, void *data)
491{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500492 struct unlock_dialog *dialog = data;
493
494 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500495 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500496
497 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500498}
499
500static void
501unlock_dialog_widget_leave_handler(struct widget *widget,
502 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200503{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500504 struct unlock_dialog *dialog = data;
505
506 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500507 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200508}
509
510static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500511unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200512{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500513 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200514 struct unlock_dialog *dialog;
515
516 dialog = malloc(sizeof *dialog);
517 if (!dialog)
518 return NULL;
519 memset(dialog, 0, sizeof *dialog);
520
521 dialog->window = window_create(display, 260, 230);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500522 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200523 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100524 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200525
526 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200527 window_set_keyboard_focus_handler(dialog->window,
528 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500529 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500530 widget_set_redraw_handler(dialog->widget,
531 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500532 widget_set_enter_handler(dialog->button,
533 unlock_dialog_widget_enter_handler);
534 widget_set_leave_handler(dialog->button,
535 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500536 widget_set_button_handler(dialog->button,
537 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200538
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500539 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200540 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500541
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200542 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200543
544 return dialog;
545}
546
547static void
548unlock_dialog_destroy(struct unlock_dialog *dialog)
549{
550 window_destroy(dialog->window);
551 free(dialog);
552}
553
554static void
555unlock_dialog_finish(struct task *task, uint32_t events)
556{
557 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100558 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200559
560 desktop_shell_unlock(desktop->shell);
561 unlock_dialog_destroy(desktop->unlock_dialog);
562 desktop->unlock_dialog = NULL;
563}
564
565static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400566desktop_shell_configure(void *data,
567 struct desktop_shell *desktop_shell,
568 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200569 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400570 int32_t width, int32_t height)
571{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200572 struct window *window = wl_shell_surface_get_user_data(shell_surface);
573 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400574
Pekka Paalanen068ae942011-11-28 14:11:15 +0200575 s->configure(data, desktop_shell, time, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400576}
577
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200578static void
579desktop_shell_prepare_lock_surface(void *data,
580 struct desktop_shell *desktop_shell)
581{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200582 struct desktop *desktop = data;
583
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200584 if (!key_locking) {
585 desktop_shell_unlock(desktop->shell);
586 return;
587 }
588
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200589 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500590 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200591 desktop->unlock_dialog->desktop = desktop;
592 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200593}
594
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400595static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200596 desktop_shell_configure,
597 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400598};
599
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100600static struct background *
601background_create(struct desktop *desktop)
602{
603 struct background *background;
604
605 background = malloc(sizeof *background);
606 memset(background, 0, sizeof *background);
607
608 background->base.configure = background_configure;
609 background->window = window_create(desktop->display, 0, 0);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500610 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100611 window_set_custom(background->window);
612 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500613 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100614
615 return background;
616}
617
618static void
619create_output(struct desktop *desktop, uint32_t id)
620{
621 struct output *output;
622
623 output = calloc(1, sizeof *output);
624 if (!output)
625 return;
626
627 output->output = wl_display_bind(display_get_display(desktop->display),
628 id, &wl_output_interface);
629
630 wl_list_insert(&desktop->outputs, &output->link);
631}
632
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400633static void
634global_handler(struct wl_display *display, uint32_t id,
635 const char *interface, uint32_t version, void *data)
636{
637 struct desktop *desktop = data;
638
639 if (!strcmp(interface, "desktop_shell")) {
640 desktop->shell =
641 wl_display_bind(display, id, &desktop_shell_interface);
642 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100643 } else if (!strcmp(interface, "wl_output")) {
644 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400645 }
646}
647
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500648static void
649launcher_section_done(void *data)
650{
651 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100652 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500653
654 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
655 fprintf(stderr, "invalid launcher section\n");
656 return;
657 }
658
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100659 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500660 panel_add_launcher(output->panel,
661 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100662
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500663 free(key_launcher_icon);
664 key_launcher_icon = NULL;
665 free(key_launcher_path);
666 key_launcher_path = NULL;
667}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400668
669int main(int argc, char *argv[])
670{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200671 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200672 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100673 struct output *output;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400674
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200675 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100676 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200677
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400678 desktop.display = display_create(&argc, &argv, NULL);
679 if (desktop.display == NULL) {
680 fprintf(stderr, "failed to create display: %m\n");
681 return -1;
682 }
683
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400684 wl_display_add_global_listener(display_get_display(desktop.display),
685 global_handler, &desktop);
686
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100687 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200688 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100689
690 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200691 s = window_get_wl_shell_surface(output->panel->window);
692 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100693
694 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200695 s = window_get_wl_shell_surface(output->background->window);
696 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100697 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400698
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500699 config_file = config_file_path("weston-desktop-shell.ini");
Pekka Paalanen668dd562011-11-15 11:45:40 +0200700 parse_config_file(config_file,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500701 config_sections, ARRAY_LENGTH(config_sections),
702 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200703 free(config_file);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500704
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400705 signal(SIGCHLD, sigchild_handler);
706
707 display_run(desktop.display);
708
709 return 0;
710}