blob: 642e92a8c327e8dc523fe544774271ddee3af35b [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;
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);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200143 window_show_menu(window_get_display(panel->window),
144 input, time, panel->window,
145 x - 10, y - 10, NULL, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400146}
147
148static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500149panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400150{
151 pid_t pid;
152
153 pid = fork();
154 if (pid < 0) {
155 fprintf(stderr, "fork failed: %m\n");
156 return;
157 }
158
159 if (pid)
160 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100161
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500162 if (execl(widget->path, widget->path, NULL) < 0) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400163 fprintf(stderr, "execl failed: %m\n");
164 exit(1);
165 }
166}
167
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400168static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500169panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400170{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500171 struct panel_launcher *launcher = data;
172 cairo_surface_t *surface;
173 struct rectangle allocation;
174 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400175
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500176 surface = window_get_surface(launcher->panel->window);
177 cr = cairo_create(surface);
178
179 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500180 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500181 allocation.x++;
182 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400183 }
184
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500185 cairo_set_source_surface(cr, launcher->icon,
186 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400187 cairo_paint(cr);
188
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500189 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400190 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500191 cairo_mask_surface(cr, launcher->icon,
192 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400193 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400194
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500195 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400196}
197
198static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500199set_hex_color(cairo_t *cr, uint32_t color)
200{
201 cairo_set_source_rgba(cr,
202 ((color >> 16) & 0xff) / 255.0,
203 ((color >> 8) & 0xff) / 255.0,
204 ((color >> 0) & 0xff) / 255.0,
205 ((color >> 24) & 0xff) / 255.0);
206}
207
208static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500209panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400210{
211 cairo_surface_t *surface;
212 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500213 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400214
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500215 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400216 cr = cairo_create(surface);
217 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500218 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400219 cairo_paint(cr);
220
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400221 cairo_destroy(cr);
222 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400223}
224
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500225static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500226panel_launcher_enter_handler(struct widget *widget, struct input *input,
227 uint32_t time, int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500228{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500229 struct panel_launcher *launcher = data;
230
231 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500232 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500233
234 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500235}
236
237static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500238panel_launcher_leave_handler(struct widget *widget,
239 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400240{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500241 struct panel_launcher *launcher = data;
242
243 launcher->focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500244 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400245}
246
247static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500248panel_launcher_button_handler(struct widget *widget,
249 struct input *input, uint32_t time,
250 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400251{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500252 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400253
Kristian Høgsberg53880802012-01-09 11:16:50 -0500254 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500255 widget_schedule_redraw(widget);
256 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500257 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500258}
259
260static void
261panel_button_handler(struct widget *widget,
262 struct input *input, uint32_t time,
263 int button, int state, void *data)
264{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500265 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500266
267 if (button == BTN_RIGHT && state)
268 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400269}
270
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100271static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500272panel_resize_handler(struct widget *widget,
273 int32_t width, int32_t height, void *data)
274{
275 struct panel_launcher *launcher;
276 struct panel *panel = data;
277 int x, y, w, h;
278
279 x = 10;
280 y = 16;
281 wl_list_for_each(launcher, &panel->launcher_list, link) {
282 w = cairo_image_surface_get_width(launcher->icon);
283 h = cairo_image_surface_get_height(launcher->icon);
284 widget_set_allocation(launcher->widget,
285 x, y - h / 2, w + 1, h + 1);
286 x += w + 10;
287 }
288}
289
290static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100291panel_configure(void *data,
292 struct desktop_shell *desktop_shell,
293 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200294 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100295 int32_t width, int32_t height)
296{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500297 struct surface *surface = window_get_user_data(window);
298 struct panel *panel = container_of(surface, struct panel, base);
299
300 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100301}
302
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400303static struct panel *
304panel_create(struct display *display)
305{
306 struct panel *panel;
307
308 panel = malloc(sizeof *panel);
309 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400310
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100311 panel->base.configure = panel_configure;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400312 panel->window = window_create(display, 0, 0);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500313 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500314 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400315
316 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400317 window_set_custom(panel->window);
318 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500319
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500320 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
321 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500322 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400323
324 return panel;
325}
326
327static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500328panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400329{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500330 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400331
Kristian Høgsberg53880802012-01-09 11:16:50 -0500332 launcher = malloc(sizeof *launcher);
333 memset(launcher, 0, sizeof *launcher);
334 launcher->icon = cairo_image_surface_create_from_png(icon);
335 launcher->path = strdup(path);
336 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500337 wl_list_insert(panel->launcher_list.prev, &launcher->link);
338
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500339 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500340 widget_set_enter_handler(launcher->widget,
341 panel_launcher_enter_handler);
342 widget_set_leave_handler(launcher->widget,
343 panel_launcher_leave_handler);
344 widget_set_button_handler(launcher->widget,
345 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500346 widget_set_redraw_handler(launcher->widget,
347 panel_launcher_redraw_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400348}
349
350static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500351background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400352{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500353 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400354 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400355 cairo_pattern_t *pattern;
356 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400357 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400358 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500359 struct rectangle allocation;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400360
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500361 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400362
363 cr = cairo_create(surface);
364 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
365 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
366 cairo_paint(cr);
367
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500368 widget_get_allocation(widget, &allocation);
369 if (key_background_image) {
370 image = load_jpeg(key_background_image);
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400371 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500372 sx = (double) cairo_image_surface_get_width(image) /
373 allocation.width;
374 sy = (double) cairo_image_surface_get_height(image) /
375 allocation.height;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400376 cairo_matrix_init_scale(&matrix, sx, sy);
377 cairo_pattern_set_matrix(pattern, &matrix);
378 cairo_set_source(cr, pattern);
379 cairo_pattern_destroy (pattern);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400380 cairo_paint(cr);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400381 cairo_surface_destroy(image);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400382 }
383
384 cairo_destroy(cr);
385 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400386}
387
388static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100389background_configure(void *data,
390 struct desktop_shell *desktop_shell,
391 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200392 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100393 int32_t width, int32_t height)
394{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500395 struct background *background =
396 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100397
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500398 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100399}
400
401static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500402unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200403{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500404 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200405 struct rectangle allocation;
406 cairo_t *cr;
407 cairo_surface_t *surface;
408 cairo_pattern_t *pat;
409 double cx, cy, r, f;
410
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200411 surface = window_get_surface(dialog->window);
412 cr = cairo_create(surface);
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500413 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200414 cairo_rectangle(cr, allocation.x, allocation.y,
415 allocation.width, allocation.height);
416 cairo_clip(cr);
417 cairo_push_group(cr);
418 cairo_translate(cr, allocation.x, allocation.y);
419
420 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
421 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
422 cairo_paint(cr);
423
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500424 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200425 f = 1.0;
426 else
427 f = 0.7;
428
429 cx = allocation.width / 2.0;
430 cy = allocation.height / 2.0;
431 r = (cx < cy ? cx : cy) * 0.4;
432 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
433 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
434 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
435 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
436 cairo_set_source(cr, pat);
437 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
438 cairo_fill(cr);
439
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500440 widget_set_allocation(dialog->button,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200441 allocation.x + cx - r,
442 allocation.y + cy - r, 2 * r, 2 * r);
443 cairo_pattern_destroy(pat);
444
445 cairo_pop_group_to_source(cr);
446 cairo_paint(cr);
447 cairo_destroy(cr);
448
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200449 cairo_surface_destroy(surface);
450}
451
452static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500453unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200454 struct input *input, uint32_t time,
455 int button, int state, void *data)
456{
457 struct unlock_dialog *dialog = data;
458 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200459
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500460 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200461 if (state == 0 && !dialog->closing) {
462 display_defer(desktop->display, &desktop->unlock_task);
463 dialog->closing = 1;
464 }
465 }
466}
467
468static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200469unlock_dialog_keyboard_focus_handler(struct window *window,
470 struct input *device, void *data)
471{
472 window_schedule_redraw(window);
473}
474
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500475static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500476unlock_dialog_widget_enter_handler(struct widget *widget,
477 struct input *input, uint32_t time,
478 int32_t x, int32_t y, void *data)
479{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500480 struct unlock_dialog *dialog = data;
481
482 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500483 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500484
485 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500486}
487
488static void
489unlock_dialog_widget_leave_handler(struct widget *widget,
490 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200491{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500492 struct unlock_dialog *dialog = data;
493
494 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500495 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200496}
497
498static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500499unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200500{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500501 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200502 struct unlock_dialog *dialog;
503
504 dialog = malloc(sizeof *dialog);
505 if (!dialog)
506 return NULL;
507 memset(dialog, 0, sizeof *dialog);
508
509 dialog->window = window_create(display, 260, 230);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500510 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200511 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100512 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200513
514 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200515 window_set_keyboard_focus_handler(dialog->window,
516 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500517 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500518 widget_set_redraw_handler(dialog->widget,
519 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500520 widget_set_enter_handler(dialog->button,
521 unlock_dialog_widget_enter_handler);
522 widget_set_leave_handler(dialog->button,
523 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500524 widget_set_button_handler(dialog->button,
525 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200526
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500527 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200528 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500529
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200530 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200531
532 return dialog;
533}
534
535static void
536unlock_dialog_destroy(struct unlock_dialog *dialog)
537{
538 window_destroy(dialog->window);
539 free(dialog);
540}
541
542static void
543unlock_dialog_finish(struct task *task, uint32_t events)
544{
545 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100546 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200547
548 desktop_shell_unlock(desktop->shell);
549 unlock_dialog_destroy(desktop->unlock_dialog);
550 desktop->unlock_dialog = NULL;
551}
552
553static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400554desktop_shell_configure(void *data,
555 struct desktop_shell *desktop_shell,
556 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200557 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400558 int32_t width, int32_t height)
559{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200560 struct window *window = wl_shell_surface_get_user_data(shell_surface);
561 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400562
Pekka Paalanen068ae942011-11-28 14:11:15 +0200563 s->configure(data, desktop_shell, time, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400564}
565
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200566static void
567desktop_shell_prepare_lock_surface(void *data,
568 struct desktop_shell *desktop_shell)
569{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200570 struct desktop *desktop = data;
571
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200572 if (!key_locking) {
573 desktop_shell_unlock(desktop->shell);
574 return;
575 }
576
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200577 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500578 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200579 desktop->unlock_dialog->desktop = desktop;
580 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200581}
582
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400583static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200584 desktop_shell_configure,
585 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400586};
587
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100588static struct background *
589background_create(struct desktop *desktop)
590{
591 struct background *background;
592
593 background = malloc(sizeof *background);
594 memset(background, 0, sizeof *background);
595
596 background->base.configure = background_configure;
597 background->window = window_create(desktop->display, 0, 0);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500598 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100599 window_set_custom(background->window);
600 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500601 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100602
603 return background;
604}
605
606static void
607create_output(struct desktop *desktop, uint32_t id)
608{
609 struct output *output;
610
611 output = calloc(1, sizeof *output);
612 if (!output)
613 return;
614
615 output->output = wl_display_bind(display_get_display(desktop->display),
616 id, &wl_output_interface);
617
618 wl_list_insert(&desktop->outputs, &output->link);
619}
620
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400621static void
622global_handler(struct wl_display *display, uint32_t id,
623 const char *interface, uint32_t version, void *data)
624{
625 struct desktop *desktop = data;
626
627 if (!strcmp(interface, "desktop_shell")) {
628 desktop->shell =
629 wl_display_bind(display, id, &desktop_shell_interface);
630 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100631 } else if (!strcmp(interface, "wl_output")) {
632 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400633 }
634}
635
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500636static void
637launcher_section_done(void *data)
638{
639 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100640 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500641
642 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
643 fprintf(stderr, "invalid launcher section\n");
644 return;
645 }
646
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100647 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500648 panel_add_launcher(output->panel,
649 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100650
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500651 free(key_launcher_icon);
652 key_launcher_icon = NULL;
653 free(key_launcher_path);
654 key_launcher_path = NULL;
655}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400656
657int main(int argc, char *argv[])
658{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200659 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200660 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100661 struct output *output;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400662
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200663 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100664 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200665
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400666 desktop.display = display_create(&argc, &argv, NULL);
667 if (desktop.display == NULL) {
668 fprintf(stderr, "failed to create display: %m\n");
669 return -1;
670 }
671
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400672 wl_display_add_global_listener(display_get_display(desktop.display),
673 global_handler, &desktop);
674
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100675 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200676 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100677
678 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200679 s = window_get_wl_shell_surface(output->panel->window);
680 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100681
682 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200683 s = window_get_wl_shell_surface(output->background->window);
684 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100685 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400686
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500687 config_file = config_file_path("weston-desktop-shell.ini");
Pekka Paalanen668dd562011-11-15 11:45:40 +0200688 parse_config_file(config_file,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500689 config_sections, ARRAY_LENGTH(config_sections),
690 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200691 free(config_file);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500692
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400693 signal(SIGCHLD, sigchild_handler);
694
695 display_run(desktop.display);
696
697 return 0;
698}