blob: cf282465439806fb0fa0d75cf1c8cd4012a56c9c [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>
Martin Minarik1e51a872012-06-08 00:39:11 +020037#include <time.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040038
Pekka Paalanen50719bc2011-11-22 14:18:50 +020039#include <wayland-client.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040040#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040041#include "../shared/cairo-util.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050042#include "../shared/config-parser.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040043
Pekka Paalanen50719bc2011-11-22 14:18:50 +020044#include "desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040045
46struct desktop {
47 struct display *display;
48 struct desktop_shell *shell;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020049 struct unlock_dialog *unlock_dialog;
50 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010051 struct wl_list outputs;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -040052
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +030053 struct window *grab_window;
54 struct widget *grab_widget;
55
56 enum desktop_shell_cursor grab_cursor;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010057};
58
59struct surface {
60 void (*configure)(void *data,
61 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040062 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010063 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040064};
65
66struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010067 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040068 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050069 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050070 struct wl_list launcher_list;
Martin Minarik1e51a872012-06-08 00:39:11 +020071 struct panel_clock *clock;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040072};
73
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010074struct background {
75 struct surface base;
76 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -050077 struct widget *widget;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010078};
79
80struct output {
81 struct wl_output *output;
82 struct wl_list link;
83
84 struct panel *panel;
85 struct background *background;
86};
87
Kristian Høgsberg53880802012-01-09 11:16:50 -050088struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -050089 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -040090 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040091 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -050092 int focused, pressed;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040093 const char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050094 struct wl_list link;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040095};
96
Martin Minarik1e51a872012-06-08 00:39:11 +020097struct panel_clock {
98 struct widget *widget;
99 struct panel *panel;
Martin Minarik1e51a872012-06-08 00:39:11 +0200100 struct task clock_task;
101 int clock_fd;
102};
103
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200104struct unlock_dialog {
105 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500106 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500107 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500108 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200109 int closing;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200110 struct desktop *desktop;
111};
112
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500113static char *key_background_image = DATADIR "/weston/pattern.png";
114static char *key_background_type = "tile";
115static uint32_t key_panel_color = 0xaa000000;
116static uint32_t key_background_color = 0xff002244;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500117static char *key_launcher_icon;
118static char *key_launcher_path;
119static void launcher_section_done(void *data);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200120static int key_locking = 1;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500121
122static const struct config_key shell_config_keys[] = {
123 { "background-image", CONFIG_KEY_STRING, &key_background_image },
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500124 { "background-type", CONFIG_KEY_STRING, &key_background_type },
Scott Moreaufa1de692012-01-27 13:25:49 -0700125 { "panel-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_panel_color },
126 { "background-color", CONFIG_KEY_UNSIGNED_INTEGER, &key_background_color },
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200127 { "locking", CONFIG_KEY_BOOLEAN, &key_locking },
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500128};
129
130static const struct config_key launcher_config_keys[] = {
131 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
132 { "path", CONFIG_KEY_STRING, &key_launcher_path },
133};
134
135static const struct config_section config_sections[] = {
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200136 { "shell",
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500137 shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
138 { "launcher",
139 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
140 launcher_section_done }
141};
142
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400143static void
144sigchild_handler(int s)
145{
146 int status;
147 pid_t pid;
148
149 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
150 fprintf(stderr, "child %d exited\n", pid);
151}
152
153static void
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200154menu_func(struct window *window, int index, void *data)
155{
156 printf("Selected index %d from a panel menu.\n", index);
157}
158
159static void
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500160show_menu(struct panel *panel, struct input *input, uint32_t time)
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400161{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500162 int32_t x, y;
163 static const char *entries[] = {
164 "Roy", "Pris", "Leon", "Zhora"
165 };
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400166
167 input_get_position(input, &x, &y);
Pekka Paalanen6d174cf2012-01-19 15:17:59 +0200168 window_show_menu(window_get_display(panel->window),
169 input, time, panel->window,
Pekka Paalanen9e30a822012-01-19 16:40:28 +0200170 x - 10, y - 10, menu_func, entries, 4);
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400171}
172
173static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500174panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400175{
176 pid_t pid;
177
178 pid = fork();
179 if (pid < 0) {
180 fprintf(stderr, "fork failed: %m\n");
181 return;
182 }
183
184 if (pid)
185 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100186
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500187 if (execl(widget->path, widget->path, NULL) < 0) {
Pekka Paalanena291ae52012-01-27 09:50:02 +0200188 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400189 exit(1);
190 }
191}
192
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400193static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500194panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400195{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500196 struct panel_launcher *launcher = data;
197 cairo_surface_t *surface;
198 struct rectangle allocation;
199 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400200
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500201 surface = window_get_surface(launcher->panel->window);
202 cr = cairo_create(surface);
203
204 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500205 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500206 allocation.x++;
207 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400208 }
209
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500210 cairo_set_source_surface(cr, launcher->icon,
211 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400212 cairo_paint(cr);
213
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500214 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400215 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500216 cairo_mask_surface(cr, launcher->icon,
217 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400218 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400219
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500220 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400221}
222
Tiago Vignatti61500722012-05-23 22:06:28 +0300223static int
224panel_launcher_motion_handler(struct widget *widget, struct input *input,
225 uint32_t time, float x, float y, void *data)
226{
227 struct panel_launcher *launcher = data;
228
229 widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
230
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300231 return CURSOR_LEFT_PTR;
Tiago Vignatti61500722012-05-23 22:06:28 +0300232}
233
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400234static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500235set_hex_color(cairo_t *cr, uint32_t color)
236{
237 cairo_set_source_rgba(cr,
238 ((color >> 16) & 0xff) / 255.0,
239 ((color >> 8) & 0xff) / 255.0,
240 ((color >> 0) & 0xff) / 255.0,
241 ((color >> 24) & 0xff) / 255.0);
242}
243
244static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500245panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400246{
247 cairo_surface_t *surface;
248 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500249 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400250
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500251 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400252 cr = cairo_create(surface);
253 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500254 set_hex_color(cr, key_panel_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400255 cairo_paint(cr);
256
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400257 cairo_destroy(cr);
258 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400259}
260
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500261static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500262panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400263 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500264{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500265 struct panel_launcher *launcher = data;
266
267 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500268 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500269
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300270 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500271}
272
273static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500274panel_launcher_leave_handler(struct widget *widget,
275 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400276{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500277 struct panel_launcher *launcher = data;
278
279 launcher->focused = 0;
Tiago Vignatti61500722012-05-23 22:06:28 +0300280 widget_destroy_tooltip(widget);
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500281 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400282}
283
284static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500285panel_launcher_button_handler(struct widget *widget,
286 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100287 uint32_t button,
288 enum wl_pointer_button_state state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400289{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500290 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400291
Kristian Høgsberg53880802012-01-09 11:16:50 -0500292 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500293 widget_schedule_redraw(widget);
Daniel Stone4dbadb12012-05-30 16:31:51 +0100294 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500295 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500296}
297
Martin Minarik1e51a872012-06-08 00:39:11 +0200298static void
299clock_func(struct task *task, uint32_t events)
300{
301 struct panel_clock *clock =
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400302 container_of(task, struct panel_clock, clock_task);
Kristian Høgsberg70226bb2012-06-08 16:54:52 -0400303 uint64_t exp;
Martin Minarik1e51a872012-06-08 00:39:11 +0200304
Martin Olsson8df662a2012-07-08 03:03:47 +0200305 if (read(clock->clock_fd, &exp, sizeof exp) != sizeof exp)
306 abort();
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400307 widget_schedule_redraw(clock->widget);
Martin Minarik1e51a872012-06-08 00:39:11 +0200308}
309
310static void
311panel_clock_redraw_handler(struct widget *widget, void *data)
312{
313 cairo_surface_t *surface;
314 struct panel_clock *clock = data;
315 cairo_t *cr;
316 struct rectangle allocation;
317 cairo_text_extents_t extents;
318 cairo_font_extents_t font_extents;
Martin Minarik1e51a872012-06-08 00:39:11 +0200319 time_t rawtime;
320 struct tm * timeinfo;
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400321 char string[128];
Martin Minarik1e51a872012-06-08 00:39:11 +0200322
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400323 time(&rawtime);
324 timeinfo = localtime(&rawtime);
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400325 strftime(string, sizeof string, "%a %b %d, %I:%M %p", timeinfo);
Martin Minarik1e51a872012-06-08 00:39:11 +0200326
327 widget_get_allocation(widget, &allocation);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400328 if (allocation.width == 0)
329 return;
Martin Minarik1e51a872012-06-08 00:39:11 +0200330
331 surface = window_get_surface(clock->panel->window);
332 cr = cairo_create(surface);
Martin Minarik1e51a872012-06-08 00:39:11 +0200333 cairo_select_font_face(cr, "sans",
334 CAIRO_FONT_SLANT_NORMAL,
335 CAIRO_FONT_WEIGHT_NORMAL);
336 cairo_set_font_size(cr, 14);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400337 cairo_text_extents(cr, string, &extents);
Martin Minarik1e51a872012-06-08 00:39:11 +0200338 cairo_font_extents (cr, &font_extents);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400339 cairo_move_to(cr, allocation.x + 5,
340 allocation.y + 3 * (allocation.height >> 2) + 1);
341 cairo_set_source_rgb(cr, 0, 0, 0);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400342 cairo_show_text(cr, string);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400343 cairo_move_to(cr, allocation.x + 4,
344 allocation.y + 3 * (allocation.height >> 2));
345 cairo_set_source_rgb(cr, 1, 1, 1);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400346 cairo_show_text(cr, string);
Martin Minarik1e51a872012-06-08 00:39:11 +0200347 cairo_destroy(cr);
348}
349
350static int
351clock_timer_reset(struct panel_clock *clock)
352{
353 struct itimerspec its;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400354
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400355 its.it_interval.tv_sec = 60;
Martin Minarik1e51a872012-06-08 00:39:11 +0200356 its.it_interval.tv_nsec = 0;
Kristian Høgsberge9f68f62012-06-11 12:24:12 -0400357 its.it_value.tv_sec = 60;
Martin Minarik1e51a872012-06-08 00:39:11 +0200358 its.it_value.tv_nsec = 0;
359 if (timerfd_settime(clock->clock_fd, 0, &its, NULL) < 0) {
360 fprintf(stderr, "could not set timerfd\n: %m");
361 return -1;
362 }
363
364 return 0;
365}
366
367static void
368panel_add_clock(struct panel *panel)
369{
370 struct panel_clock *clock;
371 int timerfd;
372
373 timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
374 if (timerfd < 0) {
375 fprintf(stderr, "could not create timerfd\n: %m");
376 return;
377 }
378
379 clock = malloc(sizeof *clock);
380 memset(clock, 0, sizeof *clock);
381 clock->panel = panel;
382 panel->clock = clock;
383 clock->clock_fd = timerfd;
384
385 clock->clock_task.run = clock_func;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400386 display_watch_fd(window_get_display(panel->window), clock->clock_fd,
387 EPOLLIN, &clock->clock_task);
Martin Minarik1e51a872012-06-08 00:39:11 +0200388 clock_timer_reset(clock);
389
390 clock->widget = widget_add_widget(panel->widget, clock);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400391 widget_set_redraw_handler(clock->widget, panel_clock_redraw_handler);
Martin Minarik1e51a872012-06-08 00:39:11 +0200392}
393
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500394static void
395panel_button_handler(struct widget *widget,
396 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100397 uint32_t button,
398 enum wl_pointer_button_state state, void *data)
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500399{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500400 struct panel *panel = data;
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500401
Daniel Stone4dbadb12012-05-30 16:31:51 +0100402 if (button == BTN_RIGHT && state == WL_POINTER_BUTTON_STATE_PRESSED)
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500403 show_menu(panel, input, time);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400404}
405
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100406static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500407panel_resize_handler(struct widget *widget,
408 int32_t width, int32_t height, void *data)
409{
410 struct panel_launcher *launcher;
411 struct panel *panel = data;
412 int x, y, w, h;
413
414 x = 10;
415 y = 16;
416 wl_list_for_each(launcher, &panel->launcher_list, link) {
417 w = cairo_image_surface_get_width(launcher->icon);
418 h = cairo_image_surface_get_height(launcher->icon);
419 widget_set_allocation(launcher->widget,
420 x, y - h / 2, w + 1, h + 1);
421 x += w + 10;
422 }
Martin Minarik1e51a872012-06-08 00:39:11 +0200423 h=20;
424 w=170;
Pekka Paalanen01b17252012-06-12 17:42:26 +0300425
426 if (panel->clock)
427 widget_set_allocation(panel->clock->widget,
428 width - w - 8, y - h / 2, w + 1, h + 1);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500429}
430
431static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100432panel_configure(void *data,
433 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400434 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100435 int32_t width, int32_t height)
436{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500437 struct surface *surface = window_get_user_data(window);
438 struct panel *panel = container_of(surface, struct panel, base);
439
440 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100441}
442
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400443static struct panel *
444panel_create(struct display *display)
445{
446 struct panel *panel;
447
448 panel = malloc(sizeof *panel);
449 memset(panel, 0, sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400450
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100451 panel->base.configure = panel_configure;
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -0400452 panel->window = window_create_custom(display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500453 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500454 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400455
456 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400457 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500458
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500459 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
460 widget_set_resize_handler(panel->widget, panel_resize_handler);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500461 widget_set_button_handler(panel->widget, panel_button_handler);
Rafal Mielniczukb9e513c2012-06-09 20:33:29 +0200462
463 panel_add_clock(panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400464
465 return panel;
466}
467
468static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500469panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400470{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500471 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400472
Kristian Høgsberg53880802012-01-09 11:16:50 -0500473 launcher = malloc(sizeof *launcher);
474 memset(launcher, 0, sizeof *launcher);
475 launcher->icon = cairo_image_surface_create_from_png(icon);
476 launcher->path = strdup(path);
477 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500478 wl_list_insert(panel->launcher_list.prev, &launcher->link);
479
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500480 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500481 widget_set_enter_handler(launcher->widget,
482 panel_launcher_enter_handler);
483 widget_set_leave_handler(launcher->widget,
484 panel_launcher_leave_handler);
485 widget_set_button_handler(launcher->widget,
486 panel_launcher_button_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500487 widget_set_redraw_handler(launcher->widget,
488 panel_launcher_redraw_handler);
Tiago Vignatti61500722012-05-23 22:06:28 +0300489 widget_set_motion_handler(launcher->widget,
490 panel_launcher_motion_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400491}
492
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500493enum {
494 BACKGROUND_SCALE,
495 BACKGROUND_TILE
496};
497
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400498static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500499background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400500{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500501 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400502 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400503 cairo_pattern_t *pattern;
504 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400505 cairo_t *cr;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400506 double sx, sy;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500507 struct rectangle allocation;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500508 int type = -1;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400509
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500510 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400511
512 cr = cairo_create(surface);
513 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
514 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
515 cairo_paint(cr);
516
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500517 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500518 image = NULL;
519 if (key_background_image)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -0400520 image = load_cairo_surface(key_background_image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500521
522 if (strcmp(key_background_type, "scale") == 0)
523 type = BACKGROUND_SCALE;
524 else if (strcmp(key_background_type, "tile") == 0)
525 type = BACKGROUND_TILE;
526 else
527 fprintf(stderr, "invalid background-type: %s\n",
528 key_background_type);
529
530 if (image && type != -1) {
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400531 pattern = cairo_pattern_create_for_surface(image);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500532 switch (type) {
533 case BACKGROUND_SCALE:
534 sx = (double) cairo_image_surface_get_width(image) /
535 allocation.width;
536 sy = (double) cairo_image_surface_get_height(image) /
537 allocation.height;
538 cairo_matrix_init_scale(&matrix, sx, sy);
539 cairo_pattern_set_matrix(pattern, &matrix);
540 break;
541 case BACKGROUND_TILE:
542 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
543 break;
544 }
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400545 cairo_set_source(cr, pattern);
546 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400547 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500548 } else {
549 set_hex_color(cr, key_background_color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400550 }
551
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500552 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400553 cairo_destroy(cr);
554 cairo_surface_destroy(surface);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400555}
556
557static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100558background_configure(void *data,
559 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400560 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100561 int32_t width, int32_t height)
562{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500563 struct background *background =
564 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100565
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500566 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100567}
568
569static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500570unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200571{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500572 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200573 struct rectangle allocation;
574 cairo_t *cr;
575 cairo_surface_t *surface;
576 cairo_pattern_t *pat;
577 double cx, cy, r, f;
578
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200579 surface = window_get_surface(dialog->window);
580 cr = cairo_create(surface);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500581
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500582 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200583 cairo_rectangle(cr, allocation.x, allocation.y,
584 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200585 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
586 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500587 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200588
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500589 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500590 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200591 f = 1.0;
592 else
593 f = 0.7;
594
595 cx = allocation.width / 2.0;
596 cy = allocation.height / 2.0;
597 r = (cx < cy ? cx : cy) * 0.4;
598 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
599 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
600 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
601 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
602 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500603 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200604 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
605 cairo_fill(cr);
606
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500607 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500608 allocation.x + cx - r,
609 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200610
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200611 cairo_destroy(cr);
612
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200613 cairo_surface_destroy(surface);
614}
615
616static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500617unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200618 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100619 uint32_t button,
620 enum wl_pointer_button_state state, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200621{
622 struct unlock_dialog *dialog = data;
623 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200624
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500625 if (button == BTN_LEFT) {
Daniel Stone4dbadb12012-05-30 16:31:51 +0100626 if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
627 !dialog->closing) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200628 display_defer(desktop->display, &desktop->unlock_task);
629 dialog->closing = 1;
630 }
631 }
632}
633
634static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200635unlock_dialog_keyboard_focus_handler(struct window *window,
636 struct input *device, void *data)
637{
638 window_schedule_redraw(window);
639}
640
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500641static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500642unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400643 struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400644 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500645{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500646 struct unlock_dialog *dialog = data;
647
648 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500649 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500650
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300651 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500652}
653
654static void
655unlock_dialog_widget_leave_handler(struct widget *widget,
656 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200657{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500658 struct unlock_dialog *dialog = data;
659
660 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500661 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200662}
663
664static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500665unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200666{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500667 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200668 struct unlock_dialog *dialog;
669
670 dialog = malloc(sizeof *dialog);
671 if (!dialog)
672 return NULL;
673 memset(dialog, 0, sizeof *dialog);
674
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400675 dialog->window = window_create_custom(display);
Kristian Høgsberg29af3eb2012-01-10 22:41:05 -0500676 dialog->widget = frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200677 window_set_title(dialog->window, "Unlock your desktop");
678
679 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200680 window_set_keyboard_focus_handler(dialog->window,
681 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500682 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500683 widget_set_redraw_handler(dialog->widget,
684 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500685 widget_set_enter_handler(dialog->button,
686 unlock_dialog_widget_enter_handler);
687 widget_set_leave_handler(dialog->button,
688 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500689 widget_set_button_handler(dialog->button,
690 unlock_dialog_button_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200691
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500692 desktop_shell_set_lock_surface(desktop->shell,
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400693 window_get_wl_surface(dialog->window));
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500694
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200695 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200696
697 return dialog;
698}
699
700static void
701unlock_dialog_destroy(struct unlock_dialog *dialog)
702{
703 window_destroy(dialog->window);
704 free(dialog);
705}
706
707static void
708unlock_dialog_finish(struct task *task, uint32_t events)
709{
710 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100711 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200712
713 desktop_shell_unlock(desktop->shell);
714 unlock_dialog_destroy(desktop->unlock_dialog);
715 desktop->unlock_dialog = NULL;
716}
717
718static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400719desktop_shell_configure(void *data,
720 struct desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400721 uint32_t edges,
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400722 struct wl_surface *surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400723 int32_t width, int32_t height)
724{
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400725 struct window *window = wl_surface_get_user_data(surface);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200726 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400727
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400728 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400729}
730
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200731static void
732desktop_shell_prepare_lock_surface(void *data,
733 struct desktop_shell *desktop_shell)
734{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200735 struct desktop *desktop = data;
736
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200737 if (!key_locking) {
738 desktop_shell_unlock(desktop->shell);
739 return;
740 }
741
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200742 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500743 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200744 desktop->unlock_dialog->desktop = desktop;
745 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200746}
747
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300748static void
749desktop_shell_grab_cursor(void *data,
750 struct desktop_shell *desktop_shell,
751 uint32_t cursor)
752{
753 struct desktop *desktop = data;
754
755 switch (cursor) {
756 case DESKTOP_SHELL_CURSOR_BUSY:
757 desktop->grab_cursor = CURSOR_WATCH;
758 break;
759 case DESKTOP_SHELL_CURSOR_MOVE:
760 desktop->grab_cursor = CURSOR_DRAGGING;
761 break;
762 case DESKTOP_SHELL_CURSOR_RESIZE_TOP:
763 desktop->grab_cursor = CURSOR_TOP;
764 break;
765 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM:
766 desktop->grab_cursor = CURSOR_BOTTOM;
767 break;
768 case DESKTOP_SHELL_CURSOR_RESIZE_LEFT:
769 desktop->grab_cursor = CURSOR_LEFT;
770 break;
771 case DESKTOP_SHELL_CURSOR_RESIZE_RIGHT:
772 desktop->grab_cursor = CURSOR_RIGHT;
773 break;
774 case DESKTOP_SHELL_CURSOR_RESIZE_TOP_LEFT:
775 desktop->grab_cursor = CURSOR_TOP_LEFT;
776 break;
777 case DESKTOP_SHELL_CURSOR_RESIZE_TOP_RIGHT:
778 desktop->grab_cursor = CURSOR_TOP_RIGHT;
779 break;
780 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_LEFT:
781 desktop->grab_cursor = CURSOR_BOTTOM_LEFT;
782 break;
783 case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_RIGHT:
784 desktop->grab_cursor = CURSOR_BOTTOM_RIGHT;
785 break;
786 case DESKTOP_SHELL_CURSOR_ARROW:
787 default:
788 desktop->grab_cursor = CURSOR_LEFT_PTR;
789 }
790}
791
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400792static const struct desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200793 desktop_shell_configure,
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300794 desktop_shell_prepare_lock_surface,
795 desktop_shell_grab_cursor
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400796};
797
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100798static struct background *
799background_create(struct desktop *desktop)
800{
801 struct background *background;
802
803 background = malloc(sizeof *background);
804 memset(background, 0, sizeof *background);
805
806 background->base.configure = background_configure;
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400807 background->window = window_create_custom(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500808 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100809 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500810 widget_set_redraw_handler(background->widget, background_draw);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100811
812 return background;
813}
814
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400815static int
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300816grab_surface_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400817 float x, float y, void *data)
818{
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300819 struct desktop *desktop = data;
820
821 return desktop->grab_cursor;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400822}
823
824static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300825grab_surface_create(struct desktop *desktop)
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400826{
827 struct wl_surface *s;
828
Ander Conselvan de Oliveira07a91cd2012-07-16 14:15:50 +0300829 desktop->grab_window = window_create_custom(desktop->display);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300830 window_set_user_data(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400831
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300832 s = window_get_wl_surface(desktop->grab_window);
833 desktop_shell_set_grab_surface(desktop->shell, s);
834
835 desktop->grab_widget =
836 window_add_widget(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400837 /* We set the allocation to 1x1 at 0,0 so the fake enter event
838 * at 0,0 will go to this widget. */
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300839 widget_set_allocation(desktop->grab_widget, 0, 0, 1, 1);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400840
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300841 widget_set_enter_handler(desktop->grab_widget,
842 grab_surface_enter_handler);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400843}
844
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100845static void
846create_output(struct desktop *desktop, uint32_t id)
847{
848 struct output *output;
849
850 output = calloc(1, sizeof *output);
851 if (!output)
852 return;
853
854 output->output = wl_display_bind(display_get_display(desktop->display),
855 id, &wl_output_interface);
856
857 wl_list_insert(&desktop->outputs, &output->link);
858}
859
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400860static void
861global_handler(struct wl_display *display, uint32_t id,
862 const char *interface, uint32_t version, void *data)
863{
864 struct desktop *desktop = data;
865
866 if (!strcmp(interface, "desktop_shell")) {
867 desktop->shell =
868 wl_display_bind(display, id, &desktop_shell_interface);
869 desktop_shell_add_listener(desktop->shell, &listener, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100870 } else if (!strcmp(interface, "wl_output")) {
871 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400872 }
873}
874
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500875static void
876launcher_section_done(void *data)
877{
878 struct desktop *desktop = data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100879 struct output *output;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500880
881 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
882 fprintf(stderr, "invalid launcher section\n");
883 return;
884 }
885
Martin Minarik1e51a872012-06-08 00:39:11 +0200886 wl_list_for_each(output, &desktop->outputs, link) {
Kristian Høgsberg53880802012-01-09 11:16:50 -0500887 panel_add_launcher(output->panel,
888 key_launcher_icon, key_launcher_path);
Martin Minarik1e51a872012-06-08 00:39:11 +0200889 }
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100890
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500891 free(key_launcher_icon);
892 key_launcher_icon = NULL;
893 free(key_launcher_path);
894 key_launcher_path = NULL;
895}
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400896
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500897static void
898add_default_launcher(struct desktop *desktop)
899{
900 struct output *output;
901
902 wl_list_for_each(output, &desktop->outputs, link)
903 panel_add_launcher(output->panel,
904 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +0100905 BINDIR "/weston-terminal");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500906}
907
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400908int main(int argc, char *argv[])
909{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200910 struct desktop desktop = { 0 };
Pekka Paalanen668dd562011-11-15 11:45:40 +0200911 char *config_file;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100912 struct output *output;
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500913 int ret;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400914
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200915 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100916 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200917
Kristian Høgsbergbcacef12012-03-11 21:05:57 -0400918 desktop.display = display_create(argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400919 if (desktop.display == NULL) {
920 fprintf(stderr, "failed to create display: %m\n");
921 return -1;
922 }
923
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400924 display_set_user_data(desktop.display, &desktop);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400925 wl_display_add_global_listener(display_get_display(desktop.display),
926 global_handler, &desktop);
927
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100928 wl_list_for_each(output, &desktop.outputs, link) {
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400929 struct wl_surface *surface;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100930
931 output->panel = panel_create(desktop.display);
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -0400932 surface = window_get_wl_surface(output->panel->window);
933 desktop_shell_set_panel(desktop.shell,
934 output->output, surface);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100935
936 output->background = background_create(&desktop);
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400937 surface = window_get_wl_surface(output->background->window);
938 desktop_shell_set_background(desktop.shell,
939 output->output, surface);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100940 }
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400941
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300942 grab_surface_create(&desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -0400943
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200944 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500945 ret = parse_config_file(config_file,
946 config_sections, ARRAY_LENGTH(config_sections),
947 &desktop);
Pekka Paalanen668dd562011-11-15 11:45:40 +0200948 free(config_file);
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500949 if (ret < 0)
950 add_default_launcher(&desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500951
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400952 signal(SIGCHLD, sigchild_handler);
953
954 display_run(desktop.display);
955
956 return 0;
957}