blob: d497807c8c7372c0c73abbc0fa459bd86d690863 [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>
Tiago Vignatti61500722012-05-23 22:06:28 +030034#include <libgen.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040035
Pekka Paalanen50719bc2011-11-22 14:18:50 +020036#include <wayland-client.h>
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +030037#include <wayland-cursor.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040038#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040039#include "../shared/cairo-util.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050040#include "../shared/config-parser.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040041
Pekka Paalanen50719bc2011-11-22 14:18:50 +020042#include "desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040043
44struct desktop {
45 struct display *display;
46 struct desktop_shell *shell;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020047 struct unlock_dialog *unlock_dialog;
48 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010049 struct wl_list outputs;
50};
51
52struct surface {
53 void (*configure)(void *data,
54 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040055 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010056 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040057};
58
59struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010060 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040061 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050062 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050063 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040064};
65
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010066struct background {
67 struct surface base;
68 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050069 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010070};
71
72struct output {
73 struct wl_output *output;
74 struct wl_list link;
75
76 struct panel *panel;
77 struct background *background;
78};
79
Kristian Høgsberg53880802012-01-09 11:16:50 -050080struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050081 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040082 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040083 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050084 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040085 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050086 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040087};
88
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020089struct unlock_dialog {
90 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050091 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050092 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050093 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020094 int closing;
95
96 struct desktop *desktop;
97};
98
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -050099static char *key_background_image = DATADIR "/weston/pattern.png";
100static char *key_background_type = "tile";
101static uint32_t key_panel_color = 0xaa000000;
102static uint32_t key_background_color = 0xff002244;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500103static char *key_launcher_icon;
104static char *key_launcher_path;
105static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200106static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500107
108static const struct config_key shell_config_keys[] = {
109 { "background-image", CONFIG_KEY_STRING, &key_background_image },
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500110 { "background-type", CONFIG_KEY_STRING, &key_background_type },
Scott Moreaufa1de692012-01-27 13:25:49 -0700111 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
112 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200113 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500114};
115
116static const struct config_key launcher_config_keys[] = {
117 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
118 { "path", CONFIG_KEY_STRING, &key_launcher_path },
119};
120
121static const struct config_section config_sections[] = {
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200122 { "shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500123 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
124 { "launcher",
125 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
126 launcher_section_done }
127};
128
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400129static void
130sigchild_handler(int s)
131{
132 int status;
133 pid_t pid;
134
135 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
136 fprintf(stderr, "child %d exited\n", pid);
137}
138
139static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200140menu_func(struct window *window, int index, void *data)
141{
142 printf("Selected index %d from a panel menu.\n", index);
143}
144
145static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500146show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400147{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500148 int32_t x, y;
149 static const char *entries[] = {
150 "Roy", "Pris", "Leon", "Zhora"
151 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400152
153 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200154 window_show_menu(window_get_display(panel->window),
155 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200156 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400157}
158
159static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500160panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400161{
162 pid_t pid;
163
164 pid = fork();
165 if (pid < 0) {
166 fprintf(stderr, "fork failed: %m\n");
167 return;
168 }
169
170 if (pid)
171 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100172
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500173 if (execl(widget->path, widget->path, NULL) < 0) {
Pekka Paalanena291ae52012-01-27 09:50:02 +0200174 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400175 exit(1);
176 }
177}
178
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400179static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500180panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400181{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500182 struct panel_launcher *launcher = data;
183 cairo_surface_t *surface;
184 struct rectangle allocation;
185 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400186
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500187 surface = window_get_surface(launcher->panel->window);
188 cr = cairo_create(surface);
189
190 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500191 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500192 allocation.x++;
193 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400194 }
195
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500196 cairo_set_source_surface(cr, launcher->icon,
197 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400198 cairo_paint(cr);
199
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500200 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400201 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500202 cairo_mask_surface(cr, launcher->icon,
203 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400204 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400205
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500206 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400207}
208
Tiago Vignatti61500722012-05-23 22:06:28 +0300209static int
210panel_launcher_motion_handler(struct widget *widget, struct input *input,
211 uint32_t time, float x, float y, void *data)
212{
213 struct panel_launcher *launcher = data;
214
215 widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
216
217 return POINTER_LEFT_PTR;
218}
219
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400220static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500221set_hex_color(cairo_t *cr, uint32_t color)
222{
223 cairo_set_source_rgba(cr,
224 ((color >> 16) & 0xff) / 255.0,
225 ((color >> 8) & 0xff) / 255.0,
226 ((color >> 0) & 0xff) / 255.0,
227 ((color >> 24) & 0xff) / 255.0);
228}
229
230static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500231panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400232{
233 cairo_surface_t *surface;
234 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500235 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400236
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500237 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400238 cr = cairo_create(surface);
239 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500240 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400241 cairo_paint(cr);
242
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400243 cairo_destroy(cr);
244 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400245}
246
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500247static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500248panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400249 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500250{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500251 struct panel_launcher *launcher = data;
252
253 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500254 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500255
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +0300256 return WL_CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500257}
258
259static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500260panel_launcher_leave_handler(struct widget *widget,
261 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400262{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500263 struct panel_launcher *launcher = data;
264
265 launcher->focused = 0;
Tiago Vignatti61500722012-05-23 22:06:28 +0300266 widget_destroy_tooltip(widget);
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500267 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400268}
269
270static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500271panel_launcher_button_handler(struct widget *widget,
272 struct input *input, uint32_t time,
Daniel Stone5d663712012-05-04 11:21:55 +0100273 uint32_t button, uint32_t state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400274{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500275 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400276
Kristian Høgsberg53880802012-01-09 11:16:50 -0500277 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500278 widget_schedule_redraw(widget);
279 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500280 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500281}
282
283static void
284panel_button_handler(struct widget *widget,
285 struct input *input, uint32_t time,
Daniel Stone5d663712012-05-04 11:21:55 +0100286 uint32_t button, uint32_t state, void *data)
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500287{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500288 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500289
290 if (button == BTN_RIGHT && state)
291 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400292}
293
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100294static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500295panel_resize_handler(struct widget *widget,
296 int32_t width, int32_t height, void *data)
297{
298 struct panel_launcher *launcher;
299 struct panel *panel = data;
300 int x, y, w, h;
301
302 x = 10;
303 y = 16;
304 wl_list_for_each(launcher, &panel->launcher_list, link) {
305 w = cairo_image_surface_get_width(launcher->icon);
306 h = cairo_image_surface_get_height(launcher->icon);
307 widget_set_allocation(launcher->widget,
308 x, y - h / 2, w + 1, h + 1);
309 x += w + 10;
310 }
311}
312
313static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100314panel_configure(void *data,
315 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400316 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100317 int32_t width, int32_t height)
318{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500319 struct surface *surface = window_get_user_data(window);
320 struct panel *panel = container_of(surface, struct panel, base);
321
322 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100323}
324
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400325static struct panel *
326panel_create(struct display *display)
327{
328 struct panel *panel;
329
330 panel = malloc(sizeof *panel);
331 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400332
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100333 panel->base.configure = panel_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500334 panel->window = window_create(display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500335 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500336 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400337
338 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400339 window_set_custom(panel->window);
340 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500341
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500342 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
343 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500344 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400345
346 return panel;
347}
348
349static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500350panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400351{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500352 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400353
Kristian Høgsberg53880802012-01-09 11:16:50 -0500354 launcher = malloc(sizeof *launcher);
355 memset(launcher, 0, sizeof *launcher);
356 launcher->icon = cairo_image_surface_create_from_png(icon);
357 launcher->path = strdup(path);
358 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500359 wl_list_insert(panel->launcher_list.prev, &launcher->link);
360
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500361 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500362 widget_set_enter_handler(launcher->widget,
363 panel_launcher_enter_handler);
364 widget_set_leave_handler(launcher->widget,
365 panel_launcher_leave_handler);
366 widget_set_button_handler(launcher->widget,
367 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500368 widget_set_redraw_handler(launcher->widget,
369 panel_launcher_redraw_handler);
Tiago Vignatti61500722012-05-23 22:06:28 +0300370 widget_set_motion_handler(launcher->widget,
371 panel_launcher_motion_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400372}
373
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500374enum {
375 BACKGROUND_SCALE,
376 BACKGROUND_TILE
377};
378
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400379static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500380background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400381{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500382 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400383 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400384 cairo_pattern_t *pattern;
385 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400386 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400387 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500388 struct rectangle allocation;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500389 int type = -1;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400390
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500391 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400392
393 cr = cairo_create(surface);
394 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
395 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
396 cairo_paint(cr);
397
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500398 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500399 image = NULL;
400 if (key_background_image)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400401 image = load_cairo_surface(key_background_image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500402
403 if (strcmp(key_background_type, "scale") == 0)
404 type = BACKGROUND_SCALE;
405 else if (strcmp(key_background_type, "tile") == 0)
406 type = BACKGROUND_TILE;
407 else
408 fprintf(stderr, "invalid background-type: %s\n",
409 key_background_type);
410
411 if (image && type != -1) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400412 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500413 switch (type) {
414 case BACKGROUND_SCALE:
415 sx = (double) cairo_image_surface_get_width(image) /
416 allocation.width;
417 sy = (double) cairo_image_surface_get_height(image) /
418 allocation.height;
419 cairo_matrix_init_scale(&matrix, sx, sy);
420 cairo_pattern_set_matrix(pattern, &matrix);
421 break;
422 case BACKGROUND_TILE:
423 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
424 break;
425 }
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400426 cairo_set_source(cr, pattern);
427 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400428 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500429 } else {
430 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400431 }
432
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500433 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400434 cairo_destroy(cr);
435 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400436}
437
438static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100439background_configure(void *data,
440 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400441 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100442 int32_t width, int32_t height)
443{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500444 struct background *background =
445 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100446
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500447 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100448}
449
450static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500451unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200452{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500453 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200454 struct rectangle allocation;
455 cairo_t *cr;
456 cairo_surface_t *surface;
457 cairo_pattern_t *pat;
458 double cx, cy, r, f;
459
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200460 surface = window_get_surface(dialog->window);
461 cr = cairo_create(surface);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500462
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500463 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200464 cairo_rectangle(cr, allocation.x, allocation.y,
465 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200466 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
467 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500468 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200469
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500470 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500471 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200472 f = 1.0;
473 else
474 f = 0.7;
475
476 cx = allocation.width / 2.0;
477 cy = allocation.height / 2.0;
478 r = (cx < cy ? cx : cy) * 0.4;
479 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
480 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
481 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
482 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
483 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500484 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200485 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
486 cairo_fill(cr);
487
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500488 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500489 allocation.x + cx - r,
490 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200491
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200492 cairo_destroy(cr);
493
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200494 cairo_surface_destroy(surface);
495}
496
497static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500498unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200499 struct input *input, uint32_t time,
Daniel Stone5d663712012-05-04 11:21:55 +0100500 uint32_t button, uint32_t state, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200501{
502 struct unlock_dialog *dialog = data;
503 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200504
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500505 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200506 if (state == 0 && !dialog->closing) {
507 display_defer(desktop->display, &desktop->unlock_task);
508 dialog->closing = 1;
509 }
510 }
511}
512
513static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200514unlock_dialog_keyboard_focus_handler(struct window *window,
515 struct input *device, void *data)
516{
517 window_schedule_redraw(window);
518}
519
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500520static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500521unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400522 struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400523 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500524{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500525 struct unlock_dialog *dialog = data;
526
527 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500528 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500529
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +0300530 return WL_CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500531}
532
533static void
534unlock_dialog_widget_leave_handler(struct widget *widget,
535 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200536{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500537 struct unlock_dialog *dialog = data;
538
539 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500540 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200541}
542
543static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500544unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200545{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500546 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200547 struct unlock_dialog *dialog;
548
549 dialog = malloc(sizeof *dialog);
550 if (!dialog)
551 return NULL;
552 memset(dialog, 0, sizeof *dialog);
553
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500554 dialog->window = window_create(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500555 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200556 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100557 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200558
559 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200560 window_set_keyboard_focus_handler(dialog->window,
561 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500562 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500563 widget_set_redraw_handler(dialog->widget,
564 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500565 widget_set_enter_handler(dialog->button,
566 unlock_dialog_widget_enter_handler);
567 widget_set_leave_handler(dialog->button,
568 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500569 widget_set_button_handler(dialog->button,
570 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200571
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500572 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200573 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500574
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200575 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200576
577 return dialog;
578}
579
580static void
581unlock_dialog_destroy(struct unlock_dialog *dialog)
582{
583 window_destroy(dialog->window);
584 free(dialog);
585}
586
587static void
588unlock_dialog_finish(struct task *task, uint32_t events)
589{
590 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100591 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200592
593 desktop_shell_unlock(desktop->shell);
594 unlock_dialog_destroy(desktop->unlock_dialog);
595 desktop->unlock_dialog = NULL;
596}
597
598static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400599desktop_shell_configure(void *data,
600 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400601 uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200602 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400603 int32_t width, int32_t height)
604{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200605 struct window *window = wl_shell_surface_get_user_data(shell_surface);
606 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400607
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400608 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400609}
610
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200611static void
612desktop_shell_prepare_lock_surface(void *data,
613 struct desktop_shell *desktop_shell)
614{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200615 struct desktop *desktop = data;
616
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200617 if (!key_locking) {
618 desktop_shell_unlock(desktop->shell);
619 return;
620 }
621
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200622 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500623 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200624 desktop->unlock_dialog->desktop = desktop;
625 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200626}
627
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400628static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200629 desktop_shell_configure,
630 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400631};
632
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100633static struct background *
634background_create(struct desktop *desktop)
635{
636 struct background *background;
637
638 background = malloc(sizeof *background);
639 memset(background, 0, sizeof *background);
640
641 background->base.configure = background_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500642 background->window = window_create(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500643 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100644 window_set_custom(background->window);
645 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500646 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100647
648 return background;
649}
650
651static void
652create_output(struct desktop *desktop, uint32_t id)
653{
654 struct output *output;
655
656 output = calloc(1, sizeof *output);
657 if (!output)
658 return;
659
660 output->output = wl_display_bind(display_get_display(desktop->display),
661 id, &wl_output_interface);
662
663 wl_list_insert(&desktop->outputs, &output->link);
664}
665
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400666static void
667global_handler(struct wl_display *display, uint32_t id,
668 const char *interface, uint32_t version, void *data)
669{
670 struct desktop *desktop = data;
671
672 if (!strcmp(interface, "desktop_shell")) {
673 desktop->shell =
674 wl_display_bind(display, id, &desktop_shell_interface);
675 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100676 } else if (!strcmp(interface, "wl_output")) {
677 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400678 }
679}
680
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500681static void
682launcher_section_done(void *data)
683{
684 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100685 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500686
687 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
688 fprintf(stderr, "invalid launcher section\n");
689 return;
690 }
691
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100692 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500693 panel_add_launcher(output->panel,
694 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100695
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500696 free(key_launcher_icon);
697 key_launcher_icon = NULL;
698 free(key_launcher_path);
699 key_launcher_path = NULL;
700}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400701
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500702static void
703add_default_launcher(struct desktop *desktop)
704{
705 struct output *output;
706
707 wl_list_for_each(output, &desktop->outputs, link)
708 panel_add_launcher(output->panel,
709 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +0100710 BINDIR "/weston-terminal");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500711}
712
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400713int main(int argc, char *argv[])
714{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200715 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200716 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100717 struct output *output;
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500718 int ret;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400719
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200720 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100721 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200722
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400723 desktop.display = display_create(argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400724 if (desktop.display == NULL) {
725 fprintf(stderr, "failed to create display: %m\n");
726 return -1;
727 }
728
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400729 wl_display_add_global_listener(display_get_display(desktop.display),
730 global_handler, &desktop);
731
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100732 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200733 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100734
735 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200736 s = window_get_wl_shell_surface(output->panel->window);
737 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100738
739 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200740 s = window_get_wl_shell_surface(output->background->window);
741 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100742 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400743
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200744 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500745 ret = parse_config_file(config_file,
746 config_sections, ARRAY_LENGTH(config_sections),
747 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200748 free(config_file);
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500749 if (ret < 0)
750 add_default_launcher(&desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500751
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400752 signal(SIGCHLD, sigchild_handler);
753
754 display_run(desktop.display);
755
756 return 0;
757}