blob: 92b5f202e43b9f36419465a1cb1da665bc1e60e6 [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øgsbergbcee9a42011-10-12 00:36:16 -040062 struct window *menu;
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;
68};
69
70struct output {
71 struct wl_output *output;
72 struct wl_list link;
73
74 struct panel *panel;
75 struct background *background;
76};
77
Kristian Høgsberg53880802012-01-09 11:16:50 -050078struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050079 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040080 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040081 cairo_surface_t *icon;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040082 int pressed;
83 const char *path;
84};
85
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020086struct unlock_dialog {
87 struct window *window;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050088 struct widget *button;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020089 int closing;
90
91 struct desktop *desktop;
92};
93
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -050094static char *key_background_image;
95static uint32_t key_panel_color;
96static char *key_launcher_icon;
97static char *key_launcher_path;
98static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +020099static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500100
101static const struct config_key shell_config_keys[] = {
102 { "background-image", CONFIG_KEY_STRING, &key_background_image },
103 { "panel-color", CONFIG_KEY_INTEGER, &key_panel_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200104 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500105};
106
107static const struct config_key launcher_config_keys[] = {
108 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
109 { "path", CONFIG_KEY_STRING, &key_launcher_path },
110};
111
112static const struct config_section config_sections[] = {
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500113 { "desktop-shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500114 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
115 { "launcher",
116 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
117 launcher_section_done }
118};
119
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400120static void
121sigchild_handler(int s)
122{
123 int status;
124 pid_t pid;
125
126 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
127 fprintf(stderr, "child %d exited\n", pid);
128}
129
130static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500131show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400132{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500133 int32_t x, y;
134 static const char *entries[] = {
135 "Roy", "Pris", "Leon", "Zhora"
136 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400137
138 input_get_position(input, &x, &y);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500139 panel->menu = window_create_menu(window_get_display(panel->window),
140 input, time, panel->window,
Kristian Høgsberg4f7dcd62012-01-06 21:59:05 -0500141 x - 10, y - 10, NULL, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400142
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500143 window_schedule_redraw(panel->menu);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400144}
145
146static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500147panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400148{
149 pid_t pid;
150
151 pid = fork();
152 if (pid < 0) {
153 fprintf(stderr, "fork failed: %m\n");
154 return;
155 }
156
157 if (pid)
158 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100159
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500160 if (execl(widget->path, widget->path, NULL) < 0) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400161 fprintf(stderr, "execl failed: %m\n");
162 exit(1);
163 }
164}
165
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400166static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500167panel_draw_launcher(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400168{
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400169 cairo_t *cr = data;
Kristian Høgsberg53880802012-01-09 11:16:50 -0500170 struct panel_launcher *pi;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400171 int x, y, width, height;
172 double dx, dy;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400173
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500174 pi = widget_get_user_data(widget);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400175 width = cairo_image_surface_get_width(pi->icon);
176 height = cairo_image_surface_get_height(pi->icon);
177 x = 0;
178 y = -height / 2;
179 if (pi->pressed) {
180 x++;
181 y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400182 }
183
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400184 dx = x;
185 dy = y;
186 cairo_user_to_device(cr, &dx, &dy);
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500187 widget_set_allocation(widget, dx, dy, width, height);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400188
189 cairo_set_source_surface(cr, pi->icon, x, y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400190 cairo_paint(cr);
191
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500192 if (window_get_focus_widget(pi->panel->window) == widget) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400193 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400194 cairo_mask_surface(cr, pi->icon, x, y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400195 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400196
197 cairo_translate(cr, width + 10, 0);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400198}
199
200static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500201set_hex_color(cairo_t *cr, uint32_t color)
202{
203 cairo_set_source_rgba(cr,
204 ((color >> 16) & 0xff) / 255.0,
205 ((color >> 8) & 0xff) / 255.0,
206 ((color >> 0) & 0xff) / 255.0,
207 ((color >> 24) & 0xff) / 255.0);
208}
209
210static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400211panel_redraw_handler(struct window *window, void *data)
212{
213 cairo_surface_t *surface;
214 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400215
216 window_draw(window);
217 surface = window_get_surface(window);
218 cr = cairo_create(surface);
219 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500220 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400221 cairo_paint(cr);
222
223 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400224 cairo_translate(cr, 10, 32 / 2);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500225 window_for_each_widget(window, panel_draw_launcher, cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400226
227 cairo_destroy(cr);
228 cairo_surface_destroy(surface);
229 window_flush(window);
230}
231
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500232static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500233panel_launcher_enter_handler(struct widget *widget, struct input *input,
234 uint32_t time, int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500235{
236 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500237
238 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500239}
240
241static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500242panel_launcher_leave_handler(struct widget *widget,
243 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400244{
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500245 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400246}
247
248static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500249panel_launcher_button_handler(struct widget *widget,
250 struct input *input, uint32_t time,
251 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400252{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500253 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400254
Kristian Høgsberg53880802012-01-09 11:16:50 -0500255 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500256 widget_schedule_redraw(widget);
257 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500258 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500259}
260
261static void
262panel_button_handler(struct widget *widget,
263 struct input *input, uint32_t time,
264 int button, int state, void *data)
265{
266 struct window *window = data;
267 struct panel *panel = window_get_user_data(window);
268
269 if (button == BTN_RIGHT && state)
270 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400271}
272
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100273static void
274panel_configure(void *data,
275 struct desktop_shell *desktop_shell,
276 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200277 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100278 int32_t width, int32_t height)
279{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200280 window_set_child_size(window, width, 32);
281 window_schedule_redraw(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100282}
283
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400284static struct panel *
285panel_create(struct display *display)
286{
287 struct panel *panel;
288
289 panel = malloc(sizeof *panel);
290 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400291
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100292 panel->base.configure = panel_configure;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400293 panel->window = window_create(display, 0, 0);
294
295 window_set_title(panel->window, "panel");
296 window_set_decoration(panel->window, 0);
297 window_set_redraw_handler(panel->window, panel_redraw_handler);
298 window_set_custom(panel->window);
299 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500300
301 widget_set_button_handler(window_get_widget(panel->window),
302 panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400303
304 return panel;
305}
306
307static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500308panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400309{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500310 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400311
Kristian Høgsberg53880802012-01-09 11:16:50 -0500312 launcher = malloc(sizeof *launcher);
313 memset(launcher, 0, sizeof *launcher);
314 launcher->icon = cairo_image_surface_create_from_png(icon);
315 launcher->path = strdup(path);
316 launcher->panel = panel;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500317
Kristian Høgsberg53880802012-01-09 11:16:50 -0500318 launcher->widget = window_add_widget(panel->window, launcher);
319 widget_set_enter_handler(launcher->widget,
320 panel_launcher_enter_handler);
321 widget_set_leave_handler(launcher->widget,
322 panel_launcher_leave_handler);
323 widget_set_button_handler(launcher->widget,
324 panel_launcher_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400325}
326
327static void
328background_draw(struct window *window, int width, int height, const char *path)
329{
330 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400331 cairo_pattern_t *pattern;
332 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400333 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400334 double sx, sy;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400335
336 window_set_child_size(window, width, height);
337 window_draw(window);
338 surface = window_get_surface(window);
339
340 cr = cairo_create(surface);
341 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
342 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
343 cairo_paint(cr);
344
345 if (path) {
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400346 image = load_jpeg(path);
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400347 pattern = cairo_pattern_create_for_surface(image);
348 sx = (double) cairo_image_surface_get_width(image) / width;
349 sy = (double) cairo_image_surface_get_height(image) / height;
350 cairo_matrix_init_scale(&matrix, sx, sy);
351 cairo_pattern_set_matrix(pattern, &matrix);
352 cairo_set_source(cr, pattern);
353 cairo_pattern_destroy (pattern);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400354 cairo_paint(cr);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400355 cairo_surface_destroy(image);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400356 }
357
358 cairo_destroy(cr);
359 cairo_surface_destroy(surface);
360 window_flush(window);
361}
362
363static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100364background_configure(void *data,
365 struct desktop_shell *desktop_shell,
366 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200367 struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100368 int32_t width, int32_t height)
369{
370 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100371
Pekka Paalanen068ae942011-11-28 14:11:15 +0200372 background_draw(window, width, height, desktop->background_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100373}
374
375static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200376unlock_dialog_draw(struct unlock_dialog *dialog)
377{
378 struct rectangle allocation;
379 cairo_t *cr;
380 cairo_surface_t *surface;
381 cairo_pattern_t *pat;
382 double cx, cy, r, f;
383
384 window_draw(dialog->window);
385
386 surface = window_get_surface(dialog->window);
387 cr = cairo_create(surface);
388 window_get_child_allocation(dialog->window, &allocation);
389 cairo_rectangle(cr, allocation.x, allocation.y,
390 allocation.width, allocation.height);
391 cairo_clip(cr);
392 cairo_push_group(cr);
393 cairo_translate(cr, allocation.x, allocation.y);
394
395 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
396 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
397 cairo_paint(cr);
398
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500399 if (window_get_focus_widget(dialog->window) == dialog->button)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200400 f = 1.0;
401 else
402 f = 0.7;
403
404 cx = allocation.width / 2.0;
405 cy = allocation.height / 2.0;
406 r = (cx < cy ? cx : cy) * 0.4;
407 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
408 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
409 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
410 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
411 cairo_set_source(cr, pat);
412 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
413 cairo_fill(cr);
414
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500415 widget_set_allocation(dialog->button,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200416 allocation.x + cx - r,
417 allocation.y + cy - r, 2 * r, 2 * r);
418 cairo_pattern_destroy(pat);
419
420 cairo_pop_group_to_source(cr);
421 cairo_paint(cr);
422 cairo_destroy(cr);
423
424 window_flush(dialog->window);
425 cairo_surface_destroy(surface);
426}
427
428static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500429unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200430 struct input *input, uint32_t time,
431 int button, int state, void *data)
432{
433 struct unlock_dialog *dialog = data;
434 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200435
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500436 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200437 if (state == 0 && !dialog->closing) {
438 display_defer(desktop->display, &desktop->unlock_task);
439 dialog->closing = 1;
440 }
441 }
442}
443
444static void
445unlock_dialog_redraw_handler(struct window *window, void *data)
446{
447 struct unlock_dialog *dialog = data;
448
449 unlock_dialog_draw(dialog);
450}
451
452static void
453unlock_dialog_keyboard_focus_handler(struct window *window,
454 struct input *device, void *data)
455{
456 window_schedule_redraw(window);
457}
458
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500459static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500460unlock_dialog_widget_enter_handler(struct widget *widget,
461 struct input *input, uint32_t time,
462 int32_t x, int32_t y, void *data)
463{
464 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500465
466 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500467}
468
469static void
470unlock_dialog_widget_leave_handler(struct widget *widget,
471 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200472{
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500473 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200474}
475
476static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500477unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200478{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500479 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200480 struct unlock_dialog *dialog;
481
482 dialog = malloc(sizeof *dialog);
483 if (!dialog)
484 return NULL;
485 memset(dialog, 0, sizeof *dialog);
486
487 dialog->window = window_create(display, 260, 230);
488 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100489 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200490
491 window_set_user_data(dialog->window, dialog);
492 window_set_redraw_handler(dialog->window, unlock_dialog_redraw_handler);
493 window_set_keyboard_focus_handler(dialog->window,
494 unlock_dialog_keyboard_focus_handler);
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500495 dialog->button = window_add_widget(dialog->window, NULL);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500496 widget_set_enter_handler(dialog->button,
497 unlock_dialog_widget_enter_handler);
498 widget_set_leave_handler(dialog->button,
499 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500500 widget_set_button_handler(dialog->button,
501 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200502
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500503 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200504 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500505
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200506 unlock_dialog_draw(dialog);
507
508 return dialog;
509}
510
511static void
512unlock_dialog_destroy(struct unlock_dialog *dialog)
513{
514 window_destroy(dialog->window);
515 free(dialog);
516}
517
518static void
519unlock_dialog_finish(struct task *task, uint32_t events)
520{
521 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100522 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200523
524 desktop_shell_unlock(desktop->shell);
525 unlock_dialog_destroy(desktop->unlock_dialog);
526 desktop->unlock_dialog = NULL;
527}
528
529static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400530desktop_shell_configure(void *data,
531 struct desktop_shell *desktop_shell,
532 uint32_t time, uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200533 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400534 int32_t width, int32_t height)
535{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200536 struct window *window = wl_shell_surface_get_user_data(shell_surface);
537 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400538
Pekka Paalanen068ae942011-11-28 14:11:15 +0200539 s->configure(data, desktop_shell, time, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400540}
541
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200542static void
543desktop_shell_prepare_lock_surface(void *data,
544 struct desktop_shell *desktop_shell)
545{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200546 struct desktop *desktop = data;
547
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200548 if (!key_locking) {
549 desktop_shell_unlock(desktop->shell);
550 return;
551 }
552
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200553 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500554 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200555 desktop->unlock_dialog->desktop = desktop;
556 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200557}
558
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400559static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200560 desktop_shell_configure,
561 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400562};
563
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100564static struct background *
565background_create(struct desktop *desktop)
566{
567 struct background *background;
568
569 background = malloc(sizeof *background);
570 memset(background, 0, sizeof *background);
571
572 background->base.configure = background_configure;
573 background->window = window_create(desktop->display, 0, 0);
574 window_set_decoration(background->window, 0);
575 window_set_custom(background->window);
576 window_set_user_data(background->window, background);
577
578 return background;
579}
580
581static void
582create_output(struct desktop *desktop, uint32_t id)
583{
584 struct output *output;
585
586 output = calloc(1, sizeof *output);
587 if (!output)
588 return;
589
590 output->output = wl_display_bind(display_get_display(desktop->display),
591 id, &wl_output_interface);
592
593 wl_list_insert(&desktop->outputs, &output->link);
594}
595
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400596static void
597global_handler(struct wl_display *display, uint32_t id,
598 const char *interface, uint32_t version, void *data)
599{
600 struct desktop *desktop = data;
601
602 if (!strcmp(interface, "desktop_shell")) {
603 desktop->shell =
604 wl_display_bind(display, id, &desktop_shell_interface);
605 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100606 } else if (!strcmp(interface, "wl_output")) {
607 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400608 }
609}
610
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500611static void
612launcher_section_done(void *data)
613{
614 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100615 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500616
617 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
618 fprintf(stderr, "invalid launcher section\n");
619 return;
620 }
621
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100622 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500623 panel_add_launcher(output->panel,
624 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100625
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500626 free(key_launcher_icon);
627 key_launcher_icon = NULL;
628 free(key_launcher_path);
629 key_launcher_path = NULL;
630}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400631
632int main(int argc, char *argv[])
633{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200634 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200635 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100636 struct output *output;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400637
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200638 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100639 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200640
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400641 desktop.display = display_create(&argc, &argv, NULL);
642 if (desktop.display == NULL) {
643 fprintf(stderr, "failed to create display: %m\n");
644 return -1;
645 }
646
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400647 wl_display_add_global_listener(display_get_display(desktop.display),
648 global_handler, &desktop);
649
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100650 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200651 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100652
653 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200654 s = window_get_wl_shell_surface(output->panel->window);
655 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100656
657 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200658 s = window_get_wl_shell_surface(output->background->window);
659 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100660 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400661
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500662 config_file = config_file_path("weston-desktop-shell.ini");
Pekka Paalanen668dd562011-11-15 11:45:40 +0200663 parse_config_file(config_file,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500664 config_sections, ARRAY_LENGTH(config_sections),
665 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200666 free(config_file);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500667
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500668 desktop.background_path = key_background_image;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400669
670 signal(SIGCHLD, sigchild_handler);
671
672 display_run(desktop.display);
673
674 return 0;
675}