blob: 2473f365c97a50873c37406d88da9129515861b4 [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>
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +030036#include <wayland-cursor.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040037#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040038#include "../shared/cairo-util.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050039#include "../shared/config-parser.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040040
Pekka Paalanen50719bc2011-11-22 14:18:50 +020041#include "desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040042
43struct desktop {
44 struct display *display;
45 struct desktop_shell *shell;
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,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040054 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010055 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040056};
57
58struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010059 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040060 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050061 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050062 struct wl_list launcher_list;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040063};
64
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010065struct background {
66 struct surface base;
67 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050068 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010069};
70
71struct output {
72 struct wl_output *output;
73 struct wl_list link;
74
75 struct panel *panel;
76 struct background *background;
77};
78
Kristian Høgsberg53880802012-01-09 11:16:50 -050079struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050080 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040081 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040082 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050083 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040084 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050085 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040086};
87
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020088struct unlock_dialog {
89 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050090 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050091 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050092 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020093 int closing;
94
95 struct desktop *desktop;
96};
97
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -050098static char *key_background_image = DATADIR "/weston/pattern.png";
99static char *key_background_type = "tile";
100static uint32_t key_panel_color = 0xaa000000;
101static uint32_t key_background_color = 0xff002244;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500102static char *key_launcher_icon;
103static char *key_launcher_path;
104static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200105static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500106
107static const struct config_key shell_config_keys[] = {
108 { "background-image", CONFIG_KEY_STRING, &key_background_image },
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500109 { "background-type", CONFIG_KEY_STRING, &key_background_type },
Scott Moreaufa1de692012-01-27 13:25:49 -0700110 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
111 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200112 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500113};
114
115static const struct config_key launcher_config_keys[] = {
116 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
117 { "path", CONFIG_KEY_STRING, &key_launcher_path },
118};
119
120static const struct config_section config_sections[] = {
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200121 { "shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500122 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
123 { "launcher",
124 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
125 launcher_section_done }
126};
127
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400128static void
129sigchild_handler(int s)
130{
131 int status;
132 pid_t pid;
133
134 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
135 fprintf(stderr, "child %d exited\n", pid);
136}
137
138static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200139menu_func(struct window *window, int index, void *data)
140{
141 printf("Selected index %d from a panel menu.\n", index);
142}
143
144static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500145show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400146{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500147 int32_t x, y;
148 static const char *entries[] = {
149 "Roy", "Pris", "Leon", "Zhora"
150 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400151
152 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200153 window_show_menu(window_get_display(panel->window),
154 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200155 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400156}
157
158static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500159panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400160{
161 pid_t pid;
162
163 pid = fork();
164 if (pid < 0) {
165 fprintf(stderr, "fork failed: %m\n");
166 return;
167 }
168
169 if (pid)
170 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100171
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500172 if (execl(widget->path, widget->path, NULL) < 0) {
Pekka Paalanena291ae52012-01-27 09:50:02 +0200173 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400174 exit(1);
175 }
176}
177
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400178static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500179panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400180{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500181 struct panel_launcher *launcher = data;
182 cairo_surface_t *surface;
183 struct rectangle allocation;
184 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400185
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500186 surface = window_get_surface(launcher->panel->window);
187 cr = cairo_create(surface);
188
189 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500190 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500191 allocation.x++;
192 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400193 }
194
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500195 cairo_set_source_surface(cr, launcher->icon,
196 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400197 cairo_paint(cr);
198
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500199 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400200 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500201 cairo_mask_surface(cr, launcher->icon,
202 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400203 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400204
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500205 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400206}
207
208static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500209set_hex_color(cairo_t *cr, uint32_t color)
210{
211 cairo_set_source_rgba(cr,
212 ((color >> 16) & 0xff) / 255.0,
213 ((color >> 8) & 0xff) / 255.0,
214 ((color >> 0) & 0xff) / 255.0,
215 ((color >> 24) & 0xff) / 255.0);
216}
217
218static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500219panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400220{
221 cairo_surface_t *surface;
222 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500223 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400224
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500225 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400226 cr = cairo_create(surface);
227 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500228 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400229 cairo_paint(cr);
230
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400231 cairo_destroy(cr);
232 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400233}
234
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500235static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500236panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400237 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500238{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500239 struct panel_launcher *launcher = data;
240
241 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500242 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500243
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +0300244 return WL_CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500245}
246
247static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500248panel_launcher_leave_handler(struct widget *widget,
249 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400250{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500251 struct panel_launcher *launcher = data;
252
253 launcher->focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500254 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400255}
256
257static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500258panel_launcher_button_handler(struct widget *widget,
259 struct input *input, uint32_t time,
Daniel Stone5d663712012-05-04 11:21:55 +0100260 uint32_t button, uint32_t state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400261{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500262 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400263
Kristian Høgsberg53880802012-01-09 11:16:50 -0500264 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500265 widget_schedule_redraw(widget);
266 if (state == 0)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500267 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500268}
269
270static void
271panel_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øgsberga8a0db32012-01-09 11:12:05 -0500274{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500275 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500276
277 if (button == BTN_RIGHT && state)
278 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400279}
280
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100281static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500282panel_resize_handler(struct widget *widget,
283 int32_t width, int32_t height, void *data)
284{
285 struct panel_launcher *launcher;
286 struct panel *panel = data;
287 int x, y, w, h;
288
289 x = 10;
290 y = 16;
291 wl_list_for_each(launcher, &panel->launcher_list, link) {
292 w = cairo_image_surface_get_width(launcher->icon);
293 h = cairo_image_surface_get_height(launcher->icon);
294 widget_set_allocation(launcher->widget,
295 x, y - h / 2, w + 1, h + 1);
296 x += w + 10;
297 }
298}
299
300static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100301panel_configure(void *data,
302 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400303 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100304 int32_t width, int32_t height)
305{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500306 struct surface *surface = window_get_user_data(window);
307 struct panel *panel = container_of(surface, struct panel, base);
308
309 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100310}
311
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400312static struct panel *
313panel_create(struct display *display)
314{
315 struct panel *panel;
316
317 panel = malloc(sizeof *panel);
318 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400319
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100320 panel->base.configure = panel_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500321 panel->window = window_create(display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500322 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500323 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400324
325 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400326 window_set_custom(panel->window);
327 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500328
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500329 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
330 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500331 widget_set_button_handler(panel->widget, panel_button_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400332
333 return panel;
334}
335
336static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500337panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400338{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500339 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400340
Kristian Høgsberg53880802012-01-09 11:16:50 -0500341 launcher = malloc(sizeof *launcher);
342 memset(launcher, 0, sizeof *launcher);
343 launcher->icon = cairo_image_surface_create_from_png(icon);
344 launcher->path = strdup(path);
345 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500346 wl_list_insert(panel->launcher_list.prev, &launcher->link);
347
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500348 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500349 widget_set_enter_handler(launcher->widget,
350 panel_launcher_enter_handler);
351 widget_set_leave_handler(launcher->widget,
352 panel_launcher_leave_handler);
353 widget_set_button_handler(launcher->widget,
354 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500355 widget_set_redraw_handler(launcher->widget,
356 panel_launcher_redraw_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400357}
358
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500359enum {
360 BACKGROUND_SCALE,
361 BACKGROUND_TILE
362};
363
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400364static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500365background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400366{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500367 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400368 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400369 cairo_pattern_t *pattern;
370 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400371 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400372 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500373 struct rectangle allocation;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500374 int type = -1;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400375
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500376 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400377
378 cr = cairo_create(surface);
379 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
380 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
381 cairo_paint(cr);
382
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500383 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500384 image = NULL;
385 if (key_background_image)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400386 image = load_cairo_surface(key_background_image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500387
388 if (strcmp(key_background_type, "scale") == 0)
389 type = BACKGROUND_SCALE;
390 else if (strcmp(key_background_type, "tile") == 0)
391 type = BACKGROUND_TILE;
392 else
393 fprintf(stderr, "invalid background-type: %s\n",
394 key_background_type);
395
396 if (image && type != -1) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400397 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500398 switch (type) {
399 case BACKGROUND_SCALE:
400 sx = (double) cairo_image_surface_get_width(image) /
401 allocation.width;
402 sy = (double) cairo_image_surface_get_height(image) /
403 allocation.height;
404 cairo_matrix_init_scale(&matrix, sx, sy);
405 cairo_pattern_set_matrix(pattern, &matrix);
406 break;
407 case BACKGROUND_TILE:
408 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
409 break;
410 }
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400411 cairo_set_source(cr, pattern);
412 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400413 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500414 } else {
415 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400416 }
417
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500418 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400419 cairo_destroy(cr);
420 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400421}
422
423static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100424background_configure(void *data,
425 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400426 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100427 int32_t width, int32_t height)
428{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500429 struct background *background =
430 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100431
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500432 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100433}
434
435static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500436unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200437{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500438 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200439 struct rectangle allocation;
440 cairo_t *cr;
441 cairo_surface_t *surface;
442 cairo_pattern_t *pat;
443 double cx, cy, r, f;
444
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200445 surface = window_get_surface(dialog->window);
446 cr = cairo_create(surface);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500447
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500448 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200449 cairo_rectangle(cr, allocation.x, allocation.y,
450 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200451 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
452 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500453 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200454
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500455 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500456 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200457 f = 1.0;
458 else
459 f = 0.7;
460
461 cx = allocation.width / 2.0;
462 cy = allocation.height / 2.0;
463 r = (cx < cy ? cx : cy) * 0.4;
464 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
465 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
466 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
467 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
468 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500469 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200470 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
471 cairo_fill(cr);
472
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500473 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500474 allocation.x + cx - r,
475 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200476
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200477 cairo_destroy(cr);
478
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200479 cairo_surface_destroy(surface);
480}
481
482static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500483unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200484 struct input *input, uint32_t time,
Daniel Stone5d663712012-05-04 11:21:55 +0100485 uint32_t button, uint32_t state, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200486{
487 struct unlock_dialog *dialog = data;
488 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200489
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500490 if (button == BTN_LEFT) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200491 if (state == 0 && !dialog->closing) {
492 display_defer(desktop->display, &desktop->unlock_task);
493 dialog->closing = 1;
494 }
495 }
496}
497
498static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200499unlock_dialog_keyboard_focus_handler(struct window *window,
500 struct input *device, void *data)
501{
502 window_schedule_redraw(window);
503}
504
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500505static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500506unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400507 struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400508 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500509{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500510 struct unlock_dialog *dialog = data;
511
512 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500513 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500514
Ander Conselvan de Oliveira1042dc12012-05-22 15:39:42 +0300515 return WL_CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500516}
517
518static void
519unlock_dialog_widget_leave_handler(struct widget *widget,
520 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200521{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500522 struct unlock_dialog *dialog = data;
523
524 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500525 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200526}
527
528static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500529unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200530{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500531 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200532 struct unlock_dialog *dialog;
533
534 dialog = malloc(sizeof *dialog);
535 if (!dialog)
536 return NULL;
537 memset(dialog, 0, sizeof *dialog);
538
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500539 dialog->window = window_create(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500540 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200541 window_set_title(dialog->window, "Unlock your desktop");
Benjamin Franzke8193bc12011-11-23 19:35:07 +0100542 window_set_custom(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200543
544 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200545 window_set_keyboard_focus_handler(dialog->window,
546 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500547 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500548 widget_set_redraw_handler(dialog->widget,
549 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500550 widget_set_enter_handler(dialog->button,
551 unlock_dialog_widget_enter_handler);
552 widget_set_leave_handler(dialog->button,
553 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500554 widget_set_button_handler(dialog->button,
555 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200556
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500557 desktop_shell_set_lock_surface(desktop->shell,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200558 window_get_wl_shell_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500559
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200560 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200561
562 return dialog;
563}
564
565static void
566unlock_dialog_destroy(struct unlock_dialog *dialog)
567{
568 window_destroy(dialog->window);
569 free(dialog);
570}
571
572static void
573unlock_dialog_finish(struct task *task, uint32_t events)
574{
575 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100576 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200577
578 desktop_shell_unlock(desktop->shell);
579 unlock_dialog_destroy(desktop->unlock_dialog);
580 desktop->unlock_dialog = NULL;
581}
582
583static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400584desktop_shell_configure(void *data,
585 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400586 uint32_t edges,
Pekka Paalanen068ae942011-11-28 14:11:15 +0200587 struct wl_shell_surface *shell_surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400588 int32_t width, int32_t height)
589{
Pekka Paalanen068ae942011-11-28 14:11:15 +0200590 struct window *window = wl_shell_surface_get_user_data(shell_surface);
591 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400592
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400593 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400594}
595
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200596static void
597desktop_shell_prepare_lock_surface(void *data,
598 struct desktop_shell *desktop_shell)
599{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200600 struct desktop *desktop = data;
601
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200602 if (!key_locking) {
603 desktop_shell_unlock(desktop->shell);
604 return;
605 }
606
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200607 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500608 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200609 desktop->unlock_dialog->desktop = desktop;
610 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200611}
612
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400613static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200614 desktop_shell_configure,
615 desktop_shell_prepare_lock_surface
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400616};
617
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100618static struct background *
619background_create(struct desktop *desktop)
620{
621 struct background *background;
622
623 background = malloc(sizeof *background);
624 memset(background, 0, sizeof *background);
625
626 background->base.configure = background_configure;
Kristian Høgsberg009ac0a2012-01-31 15:24:48 -0500627 background->window = window_create(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500628 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100629 window_set_custom(background->window);
630 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500631 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100632
633 return background;
634}
635
636static void
637create_output(struct desktop *desktop, uint32_t id)
638{
639 struct output *output;
640
641 output = calloc(1, sizeof *output);
642 if (!output)
643 return;
644
645 output->output = wl_display_bind(display_get_display(desktop->display),
646 id, &wl_output_interface);
647
648 wl_list_insert(&desktop->outputs, &output->link);
649}
650
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400651static void
652global_handler(struct wl_display *display, uint32_t id,
653 const char *interface, uint32_t version, void *data)
654{
655 struct desktop *desktop = data;
656
657 if (!strcmp(interface, "desktop_shell")) {
658 desktop->shell =
659 wl_display_bind(display, id, &desktop_shell_interface);
660 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100661 } else if (!strcmp(interface, "wl_output")) {
662 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400663 }
664}
665
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500666static void
667launcher_section_done(void *data)
668{
669 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100670 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500671
672 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
673 fprintf(stderr, "invalid launcher section\n");
674 return;
675 }
676
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100677 wl_list_for_each(output, &desktop->outputs, link)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500678 panel_add_launcher(output->panel,
679 key_launcher_icon, key_launcher_path);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100680
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500681 free(key_launcher_icon);
682 key_launcher_icon = NULL;
683 free(key_launcher_path);
684 key_launcher_path = NULL;
685}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400686
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500687static void
688add_default_launcher(struct desktop *desktop)
689{
690 struct output *output;
691
692 wl_list_for_each(output, &desktop->outputs, link)
693 panel_add_launcher(output->panel,
694 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +0100695 BINDIR "/weston-terminal");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500696}
697
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400698int main(int argc, char *argv[])
699{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200700 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200701 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100702 struct output *output;
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500703 int ret;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400704
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200705 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100706 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200707
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400708 desktop.display = display_create(argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400709 if (desktop.display == NULL) {
710 fprintf(stderr, "failed to create display: %m\n");
711 return -1;
712 }
713
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400714 wl_display_add_global_listener(display_get_display(desktop.display),
715 global_handler, &desktop);
716
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100717 wl_list_for_each(output, &desktop.outputs, link) {
Pekka Paalanen068ae942011-11-28 14:11:15 +0200718 struct wl_shell_surface *s;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100719
720 output->panel = panel_create(desktop.display);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200721 s = window_get_wl_shell_surface(output->panel->window);
722 desktop_shell_set_panel(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100723
724 output->background = background_create(&desktop);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200725 s = window_get_wl_shell_surface(output->background->window);
726 desktop_shell_set_background(desktop.shell, output->output, s);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100727 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400728
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200729 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500730 ret = parse_config_file(config_file,
731 config_sections, ARRAY_LENGTH(config_sections),
732 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200733 free(config_file);
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500734 if (ret < 0)
735 add_default_launcher(&desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500736
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400737 signal(SIGCHLD, sigchild_handler);
738
739 display_run(desktop.display);
740
741 return 0;
742}