blob: ad1318df31c747dd56132527c2fcabc4cdc0b077 [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;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040045 const char *background_path;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020046 struct unlock_dialog *unlock_dialog;
47 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010048 struct wl_list outputs;
49};
50
51struct surface {
52 void (*configure)(void *data,
53 struct desktop_shell *desktop_shell,
54 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +020055 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010056 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040057};
58
59struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010060 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040061 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050062 struct widget *widget;
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -040063 struct window *menu;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050064 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040065};
66
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010067struct background {
68 struct surface base;
69 struct window *window;
70};
71
72struct output {
73 struct wl_output *output;
74 struct wl_list link;
75
76 struct panel *panel;
77 struct background *background;
78};
79
Kristian Høgsberg53880802012-01-09 11:16:50 -050080struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050081 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040082 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040083 cairo_surface_t *icon;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040084 int pressed;
85 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050086 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040087};
88
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020089struct unlock_dialog {
90 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050091 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050092 struct widget *button;
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;
100static char *key_launcher_icon;
101static char *key_launcher_path;
102static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200103static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500104
105static const struct config_key shell_config_keys[] = {
106 { "background-image", CONFIG_KEY_STRING, &key_background_image },
107 { "panel-color", CONFIG_KEY_INTEGER, &key_panel_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200108 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500109};
110
111static const struct config_key launcher_config_keys[] = {
112 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
113 { "path", CONFIG_KEY_STRING, &key_launcher_path },
114};
115
116static const struct config_section config_sections[] = {
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500117 { "desktop-shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500118 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
119 { "launcher",
120 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
121 launcher_section_done }
122};
123
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400124static void
125sigchild_handler(int s)
126{
127 int status;
128 pid_t pid;
129
130 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
131 fprintf(stderr, "child %d exited\n", pid);
132}
133
134static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500135show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400136{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500137 int32_t x, y;
138 static const char *entries[] = {
139 "Roy", "Pris", "Leon", "Zhora"
140 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400141
142 input_get_position(input, &x, &y);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500143 panel->menu = window_create_menu(window_get_display(panel->window),
144 input, time, panel->window,
Kristian Høgsberg4f7dcd62012-01-06 21:59:05 -0500145 x - 10, y - 10, NULL, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400146
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500147 window_schedule_redraw(panel->menu);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400148}
149
150static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500151panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400152{
153 pid_t pid;
154
155 pid = fork();
156 if (pid < 0) {
157 fprintf(stderr, "fork failed: %m\n");
158 return;
159 }
160
161 if (pid)
162 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100163
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500164 if (execl(widget->path, widget->path, NULL) < 0) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400165 fprintf(stderr, "execl failed: %m\n");
166 exit(1);
167 }
168}
169
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400170static void
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500171panel_draw_launcher(struct panel_launcher *launcher, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400172{
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400173 cairo_t *cr = data;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400174 int x, y, width, height;
175 double dx, dy;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400176
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500177 width = cairo_image_surface_get_width(launcher->icon);
178 height = cairo_image_surface_get_height(launcher->icon);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400179 x = 0;
180 y = -height / 2;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500181 if (launcher->pressed) {
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400182 x++;
183 y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400184 }
185
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400186 dx = x;
187 dy = y;
188 cairo_user_to_device(cr, &dx, &dy);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500189 widget_set_allocation(launcher->widget, dx, dy, width, height);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400190
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500191 cairo_set_source_surface(cr, launcher->icon, x, y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400192 cairo_paint(cr);
193
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500194 if (window_get_focus_widget(launcher->panel->window) ==
195 launcher->widget) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400196 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500197 cairo_mask_surface(cr, launcher->icon, x, y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400198 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400199
200 cairo_translate(cr, width + 10, 0);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400201}
202
203static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500204set_hex_color(cairo_t *cr, uint32_t color)
205{
206 cairo_set_source_rgba(cr,
207 ((color >> 16) & 0xff) / 255.0,
208 ((color >> 8) & 0xff) / 255.0,
209 ((color >> 0) & 0xff) / 255.0,
210 ((color >> 24) & 0xff) / 255.0);
211}
212
213static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400214panel_redraw_handler(struct window *window, void *data)
215{
216 cairo_surface_t *surface;
217 cairo_t *cr;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500218 struct panel_launcher *launcher;
219 struct panel *panel = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400220
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400221 surface = window_get_surface(window);
222 cr = cairo_create(surface);
223 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500224 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400225 cairo_paint(cr);
226
227 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400228 cairo_translate(cr, 10, 32 / 2);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500229 wl_list_for_each(launcher, &panel->launcher_list, link)
230 panel_draw_launcher(launcher, cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400231
232 cairo_destroy(cr);
233 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400234}
235
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500236static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500237panel_launcher_enter_handler(struct widget *widget, struct input *input,
238 uint32_t time, int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500239{
240 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øgsberg9a13dab2012-01-08 15:18:19 -0500249 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400250}
251
252static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500253panel_launcher_button_handler(struct widget *widget,
254 struct input *input, uint32_t time,
255 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400256{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500257 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400258
Kristian Høgsberg53880802012-01-09 11:16:50 -0500259 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500260 widget_schedule_redraw(widget);
261 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500262 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500263}
264
265static void
266panel_button_handler(struct widget *widget,
267 struct input *input, uint32_t time,
268 int button, int state, void *data)
269{
270 struct window *window = data;
271 struct panel *panel = window_get_user_data(window);
272
273 if (button == BTN_RIGHT && state)
274 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400275}
276
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100277static void
278panel_configure(void *data,
279 struct desktop_shell *desktop_shell,
280 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200281 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100282 int32_t width, int32_t height)
283{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200284 window_set_child_size(window, width, 32);
285 window_schedule_redraw(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100286}
287
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400288static struct panel *
289panel_create(struct display *display)
290{
291 struct panel *panel;
292
293 panel = malloc(sizeof *panel);
294 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400295
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100296 panel->base.configure = panel_configure;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400297 panel->window = window_create(display, 0, 0);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500298 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400299
300 window_set_title(panel->window, "panel");
301 window_set_decoration(panel->window, 0);
302 window_set_redraw_handler(panel->window, panel_redraw_handler);
303 window_set_custom(panel->window);
304 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500305
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500306 widget_set_button_handler(panel->widget, panel_button_handler);
307 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400308
309 return panel;
310}
311
312static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500313panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400314{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500315 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400316
Kristian Høgsberg53880802012-01-09 11:16:50 -0500317 launcher = malloc(sizeof *launcher);
318 memset(launcher, 0, sizeof *launcher);
319 launcher->icon = cairo_image_surface_create_from_png(icon);
320 launcher->path = strdup(path);
321 launcher->panel = panel;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500322
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500323 wl_list_insert(panel->launcher_list.prev, &launcher->link);
324
Kristian Høgsberg53880802012-01-09 11:16:50 -0500325 launcher->widget = window_add_widget(panel->window, launcher);
326 widget_set_enter_handler(launcher->widget,
327 panel_launcher_enter_handler);
328 widget_set_leave_handler(launcher->widget,
329 panel_launcher_leave_handler);
330 widget_set_button_handler(launcher->widget,
331 panel_launcher_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400332}
333
334static void
335background_draw(struct window *window, int width, int height, const char *path)
336{
337 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400338 cairo_pattern_t *pattern;
339 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400340 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400341 double sx, sy;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400342
343 window_set_child_size(window, width, height);
Kristian Høgsberg5d129902012-01-10 10:49:41 -0500344 window_create_surface(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400345 surface = window_get_surface(window);
346
347 cr = cairo_create(surface);
348 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
349 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
350 cairo_paint(cr);
351
352 if (path) {
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400353 image = load_jpeg(path);
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400354 pattern = cairo_pattern_create_for_surface(image);
355 sx = (double) cairo_image_surface_get_width(image) / width;
356 sy = (double) cairo_image_surface_get_height(image) / height;
357 cairo_matrix_init_scale(&matrix, sx, sy);
358 cairo_pattern_set_matrix(pattern, &matrix);
359 cairo_set_source(cr, pattern);
360 cairo_pattern_destroy (pattern);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400361 cairo_paint(cr);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400362 cairo_surface_destroy(image);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400363 }
364
365 cairo_destroy(cr);
366 cairo_surface_destroy(surface);
367 window_flush(window);
368}
369
370static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100371background_configure(void *data,
372 struct desktop_shell *desktop_shell,
373 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200374 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100375 int32_t width, int32_t height)
376{
377 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100378
Pekka Paalanen068ae942011-11-28 14:11:15 +0200379 background_draw(window, width, height, desktop->background_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100380}
381
382static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200383unlock_dialog_draw(struct unlock_dialog *dialog)
384{
385 struct rectangle allocation;
386 cairo_t *cr;
387 cairo_surface_t *surface;
388 cairo_pattern_t *pat;
389 double cx, cy, r, f;
390
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200391 surface = window_get_surface(dialog->window);
392 cr = cairo_create(surface);
393 window_get_child_allocation(dialog->window, &allocation);
394 cairo_rectangle(cr, allocation.x, allocation.y,
395 allocation.width, allocation.height);
396 cairo_clip(cr);
397 cairo_push_group(cr);
398 cairo_translate(cr, allocation.x, allocation.y);
399
400 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
401 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
402 cairo_paint(cr);
403
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500404 if (window_get_focus_widget(dialog->window) == dialog->button)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200405 f = 1.0;
406 else
407 f = 0.7;
408
409 cx = allocation.width / 2.0;
410 cy = allocation.height / 2.0;
411 r = (cx < cy ? cx : cy) * 0.4;
412 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
413 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
414 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
415 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
416 cairo_set_source(cr, pat);
417 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
418 cairo_fill(cr);
419
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500420 widget_set_allocation(dialog->button,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200421 allocation.x + cx - r,
422 allocation.y + cy - r, 2 * r, 2 * r);
423 cairo_pattern_destroy(pat);
424
425 cairo_pop_group_to_source(cr);
426 cairo_paint(cr);
427 cairo_destroy(cr);
428
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200429 cairo_surface_destroy(surface);
430}
431
432static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500433unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200434 struct input *input, uint32_t time,
435 int button, int state, void *data)
436{
437 struct unlock_dialog *dialog = data;
438 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200439
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500440 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200441 if (state == 0 && !dialog->closing) {
442 display_defer(desktop->display, &desktop->unlock_task);
443 dialog->closing = 1;
444 }
445 }
446}
447
448static void
449unlock_dialog_redraw_handler(struct window *window, void *data)
450{
451 struct unlock_dialog *dialog = data;
452
453 unlock_dialog_draw(dialog);
454}
455
456static void
457unlock_dialog_keyboard_focus_handler(struct window *window,
458 struct input *device, void *data)
459{
460 window_schedule_redraw(window);
461}
462
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500463static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500464unlock_dialog_widget_enter_handler(struct widget *widget,
465 struct input *input, uint32_t time,
466 int32_t x, int32_t y, void *data)
467{
468 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500469
470 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500471}
472
473static void
474unlock_dialog_widget_leave_handler(struct widget *widget,
475 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200476{
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500477 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200478}
479
480static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500481unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200482{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500483 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200484 struct unlock_dialog *dialog;
485
486 dialog = malloc(sizeof *dialog);
487 if (!dialog)
488 return NULL;
489 memset(dialog, 0, sizeof *dialog);
490
491 dialog->window = window_create(display, 260, 230);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500492 dialog->widget = window_add_widget(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200493 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100494 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200495
496 window_set_user_data(dialog->window, dialog);
497 window_set_redraw_handler(dialog->window, unlock_dialog_redraw_handler);
498 window_set_keyboard_focus_handler(dialog->window,
499 unlock_dialog_keyboard_focus_handler);
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500500 dialog->button = window_add_widget(dialog->window, NULL);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500501 widget_set_enter_handler(dialog->button,
502 unlock_dialog_widget_enter_handler);
503 widget_set_leave_handler(dialog->button,
504 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500505 widget_set_button_handler(dialog->button,
506 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200507
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500508 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200509 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500510
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200511 unlock_dialog_draw(dialog);
512
513 return dialog;
514}
515
516static void
517unlock_dialog_destroy(struct unlock_dialog *dialog)
518{
519 window_destroy(dialog->window);
520 free(dialog);
521}
522
523static void
524unlock_dialog_finish(struct task *task, uint32_t events)
525{
526 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100527 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200528
529 desktop_shell_unlock(desktop->shell);
530 unlock_dialog_destroy(desktop->unlock_dialog);
531 desktop->unlock_dialog = NULL;
532}
533
534static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400535desktop_shell_configure(void *data,
536 struct desktop_shell *desktop_shell,
537 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200538 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400539 int32_t width, int32_t height)
540{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200541 struct window *window = wl_shell_surface_get_user_data(shell_surface);
542 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400543
Pekka Paalanen068ae942011-11-28 14:11:15 +0200544 s->configure(data, desktop_shell, time, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400545}
546
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200547static void
548desktop_shell_prepare_lock_surface(void *data,
549 struct desktop_shell *desktop_shell)
550{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200551 struct desktop *desktop = data;
552
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200553 if (!key_locking) {
554 desktop_shell_unlock(desktop->shell);
555 return;
556 }
557
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200558 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500559 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200560 desktop->unlock_dialog->desktop = desktop;
561 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200562}
563
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400564static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200565 desktop_shell_configure,
566 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400567};
568
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100569static struct background *
570background_create(struct desktop *desktop)
571{
572 struct background *background;
573
574 background = malloc(sizeof *background);
575 memset(background, 0, sizeof *background);
576
577 background->base.configure = background_configure;
578 background->window = window_create(desktop->display, 0, 0);
579 window_set_decoration(background->window, 0);
580 window_set_custom(background->window);
581 window_set_user_data(background->window, background);
582
583 return background;
584}
585
586static void
587create_output(struct desktop *desktop, uint32_t id)
588{
589 struct output *output;
590
591 output = calloc(1, sizeof *output);
592 if (!output)
593 return;
594
595 output->output = wl_display_bind(display_get_display(desktop->display),
596 id, &wl_output_interface);
597
598 wl_list_insert(&desktop->outputs, &output->link);
599}
600
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400601static void
602global_handler(struct wl_display *display, uint32_t id,
603 const char *interface, uint32_t version, void *data)
604{
605 struct desktop *desktop = data;
606
607 if (!strcmp(interface, "desktop_shell")) {
608 desktop->shell =
609 wl_display_bind(display, id, &desktop_shell_interface);
610 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100611 } else if (!strcmp(interface, "wl_output")) {
612 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400613 }
614}
615
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500616static void
617launcher_section_done(void *data)
618{
619 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100620 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500621
622 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
623 fprintf(stderr, "invalid launcher section\n");
624 return;
625 }
626
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100627 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500628 panel_add_launcher(output->panel,
629 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100630
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500631 free(key_launcher_icon);
632 key_launcher_icon = NULL;
633 free(key_launcher_path);
634 key_launcher_path = NULL;
635}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400636
637int main(int argc, char *argv[])
638{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200639 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200640 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100641 struct output *output;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400642
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200643 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100644 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200645
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400646 desktop.display = display_create(&argc, &argv, NULL);
647 if (desktop.display == NULL) {
648 fprintf(stderr, "failed to create display: %m\n");
649 return -1;
650 }
651
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400652 wl_display_add_global_listener(display_get_display(desktop.display),
653 global_handler, &desktop);
654
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100655 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200656 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100657
658 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200659 s = window_get_wl_shell_surface(output->panel->window);
660 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100661
662 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200663 s = window_get_wl_shell_surface(output->background->window);
664 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100665 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400666
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500667 config_file = config_file_path("weston-desktop-shell.ini");
Pekka Paalanen668dd562011-11-15 11:45:40 +0200668 parse_config_file(config_file,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500669 config_sections, ARRAY_LENGTH(config_sections),
670 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200671 free(config_file);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500672
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500673 desktop.background_path = key_background_image;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400674
675 signal(SIGCHLD, sigchild_handler);
676
677 display_run(desktop.display);
678
679 return 0;
680}