blob: 082a30a041e31849e1107cce55eff9b2949d7198 [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>
Martin Minarik1e51a872012-06-08 00:39:11 +020033#include <sys/timerfd.h>
34#include <sys/epoll.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040035#include <linux/input.h>
Tiago Vignatti61500722012-05-23 22:06:28 +030036#include <libgen.h>
Kristian Høgsbergd1936b92012-07-23 22:59:33 -040037#include <ctype.h>
Martin Minarik1e51a872012-06-08 00:39:11 +020038#include <time.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040039
Pekka Paalanen50719bc2011-11-22 14:18:50 +020040#include <wayland-client.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040041#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040042#include "../shared/cairo-util.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050043#include "../shared/config-parser.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040044
Pekka Paalanen50719bc2011-11-22 14:18:50 +020045#include "desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040046
47struct desktop {
48 struct display *display;
49 struct desktop_shell *shell;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020050 struct unlock_dialog *unlock_dialog;
51 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010052 struct wl_list outputs;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -040053
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +030054 struct window *grab_window;
55 struct widget *grab_widget;
56
Scott Moreauec116022012-07-22 18:23:52 -060057 enum cursor_type grab_cursor;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010058};
59
60struct surface {
61 void (*configure)(void *data,
62 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040063 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010064 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040065};
66
67struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010068 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040069 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050070 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050071 struct wl_list launcher_list;
Martin Minarik1e51a872012-06-08 00:39:11 +020072 struct panel_clock *clock;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040073};
74
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010075struct background {
76 struct surface base;
77 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050078 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010079};
80
81struct output {
82 struct wl_output *output;
83 struct wl_list link;
84
85 struct panel *panel;
86 struct background *background;
87};
88
Kristian Høgsberg53880802012-01-09 11:16:50 -050089struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050090 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040091 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040092 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050093 int focused, pressed;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -040094 char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050095 struct wl_list link;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -040096 struct wl_array envp;
97 struct wl_array argv;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040098};
99
Martin Minarik1e51a872012-06-08 00:39:11 +0200100struct panel_clock {
101 struct widget *widget;
102 struct panel *panel;
Martin Minarik1e51a872012-06-08 00:39:11 +0200103 struct task clock_task;
104 int clock_fd;
105};
106
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200107struct unlock_dialog {
108 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500109 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500110 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500111 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200112 int closing;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200113 struct desktop *desktop;
114};
115
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500116static char *key_background_image = DATADIR "/weston/pattern.png";
117static char *key_background_type = "tile";
118static uint32_t key_panel_color = 0xaa000000;
119static uint32_t key_background_color = 0xff002244;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500120static char *key_launcher_icon;
121static char *key_launcher_path;
122static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200123static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500124
125static const struct config_key shell_config_keys[] = {
126 { "background-image", CONFIG_KEY_STRING, &key_background_image },
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500127 { "background-type", CONFIG_KEY_STRING, &key_background_type },
Scott Moreaufa1de692012-01-27 13:25:49 -0700128 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
129 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200130 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500131};
132
133static const struct config_key launcher_config_keys[] = {
134 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
135 { "path", CONFIG_KEY_STRING, &key_launcher_path },
136};
137
138static const struct config_section config_sections[] = {
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200139 { "shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500140 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
141 { "launcher",
142 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
143 launcher_section_done }
144};
145
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400146static void
147sigchild_handler(int s)
148{
149 int status;
150 pid_t pid;
151
152 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
153 fprintf(stderr, "child %d exited\n", pid);
154}
155
156static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200157menu_func(struct window *window, int index, void *data)
158{
159 printf("Selected index %d from a panel menu.\n", index);
160}
161
162static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500163show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400164{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500165 int32_t x, y;
166 static const char *entries[] = {
167 "Roy", "Pris", "Leon", "Zhora"
168 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400169
170 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200171 window_show_menu(window_get_display(panel->window),
172 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200173 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400174}
175
176static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500177panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400178{
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400179 char **argv;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400180 pid_t pid;
181
182 pid = fork();
183 if (pid < 0) {
184 fprintf(stderr, "fork failed: %m\n");
185 return;
186 }
187
188 if (pid)
189 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100190
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400191 argv = widget->argv.data;
192 if (execve(argv[0], argv, widget->envp.data) < 0) {
193 fprintf(stderr, "execl '%s' failed: %m\n", argv[0]);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400194 exit(1);
195 }
196}
197
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400198static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500199panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400200{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500201 struct panel_launcher *launcher = data;
202 cairo_surface_t *surface;
203 struct rectangle allocation;
204 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400205
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500206 surface = window_get_surface(launcher->panel->window);
207 cr = cairo_create(surface);
208
209 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500210 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500211 allocation.x++;
212 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400213 }
214
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500215 cairo_set_source_surface(cr, launcher->icon,
216 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400217 cairo_paint(cr);
218
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500219 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400220 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500221 cairo_mask_surface(cr, launcher->icon,
222 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400223 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400224
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500225 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400226}
227
Tiago Vignatti61500722012-05-23 22:06:28 +0300228static int
229panel_launcher_motion_handler(struct widget *widget, struct input *input,
230 uint32_t time, float x, float y, void *data)
231{
232 struct panel_launcher *launcher = data;
233
234 widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
235
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300236 return CURSOR_LEFT_PTR;
Tiago Vignatti61500722012-05-23 22:06:28 +0300237}
238
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400239static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500240set_hex_color(cairo_t *cr, uint32_t color)
241{
242 cairo_set_source_rgba(cr,
243 ((color >> 16) & 0xff) / 255.0,
244 ((color >> 8) & 0xff) / 255.0,
245 ((color >> 0) & 0xff) / 255.0,
246 ((color >> 24) & 0xff) / 255.0);
247}
248
249static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500250panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400251{
252 cairo_surface_t *surface;
253 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500254 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400255
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500256 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400257 cr = cairo_create(surface);
258 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500259 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400260 cairo_paint(cr);
261
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400262 cairo_destroy(cr);
263 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400264}
265
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500266static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500267panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400268 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500269{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500270 struct panel_launcher *launcher = data;
271
272 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500273 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500274
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300275 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500276}
277
278static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500279panel_launcher_leave_handler(struct widget *widget,
280 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400281{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500282 struct panel_launcher *launcher = data;
283
284 launcher->focused = 0;
Tiago Vignatti61500722012-05-23 22:06:28 +0300285 widget_destroy_tooltip(widget);
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500286 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400287}
288
289static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500290panel_launcher_button_handler(struct widget *widget,
291 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100292 uint32_t button,
293 enum wl_pointer_button_state state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400294{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500295 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400296
Kristian Høgsberg53880802012-01-09 11:16:50 -0500297 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500298 widget_schedule_redraw(widget);
Daniel Stone4dbadb12012-05-30 16:31:51 +0100299 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500300 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500301}
302
Martin Minarik1e51a872012-06-08 00:39:11 +0200303static void
304clock_func(struct task *task, uint32_t events)
305{
306 struct panel_clock *clock =
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400307 container_of(task, struct panel_clock, clock_task);
Kristian Høgsberg70226bb2012-06-08 16:54:52 -0400308 uint64_t exp;
Martin Minarik1e51a872012-06-08 00:39:11 +0200309
Martin Olsson8df662a2012-07-08 03:03:47 +0200310 if (read(clock->clock_fd, &exp, sizeof exp) != sizeof exp)
311 abort();
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400312 widget_schedule_redraw(clock->widget);
Martin Minarik1e51a872012-06-08 00:39:11 +0200313}
314
315static void
316panel_clock_redraw_handler(struct widget *widget, void *data)
317{
318 cairo_surface_t *surface;
319 struct panel_clock *clock = data;
320 cairo_t *cr;
321 struct rectangle allocation;
322 cairo_text_extents_t extents;
323 cairo_font_extents_t font_extents;
Martin Minarik1e51a872012-06-08 00:39:11 +0200324 time_t rawtime;
325 struct tm * timeinfo;
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400326 char string[128];
Martin Minarik1e51a872012-06-08 00:39:11 +0200327
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400328 time(&rawtime);
329 timeinfo = localtime(&rawtime);
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400330 strftime(string, sizeof string, "%a %b %d, %I:%M %p", timeinfo);
Martin Minarik1e51a872012-06-08 00:39:11 +0200331
332 widget_get_allocation(widget, &allocation);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400333 if (allocation.width == 0)
334 return;
Martin Minarik1e51a872012-06-08 00:39:11 +0200335
336 surface = window_get_surface(clock->panel->window);
337 cr = cairo_create(surface);
Martin Minarik1e51a872012-06-08 00:39:11 +0200338 cairo_select_font_face(cr, "sans",
339 CAIRO_FONT_SLANT_NORMAL,
340 CAIRO_FONT_WEIGHT_NORMAL);
341 cairo_set_font_size(cr, 14);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400342 cairo_text_extents(cr, string, &extents);
Martin Minarik1e51a872012-06-08 00:39:11 +0200343 cairo_font_extents (cr, &font_extents);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400344 cairo_move_to(cr, allocation.x + 5,
345 allocation.y + 3 * (allocation.height >> 2) + 1);
346 cairo_set_source_rgb(cr, 0, 0, 0);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400347 cairo_show_text(cr, string);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400348 cairo_move_to(cr, allocation.x + 4,
349 allocation.y + 3 * (allocation.height >> 2));
350 cairo_set_source_rgb(cr, 1, 1, 1);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400351 cairo_show_text(cr, string);
Martin Minarik1e51a872012-06-08 00:39:11 +0200352 cairo_destroy(cr);
353}
354
355static int
356clock_timer_reset(struct panel_clock *clock)
357{
358 struct itimerspec its;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400359
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400360 its.it_interval.tv_sec = 60;
Martin Minarik1e51a872012-06-08 00:39:11 +0200361 its.it_interval.tv_nsec = 0;
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400362 its.it_value.tv_sec = 60;
Martin Minarik1e51a872012-06-08 00:39:11 +0200363 its.it_value.tv_nsec = 0;
364 if (timerfd_settime(clock->clock_fd, 0, &its, NULL) < 0) {
365 fprintf(stderr, "could not set timerfd\n: %m");
366 return -1;
367 }
368
369 return 0;
370}
371
372static void
373panel_add_clock(struct panel *panel)
374{
375 struct panel_clock *clock;
376 int timerfd;
377
378 timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
379 if (timerfd < 0) {
380 fprintf(stderr, "could not create timerfd\n: %m");
381 return;
382 }
383
384 clock = malloc(sizeof *clock);
385 memset(clock, 0, sizeof *clock);
386 clock->panel = panel;
387 panel->clock = clock;
388 clock->clock_fd = timerfd;
389
390 clock->clock_task.run = clock_func;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400391 display_watch_fd(window_get_display(panel->window), clock->clock_fd,
392 EPOLLIN, &clock->clock_task);
Martin Minarik1e51a872012-06-08 00:39:11 +0200393 clock_timer_reset(clock);
394
395 clock->widget = widget_add_widget(panel->widget, clock);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400396 widget_set_redraw_handler(clock->widget, panel_clock_redraw_handler);
Martin Minarik1e51a872012-06-08 00:39:11 +0200397}
398
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500399static void
400panel_button_handler(struct widget *widget,
401 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100402 uint32_t button,
403 enum wl_pointer_button_state state, void *data)
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500404{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500405 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500406
Daniel Stone4dbadb12012-05-30 16:31:51 +0100407 if (button == BTN_RIGHT && state == WL_POINTER_BUTTON_STATE_PRESSED)
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500408 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400409}
410
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100411static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500412panel_resize_handler(struct widget *widget,
413 int32_t width, int32_t height, void *data)
414{
415 struct panel_launcher *launcher;
416 struct panel *panel = data;
417 int x, y, w, h;
418
419 x = 10;
420 y = 16;
421 wl_list_for_each(launcher, &panel->launcher_list, link) {
422 w = cairo_image_surface_get_width(launcher->icon);
423 h = cairo_image_surface_get_height(launcher->icon);
424 widget_set_allocation(launcher->widget,
425 x, y - h / 2, w + 1, h + 1);
426 x += w + 10;
427 }
Martin Minarik1e51a872012-06-08 00:39:11 +0200428 h=20;
429 w=170;
Pekka Paalanen01b17252012-06-12 17:42:26 +0300430
431 if (panel->clock)
432 widget_set_allocation(panel->clock->widget,
433 width - w - 8, y - h / 2, w + 1, h + 1);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500434}
435
436static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100437panel_configure(void *data,
438 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400439 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100440 int32_t width, int32_t height)
441{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500442 struct surface *surface = window_get_user_data(window);
443 struct panel *panel = container_of(surface, struct panel, base);
444
445 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100446}
447
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400448static struct panel *
449panel_create(struct display *display)
450{
451 struct panel *panel;
452
453 panel = malloc(sizeof *panel);
454 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400455
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100456 panel->base.configure = panel_configure;
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -0400457 panel->window = window_create_custom(display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500458 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500459 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400460
461 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400462 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500463
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500464 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
465 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500466 widget_set_button_handler(panel->widget, panel_button_handler);
Rafal Mielniczukb9e513c2012-06-09 20:33:29 +0200467
468 panel_add_clock(panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400469
470 return panel;
471}
472
473static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500474panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400475{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500476 struct panel_launcher *launcher;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400477 char *start, *p, *eq, **ps;
478 int i, j, k;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400479
Kristian Høgsberg53880802012-01-09 11:16:50 -0500480 launcher = malloc(sizeof *launcher);
481 memset(launcher, 0, sizeof *launcher);
482 launcher->icon = cairo_image_surface_create_from_png(icon);
483 launcher->path = strdup(path);
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400484
485 wl_array_init(&launcher->envp);
486 wl_array_init(&launcher->argv);
487 for (i = 0; __environ[i]; i++) {
488 ps = wl_array_add(&launcher->envp, sizeof *ps);
489 *ps = __environ[i];
490 }
491 j = 0;
492
493 start = launcher->path;
494 while (*start) {
495 for (p = start, eq = NULL; *p && !isspace(*p); p++)
496 if (*p == '=')
497 eq = p;
498
499 if (eq && j == 0) {
500 ps = launcher->envp.data;
501 for (k = 0; k < i; k++)
502 if (strncmp(ps[k], start, eq - start) == 0) {
503 ps[k] = start;
504 break;
505 }
506 if (k == i) {
507 ps = wl_array_add(&launcher->envp, sizeof *ps);
508 *ps = start;
509 i++;
510 }
511 } else {
512 ps = wl_array_add(&launcher->argv, sizeof *ps);
513 *ps = start;
514 j++;
515 }
516
517 while (*p && isspace(*p))
518 *p++ = '\0';
519
520 start = p;
521 }
522
523 ps = wl_array_add(&launcher->envp, sizeof *ps);
524 *ps = NULL;
525 ps = wl_array_add(&launcher->argv, sizeof *ps);
526 *ps = NULL;
527
Kristian Høgsberg53880802012-01-09 11:16:50 -0500528 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500529 wl_list_insert(panel->launcher_list.prev, &launcher->link);
530
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500531 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500532 widget_set_enter_handler(launcher->widget,
533 panel_launcher_enter_handler);
534 widget_set_leave_handler(launcher->widget,
535 panel_launcher_leave_handler);
536 widget_set_button_handler(launcher->widget,
537 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500538 widget_set_redraw_handler(launcher->widget,
539 panel_launcher_redraw_handler);
Tiago Vignatti61500722012-05-23 22:06:28 +0300540 widget_set_motion_handler(launcher->widget,
541 panel_launcher_motion_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400542}
543
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500544enum {
545 BACKGROUND_SCALE,
546 BACKGROUND_TILE
547};
548
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400549static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500550background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400551{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500552 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400553 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400554 cairo_pattern_t *pattern;
555 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400556 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400557 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500558 struct rectangle allocation;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500559 int type = -1;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400560
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500561 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400562
563 cr = cairo_create(surface);
564 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
565 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
566 cairo_paint(cr);
567
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500568 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500569 image = NULL;
570 if (key_background_image)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400571 image = load_cairo_surface(key_background_image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500572
573 if (strcmp(key_background_type, "scale") == 0)
574 type = BACKGROUND_SCALE;
575 else if (strcmp(key_background_type, "tile") == 0)
576 type = BACKGROUND_TILE;
577 else
578 fprintf(stderr, "invalid background-type: %s\n",
579 key_background_type);
580
581 if (image && type != -1) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400582 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500583 switch (type) {
584 case BACKGROUND_SCALE:
585 sx = (double) cairo_image_surface_get_width(image) /
586 allocation.width;
587 sy = (double) cairo_image_surface_get_height(image) /
588 allocation.height;
589 cairo_matrix_init_scale(&matrix, sx, sy);
590 cairo_pattern_set_matrix(pattern, &matrix);
591 break;
592 case BACKGROUND_TILE:
593 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
594 break;
595 }
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400596 cairo_set_source(cr, pattern);
597 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400598 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500599 } else {
600 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400601 }
602
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500603 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400604 cairo_destroy(cr);
605 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400606}
607
608static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100609background_configure(void *data,
610 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400611 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100612 int32_t width, int32_t height)
613{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500614 struct background *background =
615 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100616
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500617 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100618}
619
620static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500621unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200622{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500623 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200624 struct rectangle allocation;
625 cairo_t *cr;
626 cairo_surface_t *surface;
627 cairo_pattern_t *pat;
628 double cx, cy, r, f;
629
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200630 surface = window_get_surface(dialog->window);
631 cr = cairo_create(surface);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500632
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500633 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200634 cairo_rectangle(cr, allocation.x, allocation.y,
635 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200636 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
637 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500638 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200639
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500640 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500641 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200642 f = 1.0;
643 else
644 f = 0.7;
645
646 cx = allocation.width / 2.0;
647 cy = allocation.height / 2.0;
648 r = (cx < cy ? cx : cy) * 0.4;
649 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
650 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
651 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
652 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
653 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500654 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200655 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
656 cairo_fill(cr);
657
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500658 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500659 allocation.x + cx - r,
660 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200661
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200662 cairo_destroy(cr);
663
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200664 cairo_surface_destroy(surface);
665}
666
667static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500668unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200669 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100670 uint32_t button,
671 enum wl_pointer_button_state state, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200672{
673 struct unlock_dialog *dialog = data;
674 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200675
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500676 if (button == BTN_LEFT) {
Daniel Stone4dbadb12012-05-30 16:31:51 +0100677 if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
678 !dialog->closing) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200679 display_defer(desktop->display, &desktop->unlock_task);
680 dialog->closing = 1;
681 }
682 }
683}
684
685static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200686unlock_dialog_keyboard_focus_handler(struct window *window,
687 struct input *device, void *data)
688{
689 window_schedule_redraw(window);
690}
691
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500692static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500693unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400694 struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400695 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500696{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500697 struct unlock_dialog *dialog = data;
698
699 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500700 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500701
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300702 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500703}
704
705static void
706unlock_dialog_widget_leave_handler(struct widget *widget,
707 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200708{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500709 struct unlock_dialog *dialog = data;
710
711 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500712 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200713}
714
715static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500716unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200717{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500718 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200719 struct unlock_dialog *dialog;
720
721 dialog = malloc(sizeof *dialog);
722 if (!dialog)
723 return NULL;
724 memset(dialog, 0, sizeof *dialog);
725
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400726 dialog->window = window_create_custom(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500727 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200728 window_set_title(dialog->window, "Unlock your desktop");
729
730 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200731 window_set_keyboard_focus_handler(dialog->window,
732 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500733 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500734 widget_set_redraw_handler(dialog->widget,
735 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500736 widget_set_enter_handler(dialog->button,
737 unlock_dialog_widget_enter_handler);
738 widget_set_leave_handler(dialog->button,
739 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500740 widget_set_button_handler(dialog->button,
741 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200742
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500743 desktop_shell_set_lock_surface(desktop->shell,
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400744 window_get_wl_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500745
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200746 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200747
748 return dialog;
749}
750
751static void
752unlock_dialog_destroy(struct unlock_dialog *dialog)
753{
754 window_destroy(dialog->window);
755 free(dialog);
756}
757
758static void
759unlock_dialog_finish(struct task *task, uint32_t events)
760{
761 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100762 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200763
764 desktop_shell_unlock(desktop->shell);
765 unlock_dialog_destroy(desktop->unlock_dialog);
766 desktop->unlock_dialog = NULL;
767}
768
769static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400770desktop_shell_configure(void *data,
771 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400772 uint32_t edges,
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400773 struct wl_surface *surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400774 int32_t width, int32_t height)
775{
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400776 struct window *window = wl_surface_get_user_data(surface);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200777 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400778
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400779 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400780}
781
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200782static void
783desktop_shell_prepare_lock_surface(void *data,
784 struct desktop_shell *desktop_shell)
785{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200786 struct desktop *desktop = data;
787
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200788 if (!key_locking) {
789 desktop_shell_unlock(desktop->shell);
790 return;
791 }
792
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200793 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500794 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200795 desktop->unlock_dialog->desktop = desktop;
796 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200797}
798
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300799static void
800desktop_shell_grab_cursor(void *data,
801 struct desktop_shell *desktop_shell,
802 uint32_t cursor)
803{
804 struct desktop *desktop = data;
805
806 switch (cursor) {
807 case DESKTOP_SHELL_CURSOR_BUSY:
808 desktop->grab_cursor = CURSOR_WATCH;
809 break;
810 case DESKTOP_SHELL_CURSOR_MOVE:
811 desktop->grab_cursor = CURSOR_DRAGGING;
812 break;
813 case DESKTOP_SHELL_CURSOR_RESIZE_TOP:
814 desktop->grab_cursor = CURSOR_TOP;
815 break;
816 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM:
817 desktop->grab_cursor = CURSOR_BOTTOM;
818 break;
819 case DESKTOP_SHELL_CURSOR_RESIZE_LEFT:
820 desktop->grab_cursor = CURSOR_LEFT;
821 break;
822 case DESKTOP_SHELL_CURSOR_RESIZE_RIGHT:
823 desktop->grab_cursor = CURSOR_RIGHT;
824 break;
825 case DESKTOP_SHELL_CURSOR_RESIZE_TOP_LEFT:
826 desktop->grab_cursor = CURSOR_TOP_LEFT;
827 break;
828 case DESKTOP_SHELL_CURSOR_RESIZE_TOP_RIGHT:
829 desktop->grab_cursor = CURSOR_TOP_RIGHT;
830 break;
831 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_LEFT:
832 desktop->grab_cursor = CURSOR_BOTTOM_LEFT;
833 break;
834 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_RIGHT:
835 desktop->grab_cursor = CURSOR_BOTTOM_RIGHT;
836 break;
837 case DESKTOP_SHELL_CURSOR_ARROW:
838 default:
839 desktop->grab_cursor = CURSOR_LEFT_PTR;
840 }
841}
842
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400843static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200844 desktop_shell_configure,
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300845 desktop_shell_prepare_lock_surface,
846 desktop_shell_grab_cursor
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400847};
848
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100849static struct background *
850background_create(struct desktop *desktop)
851{
852 struct background *background;
853
854 background = malloc(sizeof *background);
855 memset(background, 0, sizeof *background);
856
857 background->base.configure = background_configure;
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400858 background->window = window_create_custom(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500859 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100860 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500861 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100862
863 return background;
864}
865
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400866static int
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300867grab_surface_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400868 float x, float y, void *data)
869{
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300870 struct desktop *desktop = data;
871
872 return desktop->grab_cursor;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400873}
874
875static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300876grab_surface_create(struct desktop *desktop)
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400877{
878 struct wl_surface *s;
879
Ander Conselvan de Oliveira07a91cd2012-07-16 14:15:50 +0300880 desktop->grab_window = window_create_custom(desktop->display);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300881 window_set_user_data(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400882
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300883 s = window_get_wl_surface(desktop->grab_window);
884 desktop_shell_set_grab_surface(desktop->shell, s);
885
886 desktop->grab_widget =
887 window_add_widget(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400888 /* We set the allocation to 1x1 at 0,0 so the fake enter event
889 * at 0,0 will go to this widget. */
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300890 widget_set_allocation(desktop->grab_widget, 0, 0, 1, 1);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400891
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300892 widget_set_enter_handler(desktop->grab_widget,
893 grab_surface_enter_handler);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400894}
895
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100896static void
897create_output(struct desktop *desktop, uint32_t id)
898{
899 struct output *output;
900
901 output = calloc(1, sizeof *output);
902 if (!output)
903 return;
904
905 output->output = wl_display_bind(display_get_display(desktop->display),
906 id, &wl_output_interface);
907
908 wl_list_insert(&desktop->outputs, &output->link);
909}
910
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400911static void
912global_handler(struct wl_display *display, uint32_t id,
913 const char *interface, uint32_t version, void *data)
914{
915 struct desktop *desktop = data;
916
917 if (!strcmp(interface, "desktop_shell")) {
918 desktop->shell =
919 wl_display_bind(display, id, &desktop_shell_interface);
920 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100921 } else if (!strcmp(interface, "wl_output")) {
922 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400923 }
924}
925
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500926static void
927launcher_section_done(void *data)
928{
929 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100930 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500931
932 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
933 fprintf(stderr, "invalid launcher section\n");
934 return;
935 }
936
Martin Minarik1e51a872012-06-08 00:39:11 +0200937 wl_list_for_each(output, &desktop->outputs, link) {
Kristian Høgsberg53880802012-01-09 11:16:50 -0500938 panel_add_launcher(output->panel,
939 key_launcher_icon, key_launcher_path);
Martin Minarik1e51a872012-06-08 00:39:11 +0200940 }
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100941
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500942 free(key_launcher_icon);
943 key_launcher_icon = NULL;
944 free(key_launcher_path);
945 key_launcher_path = NULL;
946}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400947
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500948static void
949add_default_launcher(struct desktop *desktop)
950{
951 struct output *output;
952
953 wl_list_for_each(output, &desktop->outputs, link)
954 panel_add_launcher(output->panel,
955 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +0100956 BINDIR "/weston-terminal");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500957}
958
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400959int main(int argc, char *argv[])
960{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200961 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200962 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100963 struct output *output;
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500964 int ret;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400965
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200966 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100967 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200968
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400969 desktop.display = display_create(argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400970 if (desktop.display == NULL) {
971 fprintf(stderr, "failed to create display: %m\n");
972 return -1;
973 }
974
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400975 display_set_user_data(desktop.display, &desktop);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400976 wl_display_add_global_listener(display_get_display(desktop.display),
977 global_handler, &desktop);
978
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100979 wl_list_for_each(output, &desktop.outputs, link) {
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400980 struct wl_surface *surface;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100981
982 output->panel = panel_create(desktop.display);
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -0400983 surface = window_get_wl_surface(output->panel->window);
984 desktop_shell_set_panel(desktop.shell,
985 output->output, surface);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100986
987 output->background = background_create(&desktop);
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400988 surface = window_get_wl_surface(output->background->window);
989 desktop_shell_set_background(desktop.shell,
990 output->output, surface);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100991 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400992
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300993 grab_surface_create(&desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400994
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200995 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500996 ret = parse_config_file(config_file,
997 config_sections, ARRAY_LENGTH(config_sections),
998 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200999 free(config_file);
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -05001000 if (ret < 0)
1001 add_default_launcher(&desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -05001002
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001003 signal(SIGCHLD, sigchild_handler);
1004
1005 display_run(desktop.display);
1006
1007 return 0;
1008}