blob: 4c3b790ed22ed308c7923939df1acea41867588c [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 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -07005 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040011 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -070012 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040023 */
24
U. Artie Eoff3c946772014-01-15 10:59:50 -080025#include "config.h"
26
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040027#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <fcntl.h>
32#include <unistd.h>
U. Artie Eoff3c946772014-01-15 10:59:50 -080033#include <errno.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040034#include <math.h>
35#include <cairo.h>
36#include <sys/wait.h>
Martin Minarik1e51a872012-06-08 00:39:11 +020037#include <sys/timerfd.h>
Michael Vetter2a18a522015-05-15 17:17:47 +020038#include <sys/epoll.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040039#include <linux/input.h>
Tiago Vignatti61500722012-05-23 22:06:28 +030040#include <libgen.h>
Kristian Høgsbergd1936b92012-07-23 22:59:33 -040041#include <ctype.h>
Martin Minarik1e51a872012-06-08 00:39:11 +020042#include <time.h>
Quentin Glidicf9574f22016-06-23 18:55:21 +020043#include <assert.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040044
Pekka Paalanen50719bc2011-11-22 14:18:50 +020045#include <wayland-client.h>
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040046#include "window.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070047#include "shared/cairo-util.h"
48#include "shared/config-parser.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070049#include "shared/helpers.h"
Bryce Harringtone99e4bf2016-03-16 14:15:18 -070050#include "shared/xalloc.h"
Bryce Harrington0d1a6222016-02-11 16:42:49 -080051#include "shared/zalloc.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040052
Jonas Ådahl6d6fb612015-11-17 16:00:33 +080053#include "weston-desktop-shell-client-protocol.h"
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040054
Armin Krezovićc6a55db2016-03-10 18:02:34 +010055#define DEFAULT_CLOCK_FORMAT CLOCK_FORMAT_MINUTES
56
Pekka Paalanenb6df4f72012-08-03 14:39:15 +030057extern char **environ; /* defined by libc */
58
Quentin Glidicf9574f22016-06-23 18:55:21 +020059enum clock_format {
60 CLOCK_FORMAT_MINUTES,
61 CLOCK_FORMAT_SECONDS,
62 CLOCK_FORMAT_NONE
63};
64
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040065struct desktop {
66 struct display *display;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +080067 struct weston_desktop_shell *shell;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +020068 struct unlock_dialog *unlock_dialog;
69 struct task unlock_task;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010070 struct wl_list outputs;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -040071
Quentin Glidic55d57012016-06-23 18:55:18 +020072 int want_panel;
73 enum weston_desktop_shell_panel_position panel_position;
74
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +030075 struct window *grab_window;
76 struct widget *grab_widget;
77
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +030078 struct weston_config *config;
79 int locking;
80
Scott Moreauec116022012-07-22 18:23:52 -060081 enum cursor_type grab_cursor;
Pekka Paalanen79346ab2013-05-22 18:03:09 +030082
83 int painted;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010084};
85
86struct surface {
87 void (*configure)(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +080088 struct weston_desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -040089 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010090 int32_t width, int32_t height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040091};
92
93struct panel {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010094 struct surface base;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -040095 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050096 struct widget *widget;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -050097 struct wl_list launcher_list;
Martin Minarik1e51a872012-06-08 00:39:11 +020098 struct panel_clock *clock;
Pekka Paalanen79346ab2013-05-22 18:03:09 +030099 int painted;
Quentin Glidicf9574f22016-06-23 18:55:21 +0200100 enum clock_format clock_format;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300101 uint32_t color;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400102};
103
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100104struct background {
105 struct surface base;
106 struct window *window;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500107 struct widget *widget;
Pekka Paalanen79346ab2013-05-22 18:03:09 +0300108 int painted;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300109
110 char *image;
111 int type;
112 uint32_t color;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100113};
114
115struct output {
116 struct wl_output *output;
Xiong Zhang83d8ee72013-10-23 13:58:35 +0800117 uint32_t server_output_id;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100118 struct wl_list link;
119
120 struct panel *panel;
121 struct background *background;
122};
123
Kristian Høgsberg53880802012-01-09 11:16:50 -0500124struct panel_launcher {
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500125 struct widget *widget;
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400126 struct panel *panel;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400127 cairo_surface_t *icon;
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500128 int focused, pressed;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400129 char *path;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500130 struct wl_list link;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400131 struct wl_array envp;
132 struct wl_array argv;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400133};
134
Martin Minarik1e51a872012-06-08 00:39:11 +0200135struct panel_clock {
136 struct widget *widget;
137 struct panel *panel;
Martin Minarik1e51a872012-06-08 00:39:11 +0200138 struct task clock_task;
139 int clock_fd;
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100140 char *format_string;
141 time_t refresh_timer;
Martin Minarik1e51a872012-06-08 00:39:11 +0200142};
143
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200144struct unlock_dialog {
145 struct window *window;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500146 struct widget *widget;
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500147 struct widget *button;
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500148 int button_focused;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200149 int closing;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200150 struct desktop *desktop;
151};
152
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300153static void
154panel_add_launchers(struct panel *panel, struct desktop *desktop);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500155
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400156static void
157sigchild_handler(int s)
158{
159 int status;
160 pid_t pid;
161
162 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
163 fprintf(stderr, "child %d exited\n", pid);
164}
165
Pekka Paalanen79346ab2013-05-22 18:03:09 +0300166static int
167is_desktop_painted(struct desktop *desktop)
168{
169 struct output *output;
170
171 wl_list_for_each(output, &desktop->outputs, link) {
172 if (output->panel && !output->panel->painted)
173 return 0;
174 if (output->background && !output->background->painted)
175 return 0;
176 }
177
178 return 1;
179}
180
181static void
182check_desktop_ready(struct window *window)
183{
184 struct display *display;
185 struct desktop *desktop;
186
187 display = window_get_display(window);
188 desktop = display_get_user_data(display);
189
190 if (!desktop->painted && is_desktop_painted(desktop)) {
191 desktop->painted = 1;
192
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800193 weston_desktop_shell_desktop_ready(desktop->shell);
Pekka Paalanen79346ab2013-05-22 18:03:09 +0300194 }
195}
196
Kristian Høgsbergbcee9a42011-10-12 00:36:16 -0400197static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500198panel_launcher_activate(struct panel_launcher *widget)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400199{
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400200 char **argv;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400201 pid_t pid;
202
203 pid = fork();
204 if (pid < 0) {
205 fprintf(stderr, "fork failed: %m\n");
206 return;
207 }
208
209 if (pid)
210 return;
Benjamin Franzked7759712011-11-22 12:38:48 +0100211
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400212 argv = widget->argv.data;
213 if (execve(argv[0], argv, widget->envp.data) < 0) {
214 fprintf(stderr, "execl '%s' failed: %m\n", argv[0]);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400215 exit(1);
216 }
217}
218
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400219static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500220panel_launcher_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400221{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500222 struct panel_launcher *launcher = data;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500223 struct rectangle allocation;
224 cairo_t *cr;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400225
Alexander Larssonc584fa62013-05-22 14:41:32 +0200226 cr = widget_cairo_create(launcher->panel->widget);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500227
228 widget_get_allocation(widget, &allocation);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500229 if (launcher->pressed) {
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500230 allocation.x++;
231 allocation.y++;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400232 }
233
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500234 cairo_set_source_surface(cr, launcher->icon,
235 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400236 cairo_paint(cr);
237
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500238 if (launcher->focused) {
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400239 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500240 cairo_mask_surface(cr, launcher->icon,
241 allocation.x, allocation.y);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400242 }
Kristian Høgsberge28d05b2011-09-20 21:43:54 -0400243
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500244 cairo_destroy(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400245}
246
Tiago Vignatti61500722012-05-23 22:06:28 +0300247static int
248panel_launcher_motion_handler(struct widget *widget, struct input *input,
249 uint32_t time, float x, float y, void *data)
250{
251 struct panel_launcher *launcher = data;
252
253 widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
254
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300255 return CURSOR_LEFT_PTR;
Tiago Vignatti61500722012-05-23 22:06:28 +0300256}
257
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400258static void
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500259set_hex_color(cairo_t *cr, uint32_t color)
260{
Michael Vetter2a18a522015-05-15 17:17:47 +0200261 cairo_set_source_rgba(cr,
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -0500262 ((color >> 16) & 0xff) / 255.0,
263 ((color >> 8) & 0xff) / 255.0,
264 ((color >> 0) & 0xff) / 255.0,
265 ((color >> 24) & 0xff) / 255.0);
266}
267
268static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500269panel_redraw_handler(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400270{
271 cairo_surface_t *surface;
272 cairo_t *cr;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500273 struct panel *panel = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400274
Alexander Larssonc584fa62013-05-22 14:41:32 +0200275 cr = widget_cairo_create(panel->widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400276 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300277 set_hex_color(cr, panel->color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400278 cairo_paint(cr);
279
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400280 cairo_destroy(cr);
Alexander Larssonc584fa62013-05-22 14:41:32 +0200281 surface = window_get_surface(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400282 cairo_surface_destroy(surface);
Pekka Paalanen79346ab2013-05-22 18:03:09 +0300283 panel->painted = 1;
284 check_desktop_ready(panel->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400285}
286
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500287static int
Kristian Høgsberg53880802012-01-09 11:16:50 -0500288panel_launcher_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400289 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500290{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500291 struct panel_launcher *launcher = data;
292
293 launcher->focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500294 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500295
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300296 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500297}
298
299static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500300panel_launcher_leave_handler(struct widget *widget,
301 struct input *input, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400302{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500303 struct panel_launcher *launcher = data;
304
305 launcher->focused = 0;
Tiago Vignatti61500722012-05-23 22:06:28 +0300306 widget_destroy_tooltip(widget);
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500307 widget_schedule_redraw(widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400308}
309
310static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500311panel_launcher_button_handler(struct widget *widget,
312 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100313 uint32_t button,
314 enum wl_pointer_button_state state, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400315{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500316 struct panel_launcher *launcher;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400317
Kristian Høgsberg53880802012-01-09 11:16:50 -0500318 launcher = widget_get_user_data(widget);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500319 widget_schedule_redraw(widget);
Daniel Stone4dbadb12012-05-30 16:31:51 +0100320 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Kristian Høgsberg53880802012-01-09 11:16:50 -0500321 panel_launcher_activate(launcher);
Rusty Lynch4384a242013-08-08 21:28:22 -0700322
323}
324
325static void
Rusty Lynch1084da52013-08-15 09:10:08 -0700326panel_launcher_touch_down_handler(struct widget *widget, struct input *input,
327 uint32_t serial, uint32_t time, int32_t id,
Rusty Lynch4384a242013-08-08 21:28:22 -0700328 float x, float y, void *data)
329{
330 struct panel_launcher *launcher;
331
332 launcher = widget_get_user_data(widget);
333 launcher->focused = 1;
334 widget_schedule_redraw(widget);
335}
336
337static void
Rusty Lynch1084da52013-08-15 09:10:08 -0700338panel_launcher_touch_up_handler(struct widget *widget, struct input *input,
Michael Vetter2a18a522015-05-15 17:17:47 +0200339 uint32_t serial, uint32_t time, int32_t id,
Rusty Lynch1084da52013-08-15 09:10:08 -0700340 void *data)
Rusty Lynch4384a242013-08-08 21:28:22 -0700341{
342 struct panel_launcher *launcher;
343
344 launcher = widget_get_user_data(widget);
345 launcher->focused = 0;
346 widget_schedule_redraw(widget);
347 panel_launcher_activate(launcher);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500348}
349
Martin Minarik1e51a872012-06-08 00:39:11 +0200350static void
351clock_func(struct task *task, uint32_t events)
352{
353 struct panel_clock *clock =
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400354 container_of(task, struct panel_clock, clock_task);
Kristian Høgsberg70226bb2012-06-08 16:54:52 -0400355 uint64_t exp;
Martin Minarik1e51a872012-06-08 00:39:11 +0200356
Martin Olsson8df662a2012-07-08 03:03:47 +0200357 if (read(clock->clock_fd, &exp, sizeof exp) != sizeof exp)
358 abort();
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400359 widget_schedule_redraw(clock->widget);
Martin Minarik1e51a872012-06-08 00:39:11 +0200360}
361
362static void
363panel_clock_redraw_handler(struct widget *widget, void *data)
364{
Martin Minarik1e51a872012-06-08 00:39:11 +0200365 struct panel_clock *clock = data;
366 cairo_t *cr;
367 struct rectangle allocation;
368 cairo_text_extents_t extents;
369 cairo_font_extents_t font_extents;
Martin Minarik1e51a872012-06-08 00:39:11 +0200370 time_t rawtime;
371 struct tm * timeinfo;
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400372 char string[128];
Martin Minarik1e51a872012-06-08 00:39:11 +0200373
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400374 time(&rawtime);
375 timeinfo = localtime(&rawtime);
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100376 strftime(string, sizeof string, clock->format_string, timeinfo);
Martin Minarik1e51a872012-06-08 00:39:11 +0200377
378 widget_get_allocation(widget, &allocation);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400379 if (allocation.width == 0)
380 return;
Martin Minarik1e51a872012-06-08 00:39:11 +0200381
Alexander Larssonc584fa62013-05-22 14:41:32 +0200382 cr = widget_cairo_create(clock->panel->widget);
Martin Minarik1e51a872012-06-08 00:39:11 +0200383 cairo_select_font_face(cr, "sans",
384 CAIRO_FONT_SLANT_NORMAL,
385 CAIRO_FONT_WEIGHT_NORMAL);
386 cairo_set_font_size(cr, 14);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400387 cairo_text_extents(cr, string, &extents);
Martin Minarik1e51a872012-06-08 00:39:11 +0200388 cairo_font_extents (cr, &font_extents);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400389 cairo_move_to(cr, allocation.x + 5,
390 allocation.y + 3 * (allocation.height >> 2) + 1);
391 cairo_set_source_rgb(cr, 0, 0, 0);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400392 cairo_show_text(cr, string);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400393 cairo_move_to(cr, allocation.x + 4,
394 allocation.y + 3 * (allocation.height >> 2));
395 cairo_set_source_rgb(cr, 1, 1, 1);
Kristian Høgsberg92a984a2012-06-11 11:10:57 -0400396 cairo_show_text(cr, string);
Martin Minarik1e51a872012-06-08 00:39:11 +0200397 cairo_destroy(cr);
398}
399
400static int
401clock_timer_reset(struct panel_clock *clock)
402{
403 struct itimerspec its;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400404
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100405 its.it_interval.tv_sec = clock->refresh_timer;
Martin Minarik1e51a872012-06-08 00:39:11 +0200406 its.it_interval.tv_nsec = 0;
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100407 its.it_value.tv_sec = clock->refresh_timer;
Martin Minarik1e51a872012-06-08 00:39:11 +0200408 its.it_value.tv_nsec = 0;
409 if (timerfd_settime(clock->clock_fd, 0, &its, NULL) < 0) {
410 fprintf(stderr, "could not set timerfd\n: %m");
411 return -1;
412 }
413
414 return 0;
415}
416
417static void
U. Artie Eoff44874d92012-10-02 21:12:35 -0700418panel_destroy_clock(struct panel_clock *clock)
419{
420 widget_destroy(clock->widget);
421
422 close(clock->clock_fd);
423
424 free(clock);
425}
426
427static void
Martin Minarik1e51a872012-06-08 00:39:11 +0200428panel_add_clock(struct panel *panel)
429{
430 struct panel_clock *clock;
431 int timerfd;
432
433 timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
434 if (timerfd < 0) {
435 fprintf(stderr, "could not create timerfd\n: %m");
436 return;
437 }
438
Peter Huttererf3d62272013-08-08 11:57:05 +1000439 clock = xzalloc(sizeof *clock);
Martin Minarik1e51a872012-06-08 00:39:11 +0200440 clock->panel = panel;
441 panel->clock = clock;
442 clock->clock_fd = timerfd;
443
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100444 switch (panel->clock_format) {
445 case CLOCK_FORMAT_MINUTES:
446 clock->format_string = "%a %b %d, %I:%M %p";
447 clock->refresh_timer = 60;
448 break;
449 case CLOCK_FORMAT_SECONDS:
450 clock->format_string = "%a %b %d, %I:%M:%S %p";
451 clock->refresh_timer = 1;
452 break;
Quentin Glidicf9574f22016-06-23 18:55:21 +0200453 case CLOCK_FORMAT_NONE:
454 assert(!"not reached");
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100455 }
456
Martin Minarik1e51a872012-06-08 00:39:11 +0200457 clock->clock_task.run = clock_func;
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400458 display_watch_fd(window_get_display(panel->window), clock->clock_fd,
459 EPOLLIN, &clock->clock_task);
Martin Minarik1e51a872012-06-08 00:39:11 +0200460 clock_timer_reset(clock);
461
462 clock->widget = widget_add_widget(panel->widget, clock);
Kristian Høgsbergbb262cf2012-06-11 11:03:03 -0400463 widget_set_redraw_handler(clock->widget, panel_clock_redraw_handler);
Martin Minarik1e51a872012-06-08 00:39:11 +0200464}
465
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500466static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500467panel_resize_handler(struct widget *widget,
468 int32_t width, int32_t height, void *data)
469{
470 struct panel_launcher *launcher;
471 struct panel *panel = data;
472 int x, y, w, h;
Michael Vetter2a18a522015-05-15 17:17:47 +0200473
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500474 x = 10;
475 y = 16;
476 wl_list_for_each(launcher, &panel->launcher_list, link) {
477 w = cairo_image_surface_get_width(launcher->icon);
478 h = cairo_image_surface_get_height(launcher->icon);
479 widget_set_allocation(launcher->widget,
480 x, y - h / 2, w + 1, h + 1);
481 x += w + 10;
482 }
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100483
484 h = 20;
485
486 if (panel->clock_format == CLOCK_FORMAT_SECONDS)
487 w = 190;
488 else /* CLOCK_FORMAT_MINUTES */
489 w = 170;
Pekka Paalanen01b17252012-06-12 17:42:26 +0300490
491 if (panel->clock)
492 widget_set_allocation(panel->clock->widget,
493 width - w - 8, y - h / 2, w + 1, h + 1);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500494}
495
496static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100497panel_configure(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800498 struct weston_desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400499 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100500 int32_t width, int32_t height)
501{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500502 struct surface *surface = window_get_user_data(window);
503 struct panel *panel = container_of(surface, struct panel, base);
504
505 window_schedule_resize(panel->window, width, 32);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100506}
507
U. Artie Eoff44874d92012-10-02 21:12:35 -0700508static void
509panel_destroy_launcher(struct panel_launcher *launcher)
510{
511 wl_array_release(&launcher->argv);
512 wl_array_release(&launcher->envp);
513
514 free(launcher->path);
515
516 cairo_surface_destroy(launcher->icon);
517
518 widget_destroy(launcher->widget);
519 wl_list_remove(&launcher->link);
520
521 free(launcher);
522}
523
524static void
525panel_destroy(struct panel *panel)
526{
527 struct panel_launcher *tmp;
528 struct panel_launcher *launcher;
529
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100530 if (panel->clock)
531 panel_destroy_clock(panel->clock);
U. Artie Eoff44874d92012-10-02 21:12:35 -0700532
533 wl_list_for_each_safe(launcher, tmp, &panel->launcher_list, link)
534 panel_destroy_launcher(launcher);
535
536 widget_destroy(panel->widget);
537 window_destroy(panel->window);
538
539 free(panel);
540}
541
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400542static struct panel *
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300543panel_create(struct desktop *desktop)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400544{
545 struct panel *panel;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300546 struct weston_config_section *s;
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100547 char *clock_format_option = NULL;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400548
Peter Huttererf3d62272013-08-08 11:57:05 +1000549 panel = xzalloc(sizeof *panel);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400550
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100551 panel->base.configure = panel_configure;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300552 panel->window = window_create_custom(desktop->display);
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500553 panel->widget = window_add_widget(panel->window, panel);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500554 wl_list_init(&panel->launcher_list);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400555
556 window_set_title(panel->window, "panel");
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400557 window_set_user_data(panel->window, panel);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500558
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500559 widget_set_redraw_handler(panel->widget, panel_redraw_handler);
560 widget_set_resize_handler(panel->widget, panel_resize_handler);
Michael Vetter2a18a522015-05-15 17:17:47 +0200561
Armin Krezovićc6a55db2016-03-10 18:02:34 +0100562 s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
563 weston_config_section_get_string(s, "clock-format", &clock_format_option, "");
564
565 if (strcmp(clock_format_option, "minutes") == 0)
566 panel->clock_format = CLOCK_FORMAT_MINUTES;
567 else if (strcmp(clock_format_option, "seconds") == 0)
568 panel->clock_format = CLOCK_FORMAT_SECONDS;
569 else if (strcmp(clock_format_option, "none") == 0)
570 panel->clock_format = CLOCK_FORMAT_NONE;
571 else
572 panel->clock_format = DEFAULT_CLOCK_FORMAT;
573
574 if (panel->clock_format != CLOCK_FORMAT_NONE)
575 panel_add_clock(panel);
576
577 free (clock_format_option);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400578
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300579 s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
Bryce Harringtone776f2a2016-07-14 18:28:03 -0700580 weston_config_section_get_color(s, "panel-color",
581 &panel->color, 0xaa000000);
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300582
583 panel_add_launchers(panel, desktop);
584
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400585 return panel;
586}
587
Philipp Brüschweiler467668c2012-08-29 10:53:36 +0200588static cairo_surface_t *
589load_icon_or_fallback(const char *icon)
590{
591 cairo_surface_t *surface = cairo_image_surface_create_from_png(icon);
Philipp Brüschweiler96386b82013-04-15 20:10:40 +0200592 cairo_status_t status;
Philipp Brüschweiler467668c2012-08-29 10:53:36 +0200593 cairo_t *cr;
594
Philipp Brüschweiler96386b82013-04-15 20:10:40 +0200595 status = cairo_surface_status(surface);
596 if (status == CAIRO_STATUS_SUCCESS)
Philipp Brüschweiler467668c2012-08-29 10:53:36 +0200597 return surface;
598
599 cairo_surface_destroy(surface);
Philipp Brüschweiler96386b82013-04-15 20:10:40 +0200600 fprintf(stderr, "ERROR loading icon from file '%s', error: '%s'\n",
601 icon, cairo_status_to_string(status));
Philipp Brüschweiler467668c2012-08-29 10:53:36 +0200602
603 /* draw fallback icon */
604 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
605 20, 20);
606 cr = cairo_create(surface);
607
608 cairo_set_source_rgba(cr, 0.8, 0.8, 0.8, 1);
609 cairo_paint(cr);
610
611 cairo_set_source_rgba(cr, 0, 0, 0, 1);
612 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
613 cairo_rectangle(cr, 0, 0, 20, 20);
614 cairo_move_to(cr, 4, 4);
615 cairo_line_to(cr, 16, 16);
616 cairo_move_to(cr, 4, 16);
617 cairo_line_to(cr, 16, 4);
618 cairo_stroke(cr);
619
620 cairo_destroy(cr);
621
622 return surface;
623}
624
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400625static void
Kristian Høgsberg53880802012-01-09 11:16:50 -0500626panel_add_launcher(struct panel *panel, const char *icon, const char *path)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400627{
Kristian Høgsberg53880802012-01-09 11:16:50 -0500628 struct panel_launcher *launcher;
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400629 char *start, *p, *eq, **ps;
630 int i, j, k;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400631
Peter Huttererf3d62272013-08-08 11:57:05 +1000632 launcher = xzalloc(sizeof *launcher);
Philipp Brüschweiler467668c2012-08-29 10:53:36 +0200633 launcher->icon = load_icon_or_fallback(icon);
U. Artie Eoff3c946772014-01-15 10:59:50 -0800634 launcher->path = xstrdup(path);
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400635
636 wl_array_init(&launcher->envp);
637 wl_array_init(&launcher->argv);
Pekka Paalanenb6df4f72012-08-03 14:39:15 +0300638 for (i = 0; environ[i]; i++) {
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400639 ps = wl_array_add(&launcher->envp, sizeof *ps);
Pekka Paalanenb6df4f72012-08-03 14:39:15 +0300640 *ps = environ[i];
Kristian Høgsbergd1936b92012-07-23 22:59:33 -0400641 }
642 j = 0;
643
644 start = launcher->path;
645 while (*start) {
646 for (p = start, eq = NULL; *p && !isspace(*p); p++)
647 if (*p == '=')
648 eq = p;
649
650 if (eq && j == 0) {
651 ps = launcher->envp.data;
652 for (k = 0; k < i; k++)
653 if (strncmp(ps[k], start, eq - start) == 0) {
654 ps[k] = start;
655 break;
656 }
657 if (k == i) {
658 ps = wl_array_add(&launcher->envp, sizeof *ps);
659 *ps = start;
660 i++;
661 }
662 } else {
663 ps = wl_array_add(&launcher->argv, sizeof *ps);
664 *ps = start;
665 j++;
666 }
667
668 while (*p && isspace(*p))
669 *p++ = '\0';
670
671 start = p;
672 }
673
674 ps = wl_array_add(&launcher->envp, sizeof *ps);
675 *ps = NULL;
676 ps = wl_array_add(&launcher->argv, sizeof *ps);
677 *ps = NULL;
678
Kristian Høgsberg53880802012-01-09 11:16:50 -0500679 launcher->panel = panel;
Kristian Høgsberg75bc6672012-01-10 09:43:58 -0500680 wl_list_insert(panel->launcher_list.prev, &launcher->link);
681
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500682 launcher->widget = widget_add_widget(panel->widget, launcher);
Kristian Høgsberg53880802012-01-09 11:16:50 -0500683 widget_set_enter_handler(launcher->widget,
684 panel_launcher_enter_handler);
685 widget_set_leave_handler(launcher->widget,
686 panel_launcher_leave_handler);
687 widget_set_button_handler(launcher->widget,
688 panel_launcher_button_handler);
Rusty Lynch4384a242013-08-08 21:28:22 -0700689 widget_set_touch_down_handler(launcher->widget,
690 panel_launcher_touch_down_handler);
691 widget_set_touch_up_handler(launcher->widget,
692 panel_launcher_touch_up_handler);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500693 widget_set_redraw_handler(launcher->widget,
694 panel_launcher_redraw_handler);
Tiago Vignatti61500722012-05-23 22:06:28 +0300695 widget_set_motion_handler(launcher->widget,
696 panel_launcher_motion_handler);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400697}
698
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500699enum {
700 BACKGROUND_SCALE,
Pekka Paalanena402b052013-05-22 18:03:10 +0300701 BACKGROUND_SCALE_CROP,
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500702 BACKGROUND_TILE
703};
704
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400705static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500706background_draw(struct widget *widget, void *data)
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400707{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500708 struct background *background = data;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400709 cairo_surface_t *surface, *image;
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400710 cairo_pattern_t *pattern;
711 cairo_matrix_t matrix;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400712 cairo_t *cr;
Pekka Paalanena402b052013-05-22 18:03:10 +0300713 double im_w, im_h;
714 double sx, sy, s;
715 double tx, ty;
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500716 struct rectangle allocation;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400717
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500718 surface = window_get_surface(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400719
Alexander Larssonc584fa62013-05-22 14:41:32 +0200720 cr = widget_cairo_create(background->widget);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400721 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
722 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
723 cairo_paint(cr);
724
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500725 widget_get_allocation(widget, &allocation);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500726 image = NULL;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300727 if (background->image)
728 image = load_cairo_surface(background->image);
Kristian Høgsberg4c3661f2014-04-21 22:54:37 -0700729 else if (background->color == 0)
730 image = load_cairo_surface(DATADIR "/weston/pattern.png");
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500731
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300732 if (image && background->type != -1) {
Pekka Paalanena402b052013-05-22 18:03:10 +0300733 im_w = cairo_image_surface_get_width(image);
734 im_h = cairo_image_surface_get_height(image);
735 sx = im_w / allocation.width;
736 sy = im_h / allocation.height;
737
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400738 pattern = cairo_pattern_create_for_surface(image);
Pekka Paalanena402b052013-05-22 18:03:10 +0300739
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300740 switch (background->type) {
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500741 case BACKGROUND_SCALE:
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500742 cairo_matrix_init_scale(&matrix, sx, sy);
743 cairo_pattern_set_matrix(pattern, &matrix);
Bill Spitzak79b7cb32014-05-08 20:00:35 -0700744 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500745 break;
Pekka Paalanena402b052013-05-22 18:03:10 +0300746 case BACKGROUND_SCALE_CROP:
747 s = (sx < sy) ? sx : sy;
748 /* align center */
749 tx = (im_w - s * allocation.width) * 0.5;
750 ty = (im_h - s * allocation.height) * 0.5;
751 cairo_matrix_init_translate(&matrix, tx, ty);
752 cairo_matrix_scale(&matrix, s, s);
753 cairo_pattern_set_matrix(pattern, &matrix);
Bill Spitzak79b7cb32014-05-08 20:00:35 -0700754 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
Pekka Paalanena402b052013-05-22 18:03:10 +0300755 break;
Kristian Høgsberg07f72942012-01-25 16:34:36 -0500756 case BACKGROUND_TILE:
757 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
758 break;
759 }
Pekka Paalanena402b052013-05-22 18:03:10 +0300760
Kristian Høgsberg7e690002011-09-08 18:18:02 -0400761 cairo_set_source(cr, pattern);
762 cairo_pattern_destroy (pattern);
Kristian Høgsberg27d38662011-10-20 13:11:12 -0400763 cairo_surface_destroy(image);
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500764 } else {
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300765 set_hex_color(cr, background->color);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400766 }
767
Kristian Høgsberg8129bc02012-01-25 14:55:33 -0500768 cairo_paint(cr);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400769 cairo_destroy(cr);
770 cairo_surface_destroy(surface);
Pekka Paalanen9564c752012-10-24 09:43:08 +0300771
Pekka Paalanen79346ab2013-05-22 18:03:09 +0300772 background->painted = 1;
773 check_desktop_ready(background->window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400774}
775
776static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100777background_configure(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800778 struct weston_desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400779 uint32_t edges, struct window *window,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100780 int32_t width, int32_t height)
781{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500782 struct background *background =
783 (struct background *) window_get_user_data(window);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100784
Kristian Høgsberg4598f962014-01-01 16:32:09 -0800785 widget_schedule_resize(background->widget, width, height);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100786}
787
788static void
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500789unlock_dialog_redraw_handler(struct widget *widget, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200790{
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500791 struct unlock_dialog *dialog = data;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200792 struct rectangle allocation;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200793 cairo_surface_t *surface;
Alexander Larssonc584fa62013-05-22 14:41:32 +0200794 cairo_t *cr;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200795 cairo_pattern_t *pat;
796 double cx, cy, r, f;
797
Alexander Larssonc584fa62013-05-22 14:41:32 +0200798 cr = widget_cairo_create(widget);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500799
Kristian Høgsbergbb977002012-01-10 19:11:42 -0500800 widget_get_allocation(dialog->widget, &allocation);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200801 cairo_rectangle(cr, allocation.x, allocation.y,
802 allocation.width, allocation.height);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200803 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
804 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500805 cairo_fill(cr);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200806
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500807 cairo_translate(cr, allocation.x, allocation.y);
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500808 if (dialog->button_focused)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200809 f = 1.0;
810 else
811 f = 0.7;
812
813 cx = allocation.width / 2.0;
814 cy = allocation.height / 2.0;
815 r = (cx < cy ? cx : cy) * 0.4;
816 pat = cairo_pattern_create_radial(cx, cy, r * 0.7, cx, cy, r);
817 cairo_pattern_add_color_stop_rgb(pat, 0.0, 0, 0.86 * f, 0);
818 cairo_pattern_add_color_stop_rgb(pat, 0.85, 0.2 * f, f, 0.2 * f);
819 cairo_pattern_add_color_stop_rgb(pat, 1.0, 0, 0.86 * f, 0);
820 cairo_set_source(cr, pat);
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500821 cairo_pattern_destroy(pat);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200822 cairo_arc(cr, cx, cy, r, 0.0, 2.0 * M_PI);
823 cairo_fill(cr);
824
Kristian Høgsbergc51f7992012-01-08 15:09:53 -0500825 widget_set_allocation(dialog->button,
Kristian Høgsberg41c5c4e2012-03-05 20:37:51 -0500826 allocation.x + cx - r,
827 allocation.y + cy - r, 2 * r, 2 * r);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200828
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200829 cairo_destroy(cr);
830
Alexander Larssonc584fa62013-05-22 14:41:32 +0200831 surface = window_get_surface(dialog->window);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200832 cairo_surface_destroy(surface);
833}
834
835static void
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500836unlock_dialog_button_handler(struct widget *widget,
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200837 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100838 uint32_t button,
839 enum wl_pointer_button_state state, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200840{
841 struct unlock_dialog *dialog = data;
842 struct desktop *desktop = dialog->desktop;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200843
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500844 if (button == BTN_LEFT) {
Daniel Stone4dbadb12012-05-30 16:31:51 +0100845 if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
846 !dialog->closing) {
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200847 display_defer(desktop->display, &desktop->unlock_task);
848 dialog->closing = 1;
849 }
850 }
851}
852
853static void
Brian J Lovinc4df4082013-08-26 15:58:22 -0700854unlock_dialog_touch_down_handler(struct widget *widget, struct input *input,
855 uint32_t serial, uint32_t time, int32_t id,
856 float x, float y, void *data)
857{
858 struct unlock_dialog *dialog = data;
859
860 dialog->button_focused = 1;
861 widget_schedule_redraw(widget);
862}
863
864static void
865unlock_dialog_touch_up_handler(struct widget *widget, struct input *input,
866 uint32_t serial, uint32_t time, int32_t id,
867 void *data)
868{
869 struct unlock_dialog *dialog = data;
870 struct desktop *desktop = dialog->desktop;
871
872 dialog->button_focused = 0;
873 widget_schedule_redraw(widget);
874 display_defer(desktop->display, &desktop->unlock_task);
875 dialog->closing = 1;
876}
877
878static void
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200879unlock_dialog_keyboard_focus_handler(struct window *window,
880 struct input *device, void *data)
881{
882 window_schedule_redraw(window);
883}
884
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500885static int
Kristian Høgsbergee143232012-01-09 08:42:24 -0500886unlock_dialog_widget_enter_handler(struct widget *widget,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400887 struct input *input,
Kristian Høgsberg80680c72012-05-10 12:21:37 -0400888 float x, float y, void *data)
Kristian Høgsbergee143232012-01-09 08:42:24 -0500889{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500890 struct unlock_dialog *dialog = data;
891
892 dialog->button_focused = 1;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500893 widget_schedule_redraw(widget);
Kristian Høgsbergbb901fa2012-01-09 11:22:32 -0500894
Ander Conselvan de Oliveiradc8c8fc2012-05-25 16:01:41 +0300895 return CURSOR_LEFT_PTR;
Kristian Høgsbergee143232012-01-09 08:42:24 -0500896}
897
898static void
899unlock_dialog_widget_leave_handler(struct widget *widget,
900 struct input *input, void *data)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200901{
Kristian Høgsbergb6323512012-01-11 00:04:42 -0500902 struct unlock_dialog *dialog = data;
903
904 dialog->button_focused = 0;
Kristian Høgsberg9a13dab2012-01-08 15:18:19 -0500905 widget_schedule_redraw(widget);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200906}
907
908static struct unlock_dialog *
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500909unlock_dialog_create(struct desktop *desktop)
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200910{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500911 struct display *display = desktop->display;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200912 struct unlock_dialog *dialog;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800913 struct wl_surface *surface;
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200914
Peter Huttererf3d62272013-08-08 11:57:05 +1000915 dialog = xzalloc(sizeof *dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200916
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400917 dialog->window = window_create_custom(display);
Jason Ekstrandee7fefc2013-10-13 19:08:38 -0500918 dialog->widget = window_frame_create(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200919 window_set_title(dialog->window, "Unlock your desktop");
920
921 window_set_user_data(dialog->window, dialog);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200922 window_set_keyboard_focus_handler(dialog->window,
923 unlock_dialog_keyboard_focus_handler);
Kristian Høgsberg441338c2012-01-10 13:52:34 -0500924 dialog->button = widget_add_widget(dialog->widget, dialog);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -0500925 widget_set_redraw_handler(dialog->widget,
926 unlock_dialog_redraw_handler);
Kristian Høgsbergee143232012-01-09 08:42:24 -0500927 widget_set_enter_handler(dialog->button,
928 unlock_dialog_widget_enter_handler);
929 widget_set_leave_handler(dialog->button,
930 unlock_dialog_widget_leave_handler);
Kristian Høgsberga8a0db32012-01-09 11:12:05 -0500931 widget_set_button_handler(dialog->button,
932 unlock_dialog_button_handler);
Brian J Lovinc4df4082013-08-26 15:58:22 -0700933 widget_set_touch_down_handler(dialog->button,
934 unlock_dialog_touch_down_handler);
935 widget_set_touch_up_handler(dialog->button,
936 unlock_dialog_touch_up_handler);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200937
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800938 surface = window_get_wl_surface(dialog->window);
939 weston_desktop_shell_set_lock_surface(desktop->shell, surface);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500940
Pekka Paalanen40e49ac2012-01-18 16:51:30 +0200941 window_schedule_resize(dialog->window, 260, 230);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200942
943 return dialog;
944}
945
946static void
947unlock_dialog_destroy(struct unlock_dialog *dialog)
948{
949 window_destroy(dialog->window);
950 free(dialog);
951}
952
953static void
954unlock_dialog_finish(struct task *task, uint32_t events)
955{
956 struct desktop *desktop =
Benjamin Franzked7759712011-11-22 12:38:48 +0100957 container_of(task, struct desktop, unlock_task);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200958
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800959 weston_desktop_shell_unlock(desktop->shell);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200960 unlock_dialog_destroy(desktop->unlock_dialog);
961 desktop->unlock_dialog = NULL;
962}
963
964static void
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400965desktop_shell_configure(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800966 struct weston_desktop_shell *desktop_shell,
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400967 uint32_t edges,
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400968 struct wl_surface *surface,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400969 int32_t width, int32_t height)
970{
Kristian Høgsberg962342c2012-06-26 16:29:50 -0400971 struct window *window = wl_surface_get_user_data(surface);
Pekka Paalanen068ae942011-11-28 14:11:15 +0200972 struct surface *s = window_get_user_data(window);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400973
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400974 s->configure(data, desktop_shell, edges, window, width, height);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -0400975}
976
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200977static void
978desktop_shell_prepare_lock_surface(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800979 struct weston_desktop_shell *desktop_shell)
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200980{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200981 struct desktop *desktop = data;
982
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +0300983 if (!desktop->locking) {
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800984 weston_desktop_shell_unlock(desktop->shell);
Pekka Paalanenfd83b6d2011-12-08 10:06:53 +0200985 return;
986 }
987
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200988 if (!desktop->unlock_dialog) {
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500989 desktop->unlock_dialog = unlock_dialog_create(desktop);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +0200990 desktop->unlock_dialog->desktop = desktop;
991 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200992}
993
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300994static void
995desktop_shell_grab_cursor(void *data,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +0800996 struct weston_desktop_shell *desktop_shell,
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300997 uint32_t cursor)
998{
999 struct desktop *desktop = data;
1000
1001 switch (cursor) {
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001002 case WESTON_DESKTOP_SHELL_CURSOR_NONE:
Philipp Brüschweiler16d59d72012-08-24 15:43:55 +02001003 desktop->grab_cursor = CURSOR_BLANK;
1004 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001005 case WESTON_DESKTOP_SHELL_CURSOR_BUSY:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001006 desktop->grab_cursor = CURSOR_WATCH;
1007 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001008 case WESTON_DESKTOP_SHELL_CURSOR_MOVE:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001009 desktop->grab_cursor = CURSOR_DRAGGING;
1010 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001011 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_TOP:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001012 desktop->grab_cursor = CURSOR_TOP;
1013 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001014 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001015 desktop->grab_cursor = CURSOR_BOTTOM;
1016 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001017 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_LEFT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001018 desktop->grab_cursor = CURSOR_LEFT;
1019 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001020 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_RIGHT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001021 desktop->grab_cursor = CURSOR_RIGHT;
1022 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001023 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_TOP_LEFT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001024 desktop->grab_cursor = CURSOR_TOP_LEFT;
1025 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001026 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_TOP_RIGHT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001027 desktop->grab_cursor = CURSOR_TOP_RIGHT;
1028 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001029 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_LEFT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001030 desktop->grab_cursor = CURSOR_BOTTOM_LEFT;
1031 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001032 case WESTON_DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_RIGHT:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001033 desktop->grab_cursor = CURSOR_BOTTOM_RIGHT;
1034 break;
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001035 case WESTON_DESKTOP_SHELL_CURSOR_ARROW:
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001036 default:
1037 desktop->grab_cursor = CURSOR_LEFT_PTR;
1038 }
1039}
1040
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001041static const struct weston_desktop_shell_listener listener = {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001042 desktop_shell_configure,
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001043 desktop_shell_prepare_lock_surface,
1044 desktop_shell_grab_cursor
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001045};
1046
U. Artie Eoff44874d92012-10-02 21:12:35 -07001047static void
1048background_destroy(struct background *background)
1049{
1050 widget_destroy(background->widget);
1051 window_destroy(background->window);
1052
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001053 free(background->image);
U. Artie Eoff44874d92012-10-02 21:12:35 -07001054 free(background);
1055}
1056
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001057static struct background *
1058background_create(struct desktop *desktop)
1059{
1060 struct background *background;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001061 struct weston_config_section *s;
1062 char *type;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001063
Peter Huttererf3d62272013-08-08 11:57:05 +10001064 background = xzalloc(sizeof *background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001065 background->base.configure = background_configure;
Kristian Høgsberg962342c2012-06-26 16:29:50 -04001066 background->window = window_create_custom(desktop->display);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -05001067 background->widget = window_add_widget(background->window, background);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001068 window_set_user_data(background->window, background);
Kristian Høgsbergb67e94b2012-01-10 12:23:19 -05001069 widget_set_redraw_handler(background->widget, background_draw);
Arnaud Vracfb754a02014-08-25 20:56:49 +02001070 widget_set_transparent(background->widget, 0);
Tomeu Vizosobee45a12013-08-06 20:05:54 +02001071 window_set_preferred_format(background->window,
1072 WINDOW_PREFERRED_FORMAT_RGB565);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001073
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001074 s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
1075 weston_config_section_get_string(s, "background-image",
Kristian Høgsberg4c3661f2014-04-21 22:54:37 -07001076 &background->image, NULL);
Bryce Harringtone776f2a2016-07-14 18:28:03 -07001077 weston_config_section_get_color(s, "background-color",
1078 &background->color, 0x00000000);
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001079
1080 weston_config_section_get_string(s, "background-type",
1081 &type, "tile");
U. Artie Eoff3c946772014-01-15 10:59:50 -08001082 if (type == NULL) {
1083 fprintf(stderr, "%s: out of memory\n", program_invocation_short_name);
1084 exit(EXIT_FAILURE);
1085 }
1086
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001087 if (strcmp(type, "scale") == 0) {
1088 background->type = BACKGROUND_SCALE;
1089 } else if (strcmp(type, "scale-crop") == 0) {
1090 background->type = BACKGROUND_SCALE_CROP;
1091 } else if (strcmp(type, "tile") == 0) {
1092 background->type = BACKGROUND_TILE;
1093 } else {
1094 background->type = -1;
1095 fprintf(stderr, "invalid background-type: %s\n",
1096 type);
1097 }
1098
1099 free(type);
1100
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001101 return background;
1102}
1103
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001104static int
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001105grab_surface_enter_handler(struct widget *widget, struct input *input,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001106 float x, float y, void *data)
1107{
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001108 struct desktop *desktop = data;
1109
1110 return desktop->grab_cursor;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001111}
1112
1113static void
U. Artie Eoff44874d92012-10-02 21:12:35 -07001114grab_surface_destroy(struct desktop *desktop)
1115{
1116 widget_destroy(desktop->grab_widget);
1117 window_destroy(desktop->grab_window);
1118}
1119
1120static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001121grab_surface_create(struct desktop *desktop)
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001122{
1123 struct wl_surface *s;
1124
Ander Conselvan de Oliveira07a91cd2012-07-16 14:15:50 +03001125 desktop->grab_window = window_create_custom(desktop->display);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001126 window_set_user_data(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001127
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001128 s = window_get_wl_surface(desktop->grab_window);
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001129 weston_desktop_shell_set_grab_surface(desktop->shell, s);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001130
1131 desktop->grab_widget =
1132 window_add_widget(desktop->grab_window, desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001133 /* We set the allocation to 1x1 at 0,0 so the fake enter event
1134 * at 0,0 will go to this widget. */
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001135 widget_set_allocation(desktop->grab_widget, 0, 0, 1, 1);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001136
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001137 widget_set_enter_handler(desktop->grab_widget,
1138 grab_surface_enter_handler);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001139}
1140
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001141static void
U. Artie Eoff44874d92012-10-02 21:12:35 -07001142output_destroy(struct output *output)
1143{
1144 background_destroy(output->background);
Jonny Lambe67118c2014-08-12 15:07:51 +02001145 if (output->panel)
1146 panel_destroy(output->panel);
U. Artie Eoff44874d92012-10-02 21:12:35 -07001147 wl_output_destroy(output->output);
1148 wl_list_remove(&output->link);
1149
1150 free(output);
1151}
1152
1153static void
1154desktop_destroy_outputs(struct desktop *desktop)
1155{
1156 struct output *tmp;
1157 struct output *output;
1158
1159 wl_list_for_each_safe(output, tmp, &desktop->outputs, link)
1160 output_destroy(output);
1161}
1162
1163static void
Alexander Larssonc584fa62013-05-22 14:41:32 +02001164output_handle_geometry(void *data,
1165 struct wl_output *wl_output,
1166 int x, int y,
1167 int physical_width,
1168 int physical_height,
1169 int subpixel,
1170 const char *make,
1171 const char *model,
1172 int transform)
1173{
1174 struct output *output = data;
1175
Jonny Lambe67118c2014-08-12 15:07:51 +02001176 if (output->panel)
1177 window_set_buffer_transform(output->panel->window, transform);
Alexander Larssonc584fa62013-05-22 14:41:32 +02001178 window_set_buffer_transform(output->background->window, transform);
1179}
1180
1181static void
1182output_handle_mode(void *data,
1183 struct wl_output *wl_output,
1184 uint32_t flags,
1185 int width,
1186 int height,
1187 int refresh)
1188{
1189}
1190
1191static void
1192output_handle_done(void *data,
1193 struct wl_output *wl_output)
1194{
1195}
1196
1197static void
1198output_handle_scale(void *data,
1199 struct wl_output *wl_output,
Alexander Larssonedddbd12013-05-24 13:09:43 +02001200 int32_t scale)
Alexander Larssonc584fa62013-05-22 14:41:32 +02001201{
1202 struct output *output = data;
1203
Jonny Lambe67118c2014-08-12 15:07:51 +02001204 if (output->panel)
1205 window_set_buffer_scale(output->panel->window, scale);
Alexander Larssonc584fa62013-05-22 14:41:32 +02001206 window_set_buffer_scale(output->background->window, scale);
1207}
1208
1209static const struct wl_output_listener output_listener = {
1210 output_handle_geometry,
1211 output_handle_mode,
1212 output_handle_done,
1213 output_handle_scale
1214};
1215
1216static void
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001217output_init(struct output *output, struct desktop *desktop)
1218{
1219 struct wl_surface *surface;
1220
Quentin Glidic55d57012016-06-23 18:55:18 +02001221 if (desktop->want_panel) {
Jonny Lambe67118c2014-08-12 15:07:51 +02001222 output->panel = panel_create(desktop);
1223 surface = window_get_wl_surface(output->panel->window);
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001224 weston_desktop_shell_set_panel(desktop->shell,
1225 output->output, surface);
Jonny Lambe67118c2014-08-12 15:07:51 +02001226 }
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001227
1228 output->background = background_create(desktop);
1229 surface = window_get_wl_surface(output->background->window);
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001230 weston_desktop_shell_set_background(desktop->shell,
1231 output->output, surface);
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001232}
1233
1234static void
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001235create_output(struct desktop *desktop, uint32_t id)
1236{
1237 struct output *output;
1238
Bryce Harrington0d1a6222016-02-11 16:42:49 -08001239 output = zalloc(sizeof *output);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001240 if (!output)
1241 return;
1242
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001243 output->output =
Alexander Larssonc584fa62013-05-22 14:41:32 +02001244 display_bind(desktop->display, id, &wl_output_interface, 2);
Xiong Zhang83d8ee72013-10-23 13:58:35 +08001245 output->server_output_id = id;
Alexander Larssonc584fa62013-05-22 14:41:32 +02001246
1247 wl_output_add_listener(output->output, &output_listener, output);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001248
1249 wl_list_insert(&desktop->outputs, &output->link);
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001250
1251 /* On start up we may process an output global before the shell global
1252 * in which case we can't create the panel and background just yet */
1253 if (desktop->shell)
1254 output_init(output, desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001255}
1256
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001257static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001258global_handler(struct display *display, uint32_t id,
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001259 const char *interface, uint32_t version, void *data)
1260{
1261 struct desktop *desktop = data;
1262
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001263 if (!strcmp(interface, "weston_desktop_shell")) {
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001264 desktop->shell = display_bind(desktop->display,
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001265 id,
1266 &weston_desktop_shell_interface,
1267 1);
1268 weston_desktop_shell_add_listener(desktop->shell,
1269 &listener,
1270 desktop);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001271 } else if (!strcmp(interface, "wl_output")) {
1272 create_output(desktop, id);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001273 }
1274}
1275
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -05001276static void
Xiong Zhang83d8ee72013-10-23 13:58:35 +08001277global_handler_remove(struct display *display, uint32_t id,
1278 const char *interface, uint32_t version, void *data)
1279{
1280 struct desktop *desktop = data;
1281 struct output *output;
1282
1283 if (!strcmp(interface, "wl_output")) {
1284 wl_list_for_each(output, &desktop->outputs, link) {
1285 if (output->server_output_id == id) {
1286 output_destroy(output);
1287 break;
1288 }
1289 }
1290 }
1291}
1292
1293static void
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001294panel_add_launchers(struct panel *panel, struct desktop *desktop)
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -05001295{
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001296 struct weston_config_section *s;
1297 char *icon, *path;
1298 const char *name;
1299 int count;
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -05001300
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001301 count = 0;
1302 s = NULL;
1303 while (weston_config_next_section(desktop->config, &s, &name)) {
1304 if (strcmp(name, "launcher") != 0)
1305 continue;
1306
1307 weston_config_section_get_string(s, "icon", &icon, NULL);
1308 weston_config_section_get_string(s, "path", &path, NULL);
1309
1310 if (icon != NULL && path != NULL) {
1311 panel_add_launcher(panel, icon, path);
Rob Bradford09252d42013-07-26 16:29:45 +01001312 count++;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001313 } else {
1314 fprintf(stderr, "invalid launcher section\n");
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001315 }
1316
1317 free(icon);
1318 free(path);
Kristian Høgsbergac3a59a2011-11-14 22:43:37 -05001319 }
1320
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001321 if (count == 0) {
1322 /* add default launcher */
1323 panel_add_launcher(panel,
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -05001324 DATADIR "/weston/terminal.png",
Rodney Lorrimar99ff01b2012-02-29 17:31:03 +01001325 BINDIR "/weston-terminal");
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001326 }
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -05001327}
1328
Quentin Glidic55d57012016-06-23 18:55:18 +02001329static void
1330parse_panel_position(struct desktop *desktop, struct weston_config_section *s)
1331{
1332 char *position;
1333
1334 weston_config_section_get_string(s, "panel-position", &position, "top");
1335 if (strcmp(position, "top") == 0)
1336 desktop->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP;
1337 else if (strcmp(position, "bottom") == 0)
1338 desktop->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM;
1339 else if (strcmp(position, "left") == 0)
1340 desktop->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT;
1341 else if (strcmp(position, "right") == 0)
1342 desktop->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT;
1343 else
1344 fprintf(stderr, "Wrong panel position: %s\n", position);
1345 free(position);
1346
1347 if (desktop->panel_position == WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP
1348 || desktop->panel_position == WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM) {
1349 desktop->want_panel = 1;
1350 } else if (desktop->panel_position == WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT
1351 || desktop->panel_position == WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT) {
1352 fprintf(stderr, "Unsupported panel position\n");
1353 }
1354}
1355
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001356int main(int argc, char *argv[])
1357{
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +02001358 struct desktop desktop = { 0 };
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001359 struct output *output;
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001360 struct weston_config_section *s;
Pekka Paalanen6c71aae2015-03-24 15:56:19 +02001361 const char *config_file;
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001362
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +02001363 desktop.unlock_task.run = unlock_dialog_finish;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001364 wl_list_init(&desktop.outputs);
Pekka Paalanenbfbb26b2011-11-15 13:34:56 +02001365
Pekka Paalanen6c71aae2015-03-24 15:56:19 +02001366 config_file = weston_config_get_name_from_env();
1367 desktop.config = weston_config_parse(config_file);
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001368 s = weston_config_get_section(desktop.config, "shell", NULL, NULL);
1369 weston_config_section_get_bool(s, "locking", &desktop.locking, 1);
Quentin Glidic55d57012016-06-23 18:55:18 +02001370 parse_panel_position(&desktop, s);
Ander Conselvan de Oliveira6d75da72013-07-05 16:05:27 +03001371
Kristian Høgsberg4172f662013-02-20 15:27:49 -05001372 desktop.display = display_create(&argc, argv);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001373 if (desktop.display == NULL) {
1374 fprintf(stderr, "failed to create display: %m\n");
1375 return -1;
1376 }
1377
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001378 display_set_user_data(desktop.display, &desktop);
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001379 display_set_global_handler(desktop.display, global_handler);
Xiong Zhang83d8ee72013-10-23 13:58:35 +08001380 display_set_global_handler_remove(desktop.display, global_handler_remove);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001381
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001382 /* Create panel and background for outputs processed before the shell
1383 * global interface was processed */
Quentin Glidic55d57012016-06-23 18:55:18 +02001384 if (desktop.want_panel)
1385 weston_desktop_shell_set_panel_position(desktop.shell, desktop.panel_position);
Ander Conselvan de Oliveirae4925492013-07-05 16:05:28 +03001386 wl_list_for_each(output, &desktop.outputs, link)
1387 if (!output->panel)
1388 output_init(output, &desktop);
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001389
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001390 grab_surface_create(&desktop);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001391
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001392 signal(SIGCHLD, sigchild_handler);
1393
1394 display_run(desktop.display);
1395
U. Artie Eoff44874d92012-10-02 21:12:35 -07001396 /* Cleanup */
1397 grab_surface_destroy(&desktop);
1398 desktop_destroy_outputs(&desktop);
1399 if (desktop.unlock_dialog)
1400 unlock_dialog_destroy(desktop.unlock_dialog);
Jonas Ådahl6d6fb612015-11-17 16:00:33 +08001401 weston_desktop_shell_destroy(desktop.shell);
U. Artie Eoff44874d92012-10-02 21:12:35 -07001402 display_destroy(desktop.display);
1403
Kristian Høgsberg0c29eb22011-09-06 18:02:34 -04001404 return 0;
1405}