blob: df4494ed9e2772c43d42338b28c987dc9700262b [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,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040053 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010054 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040055};
56
57struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010058 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040059 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050060 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050061 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040062};
63
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010064struct background {
65 struct surface base;
66 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050067 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010068};
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øgsbergb6323512012-01-11 00:04:42 -050082 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040083 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050084 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040085};
86
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020087struct unlock_dialog {
88 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050089 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050090 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050091 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020092 int closing;
93
94 struct desktop *desktop;
95};
96
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -050097static char *key_background_image = DATADIR "/weston/pattern.png";
98static char *key_background_type = "tile";
99static uint32_t key_panel_color = 0xaa000000;
100static uint32_t key_background_color = 0xff002244;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500101static char *key_launcher_icon;
102static char *key_launcher_path;
103static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200104static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500105
106static const struct config_key shell_config_keys[] = {
107 { "background-image", CONFIG_KEY_STRING, &key_background_image },
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500108 { "background-type", CONFIG_KEY_STRING, &key_background_type },
Scott Moreaufa1de692012-01-27 13:25:49 -0700109 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
110 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200111 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500112};
113
114static const struct config_key launcher_config_keys[] = {
115 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
116 { "path", CONFIG_KEY_STRING, &key_launcher_path },
117};
118
119static const struct config_section config_sections[] = {
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200120 { "shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500121 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
122 { "launcher",
123 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
124 launcher_section_done }
125};
126
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400127static void
128sigchild_handler(int s)
129{
130 int status;
131 pid_t pid;
132
133 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
134 fprintf(stderr, "child %d exited\n", pid);
135}
136
137static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200138menu_func(struct window *window, int index, void *data)
139{
140 printf("Selected index %d from a panel menu.\n", index);
141}
142
143static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500144show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400145{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500146 int32_t x, y;
147 static const char *entries[] = {
148 "Roy", "Pris", "Leon", "Zhora"
149 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400150
151 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200152 window_show_menu(window_get_display(panel->window),
153 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200154 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400155}
156
157static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500158panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400159{
160 pid_t pid;
161
162 pid = fork();
163 if (pid < 0) {
164 fprintf(stderr, "fork failed: %m\n");
165 return;
166 }
167
168 if (pid)
169 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100170
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500171 if (execl(widget->path, widget->path, NULL) < 0) {
Pekka Paalanena291ae52012-01-27 09:50:02 +0200172 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400173 exit(1);
174 }
175}
176
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400177static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500178panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400179{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500180 struct panel_launcher *launcher = data;
181 cairo_surface_t *surface;
182 struct rectangle allocation;
183 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400184
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500185 surface = window_get_surface(launcher->panel->window);
186 cr = cairo_create(surface);
187
188 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500189 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500190 allocation.x++;
191 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400192 }
193
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500194 cairo_set_source_surface(cr, launcher->icon,
195 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400196 cairo_paint(cr);
197
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500198 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400199 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500200 cairo_mask_surface(cr, launcher->icon,
201 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400202 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400203
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500204 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400205}
206
207static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500208set_hex_color(cairo_t *cr, uint32_t color)
209{
210 cairo_set_source_rgba(cr,
211 ((color >> 16) & 0xff) / 255.0,
212 ((color >> 8) & 0xff) / 255.0,
213 ((color >> 0) & 0xff) / 255.0,
214 ((color >> 24) & 0xff) / 255.0);
215}
216
217static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500218panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400219{
220 cairo_surface_t *surface;
221 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500222 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400223
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500224 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400225 cr = cairo_create(surface);
226 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500227 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400228 cairo_paint(cr);
229
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400230 cairo_destroy(cr);
231 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400232}
233
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500234static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500235panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400236 int32_t x, int32_t y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500237{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500238 struct panel_launcher *launcher = data;
239
240 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500241 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500242
243 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500244}
245
246static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500247panel_launcher_leave_handler(struct widget *widget,
248 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400249{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500250 struct panel_launcher *launcher = data;
251
252 launcher->focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500253 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400254}
255
256static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500257panel_launcher_button_handler(struct widget *widget,
258 struct input *input, uint32_t time,
259 int button, int state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400260{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500261 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400262
Kristian Høgsberg53880802012-01-09 11:16:50 -0500263 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500264 widget_schedule_redraw(widget);
265 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500266 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500267}
268
269static void
270panel_button_handler(struct widget *widget,
271 struct input *input, uint32_t time,
272 int button, int state, void *data)
273{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500274 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500275
276 if (button == BTN_RIGHT && state)
277 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400278}
279
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100280static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500281panel_resize_handler(struct widget *widget,
282 int32_t width, int32_t height, void *data)
283{
284 struct panel_launcher *launcher;
285 struct panel *panel = data;
286 int x, y, w, h;
287
288 x = 10;
289 y = 16;
290 wl_list_for_each(launcher, &panel->launcher_list, link) {
291 w = cairo_image_surface_get_width(launcher->icon);
292 h = cairo_image_surface_get_height(launcher->icon);
293 widget_set_allocation(launcher->widget,
294 x, y - h / 2, w + 1, h + 1);
295 x += w + 10;
296 }
297}
298
299static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100300panel_configure(void *data,
301 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400302 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100303 int32_t width, int32_t height)
304{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500305 struct surface *surface = window_get_user_data(window);
306 struct panel *panel = container_of(surface, struct panel, base);
307
308 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100309}
310
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400311static struct panel *
312panel_create(struct display *display)
313{
314 struct panel *panel;
315
316 panel = malloc(sizeof *panel);
317 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400318
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100319 panel->base.configure = panel_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500320 panel->window = window_create(display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500321 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500322 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400323
324 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400325 window_set_custom(panel->window);
326 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500327
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500328 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
329 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500330 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400331
332 return panel;
333}
334
335static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500336panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400337{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500338 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400339
Kristian Høgsberg53880802012-01-09 11:16:50 -0500340 launcher = malloc(sizeof *launcher);
341 memset(launcher, 0, sizeof *launcher);
342 launcher->icon = cairo_image_surface_create_from_png(icon);
343 launcher->path = strdup(path);
344 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500345 wl_list_insert(panel->launcher_list.prev, &launcher->link);
346
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500347 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500348 widget_set_enter_handler(launcher->widget,
349 panel_launcher_enter_handler);
350 widget_set_leave_handler(launcher->widget,
351 panel_launcher_leave_handler);
352 widget_set_button_handler(launcher->widget,
353 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500354 widget_set_redraw_handler(launcher->widget,
355 panel_launcher_redraw_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400356}
357
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500358enum {
359 BACKGROUND_SCALE,
360 BACKGROUND_TILE
361};
362
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400363static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500364background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400365{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500366 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400367 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400368 cairo_pattern_t *pattern;
369 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400370 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400371 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500372 struct rectangle allocation;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500373 int type = -1;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400374
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500375 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400376
377 cr = cairo_create(surface);
378 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
379 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
380 cairo_paint(cr);
381
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500382 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500383 image = NULL;
384 if (key_background_image)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400385 image = load_cairo_surface(key_background_image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500386
387 if (strcmp(key_background_type, "scale") == 0)
388 type = BACKGROUND_SCALE;
389 else if (strcmp(key_background_type, "tile") == 0)
390 type = BACKGROUND_TILE;
391 else
392 fprintf(stderr, "invalid background-type: %s\n",
393 key_background_type);
394
395 if (image && type != -1) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400396 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500397 switch (type) {
398 case BACKGROUND_SCALE:
399 sx = (double) cairo_image_surface_get_width(image) /
400 allocation.width;
401 sy = (double) cairo_image_surface_get_height(image) /
402 allocation.height;
403 cairo_matrix_init_scale(&matrix, sx, sy);
404 cairo_pattern_set_matrix(pattern, &matrix);
405 break;
406 case BACKGROUND_TILE:
407 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
408 break;
409 }
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400410 cairo_set_source(cr, pattern);
411 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400412 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500413 } else {
414 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400415 }
416
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500417 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400418 cairo_destroy(cr);
419 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400420}
421
422static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100423background_configure(void *data,
424 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400425 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100426 int32_t width, int32_t height)
427{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500428 struct background *background =
429 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100430
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500431 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100432}
433
434static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500435unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200436{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500437 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200438 struct rectangle allocation;
439 cairo_t *cr;
440 cairo_surface_t *surface;
441 cairo_pattern_t *pat;
442 double cx, cy, r, f;
443
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200444 surface = window_get_surface(dialog->window);
445 cr = cairo_create(surface);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500446
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500447 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200448 cairo_rectangle(cr, allocation.x, allocation.y,
449 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200450 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
451 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500452 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200453
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500454 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500455 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200456 f = 1.0;
457 else
458 f = 0.7;
459
460 cx = allocation.width / 2.0;
461 cy = allocation.height / 2.0;
462 r = (cx < cy ? cx : cy) * 0.4;
463 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
464 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
465 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
466 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
467 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500468 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200469 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
470 cairo_fill(cr);
471
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500472 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500473 allocation.x + cx - r,
474 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200475
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200476 cairo_destroy(cr);
477
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200478 cairo_surface_destroy(surface);
479}
480
481static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500482unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200483 struct input *input, uint32_t time,
484 int button, int state, void *data)
485{
486 struct unlock_dialog *dialog = data;
487 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200488
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500489 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200490 if (state == 0 && !dialog->closing) {
491 display_defer(desktop->display, &desktop->unlock_task);
492 dialog->closing = 1;
493 }
494 }
495}
496
497static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200498unlock_dialog_keyboard_focus_handler(struct window *window,
499 struct input *device, void *data)
500{
501 window_schedule_redraw(window);
502}
503
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500504static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500505unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400506 struct input *input,
Kristian Høgsbergee143232012-01-09 08:42:24 -0500507 int32_t x, int32_t y, void *data)
508{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500509 struct unlock_dialog *dialog = data;
510
511 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500512 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500513
514 return POINTER_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500515}
516
517static void
518unlock_dialog_widget_leave_handler(struct widget *widget,
519 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200520{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500521 struct unlock_dialog *dialog = data;
522
523 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500524 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200525}
526
527static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500528unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200529{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500530 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200531 struct unlock_dialog *dialog;
532
533 dialog = malloc(sizeof *dialog);
534 if (!dialog)
535 return NULL;
536 memset(dialog, 0, sizeof *dialog);
537
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500538 dialog->window = window_create(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500539 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200540 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100541 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200542
543 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200544 window_set_keyboard_focus_handler(dialog->window,
545 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500546 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500547 widget_set_redraw_handler(dialog->widget,
548 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500549 widget_set_enter_handler(dialog->button,
550 unlock_dialog_widget_enter_handler);
551 widget_set_leave_handler(dialog->button,
552 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500553 widget_set_button_handler(dialog->button,
554 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200555
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500556 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200557 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500558
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200559 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200560
561 return dialog;
562}
563
564static void
565unlock_dialog_destroy(struct unlock_dialog *dialog)
566{
567 window_destroy(dialog->window);
568 free(dialog);
569}
570
571static void
572unlock_dialog_finish(struct task *task, uint32_t events)
573{
574 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100575 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200576
577 desktop_shell_unlock(desktop->shell);
578 unlock_dialog_destroy(desktop->unlock_dialog);
579 desktop->unlock_dialog = NULL;
580}
581
582static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400583desktop_shell_configure(void *data,
584 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400585 uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200586 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400587 int32_t width, int32_t height)
588{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200589 struct window *window = wl_shell_surface_get_user_data(shell_surface);
590 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400591
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400592 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400593}
594
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200595static void
596desktop_shell_prepare_lock_surface(void *data,
597 struct desktop_shell *desktop_shell)
598{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200599 struct desktop *desktop = data;
600
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200601 if (!key_locking) {
602 desktop_shell_unlock(desktop->shell);
603 return;
604 }
605
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200606 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500607 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200608 desktop->unlock_dialog->desktop = desktop;
609 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200610}
611
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400612static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200613 desktop_shell_configure,
614 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400615};
616
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100617static struct background *
618background_create(struct desktop *desktop)
619{
620 struct background *background;
621
622 background = malloc(sizeof *background);
623 memset(background, 0, sizeof *background);
624
625 background->base.configure = background_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500626 background->window = window_create(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500627 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100628 window_set_custom(background->window);
629 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500630 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100631
632 return background;
633}
634
635static void
636create_output(struct desktop *desktop, uint32_t id)
637{
638 struct output *output;
639
640 output = calloc(1, sizeof *output);
641 if (!output)
642 return;
643
644 output->output = wl_display_bind(display_get_display(desktop->display),
645 id, &wl_output_interface);
646
647 wl_list_insert(&desktop->outputs, &output->link);
648}
649
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400650static void
651global_handler(struct wl_display *display, uint32_t id,
652 const char *interface, uint32_t version, void *data)
653{
654 struct desktop *desktop = data;
655
656 if (!strcmp(interface, "desktop_shell")) {
657 desktop->shell =
658 wl_display_bind(display, id, &desktop_shell_interface);
659 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100660 } else if (!strcmp(interface, "wl_output")) {
661 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400662 }
663}
664
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500665static void
666launcher_section_done(void *data)
667{
668 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100669 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500670
671 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
672 fprintf(stderr, "invalid launcher section\n");
673 return;
674 }
675
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100676 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500677 panel_add_launcher(output->panel,
678 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100679
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500680 free(key_launcher_icon);
681 key_launcher_icon = NULL;
682 free(key_launcher_path);
683 key_launcher_path = NULL;
684}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400685
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500686static void
687add_default_launcher(struct desktop *desktop)
688{
689 struct output *output;
690
691 wl_list_for_each(output, &desktop->outputs, link)
692 panel_add_launcher(output->panel,
693 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +0100694 BINDIR "/weston-terminal");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500695}
696
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400697int main(int argc, char *argv[])
698{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200699 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200700 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100701 struct output *output;
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500702 int ret;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400703
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200704 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100705 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200706
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400707 desktop.display = display_create(argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400708 if (desktop.display == NULL) {
709 fprintf(stderr, "failed to create display: %m\n");
710 return -1;
711 }
712
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400713 wl_display_add_global_listener(display_get_display(desktop.display),
714 global_handler, &desktop);
715
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100716 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200717 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100718
719 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200720 s = window_get_wl_shell_surface(output->panel->window);
721 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100722
723 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200724 s = window_get_wl_shell_surface(output->background->window);
725 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100726 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400727
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200728 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500729 ret = parse_config_file(config_file,
730 config_sections, ARRAY_LENGTH(config_sections),
731 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200732 free(config_file);
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500733 if (ret < 0)
734 add_default_launcher(&desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500735
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400736 signal(SIGCHLD, sigchild_handler);
737
738 display_run(desktop.display);
739
740 return 0;
741}