blob: 4303ad003c764a8dad12b05b0ed9d1c7da6a87c3 [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øgsbergbcee9a42011-10-12 00:36:16 -040062 struct window *menu;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050063 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040064};
65
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010066struct background {
67 struct surface base;
68 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050069 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010070};
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øgsbergb6323512012-01-11 00:04:42 -050084 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040085 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;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050093 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020094 int closing;
95
96 struct desktop *desktop;
97};
98
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -050099static char *key_background_image;
100static uint32_t key_panel_color;
101static 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 },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200109 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500110};
111
112static const struct config_key launcher_config_keys[] = {
113 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
114 { "path", CONFIG_KEY_STRING, &key_launcher_path },
115};
116
117static const struct config_section config_sections[] = {
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500118 { "desktop-shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500119 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
120 { "launcher",
121 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
122 launcher_section_done }
123};
124
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400125static void
126sigchild_handler(int s)
127{
128 int status;
129 pid_t pid;
130
131 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
132 fprintf(stderr, "child %d exited\n", pid);
133}
134
135static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500136show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400137{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500138 int32_t x, y;
139 static const char *entries[] = {
140 "Roy", "Pris", "Leon", "Zhora"
141 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400142
143 input_get_position(input, &x, &y);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500144 panel->menu = window_create_menu(window_get_display(panel->window),
145 input, time, panel->window,
Kristian Høgsberg4f7dcd62012-01-06 21:59:05 -0500146 x - 10, y - 10, NULL, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400147
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500148 window_schedule_redraw(panel->menu);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400149}
150
151static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500152panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400153{
154 pid_t pid;
155
156 pid = fork();
157 if (pid < 0) {
158 fprintf(stderr, "fork failed: %m\n");
159 return;
160 }
161
162 if (pid)
163 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100164
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500165 if (execl(widget->path, widget->path, NULL) < 0) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400166 fprintf(stderr, "execl failed: %m\n");
167 exit(1);
168 }
169}
170
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400171static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500172panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400173{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500174 struct panel_launcher *launcher = data;
175 cairo_surface_t *surface;
176 struct rectangle allocation;
177 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400178
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500179 surface = window_get_surface(launcher->panel->window);
180 cr = cairo_create(surface);
181
182 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500183 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500184 allocation.x++;
185 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400186 }
187
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500188 cairo_set_source_surface(cr, launcher->icon,
189 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400190 cairo_paint(cr);
191
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500192 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400193 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500194 cairo_mask_surface(cr, launcher->icon,
195 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400196 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400197
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500198 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400199}
200
201static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500202set_hex_color(cairo_t *cr, uint32_t color)
203{
204 cairo_set_source_rgba(cr,
205 ((color >> 16) & 0xff) / 255.0,
206 ((color >> 8) & 0xff) / 255.0,
207 ((color >> 0) & 0xff) / 255.0,
208 ((color >> 24) & 0xff) / 255.0);
209}
210
211static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500212panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400213{
214 cairo_surface_t *surface;
215 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500216 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400217
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500218 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400219 cr = cairo_create(surface);
220 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500221 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400222 cairo_paint(cr);
223
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400224 cairo_destroy(cr);
225 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400226}
227
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500228static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500229panel_launcher_enter_handler(struct widget *widget, struct input *input,
230 uint32_t time, int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500231{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500232 struct panel_launcher *launcher = data;
233
234 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500235 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500236
237 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500238}
239
240static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500241panel_launcher_leave_handler(struct widget *widget,
242 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400243{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500244 struct panel_launcher *launcher = data;
245
246 launcher->focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500247 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400248}
249
250static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500251panel_launcher_button_handler(struct widget *widget,
252 struct input *input, uint32_t time,
253 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400254{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500255 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400256
Kristian Høgsberg53880802012-01-09 11:16:50 -0500257 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500258 widget_schedule_redraw(widget);
259 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500260 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500261}
262
263static void
264panel_button_handler(struct widget *widget,
265 struct input *input, uint32_t time,
266 int button, int state, void *data)
267{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500268 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500269
270 if (button == BTN_RIGHT && state)
271 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400272}
273
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100274static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500275panel_resize_handler(struct widget *widget,
276 int32_t width, int32_t height, void *data)
277{
278 struct panel_launcher *launcher;
279 struct panel *panel = data;
280 int x, y, w, h;
281
282 x = 10;
283 y = 16;
284 wl_list_for_each(launcher, &panel->launcher_list, link) {
285 w = cairo_image_surface_get_width(launcher->icon);
286 h = cairo_image_surface_get_height(launcher->icon);
287 widget_set_allocation(launcher->widget,
288 x, y - h / 2, w + 1, h + 1);
289 x += w + 10;
290 }
291}
292
293static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100294panel_configure(void *data,
295 struct desktop_shell *desktop_shell,
296 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200297 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100298 int32_t width, int32_t height)
299{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500300 struct surface *surface = window_get_user_data(window);
301 struct panel *panel = container_of(surface, struct panel, base);
302
303 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100304}
305
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400306static struct panel *
307panel_create(struct display *display)
308{
309 struct panel *panel;
310
311 panel = malloc(sizeof *panel);
312 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400313
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100314 panel->base.configure = panel_configure;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400315 panel->window = window_create(display, 0, 0);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500316 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500317 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400318
319 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400320 window_set_custom(panel->window);
321 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500322
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500323 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
324 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500325 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400326
327 return panel;
328}
329
330static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500331panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400332{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500333 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400334
Kristian Høgsberg53880802012-01-09 11:16:50 -0500335 launcher = malloc(sizeof *launcher);
336 memset(launcher, 0, sizeof *launcher);
337 launcher->icon = cairo_image_surface_create_from_png(icon);
338 launcher->path = strdup(path);
339 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500340 wl_list_insert(panel->launcher_list.prev, &launcher->link);
341
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500342 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500343 widget_set_enter_handler(launcher->widget,
344 panel_launcher_enter_handler);
345 widget_set_leave_handler(launcher->widget,
346 panel_launcher_leave_handler);
347 widget_set_button_handler(launcher->widget,
348 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500349 widget_set_redraw_handler(launcher->widget,
350 panel_launcher_redraw_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400351}
352
353static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500354background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400355{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500356 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400357 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400358 cairo_pattern_t *pattern;
359 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400360 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400361 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500362 struct rectangle allocation;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400363
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500364 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400365
366 cr = cairo_create(surface);
367 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
368 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
369 cairo_paint(cr);
370
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500371 widget_get_allocation(widget, &allocation);
372 if (key_background_image) {
373 image = load_jpeg(key_background_image);
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400374 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500375 sx = (double) cairo_image_surface_get_width(image) /
376 allocation.width;
377 sy = (double) cairo_image_surface_get_height(image) /
378 allocation.height;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400379 cairo_matrix_init_scale(&matrix, sx, sy);
380 cairo_pattern_set_matrix(pattern, &matrix);
381 cairo_set_source(cr, pattern);
382 cairo_pattern_destroy (pattern);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400383 cairo_paint(cr);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400384 cairo_surface_destroy(image);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400385 }
386
387 cairo_destroy(cr);
388 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400389}
390
391static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100392background_configure(void *data,
393 struct desktop_shell *desktop_shell,
394 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200395 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100396 int32_t width, int32_t height)
397{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500398 struct background *background =
399 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100400
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500401 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100402}
403
404static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500405unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200406{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500407 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200408 struct rectangle allocation;
409 cairo_t *cr;
410 cairo_surface_t *surface;
411 cairo_pattern_t *pat;
412 double cx, cy, r, f;
413
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200414 surface = window_get_surface(dialog->window);
415 cr = cairo_create(surface);
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500416 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200417 cairo_rectangle(cr, allocation.x, allocation.y,
418 allocation.width, allocation.height);
419 cairo_clip(cr);
420 cairo_push_group(cr);
421 cairo_translate(cr, allocation.x, allocation.y);
422
423 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
424 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
425 cairo_paint(cr);
426
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500427 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200428 f = 1.0;
429 else
430 f = 0.7;
431
432 cx = allocation.width / 2.0;
433 cy = allocation.height / 2.0;
434 r = (cx < cy ? cx : cy) * 0.4;
435 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
436 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
437 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
438 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
439 cairo_set_source(cr, pat);
440 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
441 cairo_fill(cr);
442
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500443 widget_set_allocation(dialog->button,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200444 allocation.x + cx - r,
445 allocation.y + cy - r, 2 * r, 2 * r);
446 cairo_pattern_destroy(pat);
447
448 cairo_pop_group_to_source(cr);
449 cairo_paint(cr);
450 cairo_destroy(cr);
451
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200452 cairo_surface_destroy(surface);
453}
454
455static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500456unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200457 struct input *input, uint32_t time,
458 int button, int state, void *data)
459{
460 struct unlock_dialog *dialog = data;
461 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200462
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500463 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200464 if (state == 0 && !dialog->closing) {
465 display_defer(desktop->display, &desktop->unlock_task);
466 dialog->closing = 1;
467 }
468 }
469}
470
471static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200472unlock_dialog_keyboard_focus_handler(struct window *window,
473 struct input *device, void *data)
474{
475 window_schedule_redraw(window);
476}
477
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500478static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500479unlock_dialog_widget_enter_handler(struct widget *widget,
480 struct input *input, uint32_t time,
481 int32_t x, int32_t y, void *data)
482{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500483 struct unlock_dialog *dialog = data;
484
485 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500486 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500487
488 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500489}
490
491static void
492unlock_dialog_widget_leave_handler(struct widget *widget,
493 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200494{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500495 struct unlock_dialog *dialog = data;
496
497 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500498 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200499}
500
501static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500502unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200503{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500504 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200505 struct unlock_dialog *dialog;
506
507 dialog = malloc(sizeof *dialog);
508 if (!dialog)
509 return NULL;
510 memset(dialog, 0, sizeof *dialog);
511
512 dialog->window = window_create(display, 260, 230);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500513 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200514 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100515 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200516
517 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200518 window_set_keyboard_focus_handler(dialog->window,
519 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500520 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500521 widget_set_redraw_handler(dialog->widget,
522 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500523 widget_set_enter_handler(dialog->button,
524 unlock_dialog_widget_enter_handler);
525 widget_set_leave_handler(dialog->button,
526 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500527 widget_set_button_handler(dialog->button,
528 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200529
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500530 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200531 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500532
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500533 window_schedule_redraw(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200534
535 return dialog;
536}
537
538static void
539unlock_dialog_destroy(struct unlock_dialog *dialog)
540{
541 window_destroy(dialog->window);
542 free(dialog);
543}
544
545static void
546unlock_dialog_finish(struct task *task, uint32_t events)
547{
548 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100549 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200550
551 desktop_shell_unlock(desktop->shell);
552 unlock_dialog_destroy(desktop->unlock_dialog);
553 desktop->unlock_dialog = NULL;
554}
555
556static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400557desktop_shell_configure(void *data,
558 struct desktop_shell *desktop_shell,
559 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200560 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400561 int32_t width, int32_t height)
562{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200563 struct window *window = wl_shell_surface_get_user_data(shell_surface);
564 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400565
Pekka Paalanen068ae942011-11-28 14:11:15 +0200566 s->configure(data, desktop_shell, time, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400567}
568
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200569static void
570desktop_shell_prepare_lock_surface(void *data,
571 struct desktop_shell *desktop_shell)
572{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200573 struct desktop *desktop = data;
574
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200575 if (!key_locking) {
576 desktop_shell_unlock(desktop->shell);
577 return;
578 }
579
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200580 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500581 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200582 desktop->unlock_dialog->desktop = desktop;
583 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200584}
585
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400586static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200587 desktop_shell_configure,
588 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400589};
590
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100591static struct background *
592background_create(struct desktop *desktop)
593{
594 struct background *background;
595
596 background = malloc(sizeof *background);
597 memset(background, 0, sizeof *background);
598
599 background->base.configure = background_configure;
600 background->window = window_create(desktop->display, 0, 0);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500601 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100602 window_set_custom(background->window);
603 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500604 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100605
606 return background;
607}
608
609static void
610create_output(struct desktop *desktop, uint32_t id)
611{
612 struct output *output;
613
614 output = calloc(1, sizeof *output);
615 if (!output)
616 return;
617
618 output->output = wl_display_bind(display_get_display(desktop->display),
619 id, &wl_output_interface);
620
621 wl_list_insert(&desktop->outputs, &output->link);
622}
623
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400624static void
625global_handler(struct wl_display *display, uint32_t id,
626 const char *interface, uint32_t version, void *data)
627{
628 struct desktop *desktop = data;
629
630 if (!strcmp(interface, "desktop_shell")) {
631 desktop->shell =
632 wl_display_bind(display, id, &desktop_shell_interface);
633 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100634 } else if (!strcmp(interface, "wl_output")) {
635 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400636 }
637}
638
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500639static void
640launcher_section_done(void *data)
641{
642 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100643 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500644
645 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
646 fprintf(stderr, "invalid launcher section\n");
647 return;
648 }
649
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100650 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500651 panel_add_launcher(output->panel,
652 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100653
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500654 free(key_launcher_icon);
655 key_launcher_icon = NULL;
656 free(key_launcher_path);
657 key_launcher_path = NULL;
658}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400659
660int main(int argc, char *argv[])
661{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200662 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200663 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100664 struct output *output;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400665
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200666 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100667 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200668
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400669 desktop.display = display_create(&argc, &argv, NULL);
670 if (desktop.display == NULL) {
671 fprintf(stderr, "failed to create display: %m\n");
672 return -1;
673 }
674
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400675 wl_display_add_global_listener(display_get_display(desktop.display),
676 global_handler, &desktop);
677
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100678 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200679 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100680
681 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200682 s = window_get_wl_shell_surface(output->panel->window);
683 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100684
685 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200686 s = window_get_wl_shell_surface(output->background->window);
687 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100688 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400689
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500690 config_file = config_file_path("weston-desktop-shell.ini");
Pekka Paalanen668dd562011-11-15 11:45:40 +0200691 parse_config_file(config_file,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500692 config_sections, ARRAY_LENGTH(config_sections),
693 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200694 free(config_file);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500695
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400696 signal(SIGCHLD, sigchild_handler);
697
698 display_run(desktop.display);
699
700 return 0;
701}