blob: bce0a800cfd698c30fe30160210a16785a87dad0 [file] [log] [blame]
Kristian Høgsberg6336e462011-11-26 17:36:23 -05001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "window.h"
29#include "cairo-util.h"
30
31#include "tablet-shell-client-protocol.h"
32
33struct tablet_shell {
34 struct display *display;
35 struct tablet_shell *tablet_shell;
36 struct rectangle allocation;
37 struct window *lockscreen;
38 struct window *switcher;
39 struct window *homescreen;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050040 struct wl_list launcher_list;
41};
42
43struct launcher {
44 cairo_surface_t *icon;
45 char *path;
46 struct wl_list link;
47};
48
49static char *key_lockscreen_icon;
50static char *key_lockscreen_background;
51static char *key_homescreen_background;
52static char *key_launcher_icon;
53static char *key_launcher_path;
54static void launcher_section_done(void *data);
55
56static const struct config_key lockscreen_config_keys[] = {
57 { "icon", CONFIG_KEY_STRING, &key_lockscreen_icon },
58 { "background", CONFIG_KEY_STRING, &key_lockscreen_background },
59};
60
61static const struct config_key homescreen_config_keys[] = {
62 { "background", CONFIG_KEY_STRING, &key_homescreen_background },
63};
64
65static const struct config_key launcher_config_keys[] = {
66 { "icon", CONFIG_KEY_STRING, &key_launcher_icon },
67 { "path", CONFIG_KEY_STRING, &key_launcher_path },
68};
69
70static const struct config_section config_sections[] = {
71 { "lockscreen",
72 lockscreen_config_keys, ARRAY_LENGTH(lockscreen_config_keys) },
73 { "homescreen",
74 homescreen_config_keys, ARRAY_LENGTH(homescreen_config_keys) },
75 { "launcher",
76 launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
77 launcher_section_done }
Kristian Høgsberg6336e462011-11-26 17:36:23 -050078};
79
80static void
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050081paint_background(cairo_t *cr, const char *path, struct rectangle *allocation)
Kristian Høgsberg6336e462011-11-26 17:36:23 -050082{
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050083 cairo_surface_t *image = NULL;
84 cairo_pattern_t *pattern;
85 cairo_matrix_t matrix;
86 double sx, sy;
Kristian Høgsberg6336e462011-11-26 17:36:23 -050087
88 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050089 if (path)
90 image = load_jpeg(path);
91 if (image) {
92 pattern = cairo_pattern_create_for_surface(image);
93 sx = (double) cairo_image_surface_get_width(image) /
94 allocation->width;
95 sy = (double) cairo_image_surface_get_height(image) /
96 allocation->height;
97 cairo_matrix_init_scale(&matrix, sx, sy);
98 cairo_pattern_set_matrix(pattern, &matrix);
99 cairo_set_source(cr, pattern);
100 cairo_pattern_destroy (pattern);
101 cairo_surface_destroy(image);
102 cairo_paint(cr);
103 } else {
104 fprintf(stderr, "couldn't load backgrond image: %s\n",
105 key_lockscreen_background);
106 cairo_set_source_rgb(cr, 0.2, 0, 0);
107 cairo_paint(cr);
108 }
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500109}
110
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500111static void
112homescreen_draw(struct tablet_shell *shell)
113{
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500114 cairo_surface_t *surface;
115 struct rectangle allocation;
116 cairo_pattern_t *pattern;
117 cairo_matrix_t matrix;
118 cairo_t *cr;
119 struct launcher *launcher;
120 const int rows = 4, columns = 5, icon_width = 128, icon_height = 128;
121 int x, y, i, width, height, vmargin, hmargin, vpadding, hpadding;
122
123 window_draw(shell->homescreen);
124 window_get_child_allocation(shell->homescreen, &allocation);
125 surface = window_get_surface(shell->homescreen);
126 cr = cairo_create(surface);
127
128 paint_background(cr, key_homescreen_background, &allocation);
129
130 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
131
132 width = allocation.width - columns * icon_width;
133 hpadding = width / (columns + 1);
134 hmargin = (width - hpadding * (columns - 1)) / 2;
135
136 height = allocation.height - rows * icon_height;
137 vpadding = height / (rows + 1);
138 vmargin = (height - vpadding * (rows - 1)) / 2;
139
140 x = hmargin;
141 y = vmargin;
142 i = 0;
143
144 wl_list_for_each(launcher, &shell->launcher_list, link) {
145 pattern = cairo_pattern_create_for_surface(launcher->icon);
146 cairo_matrix_init_scale(&matrix, 2.0, 2.0);
147 cairo_matrix_translate(&matrix, -x, -y);
148 cairo_pattern_set_matrix(pattern, &matrix);
149 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
150 cairo_set_source(cr, pattern);
151 cairo_pattern_destroy(pattern);
152 cairo_paint(cr);
153 x += icon_width + hpadding;
154 i++;
155 if (i == columns) {
156 x = hmargin;
157 y += icon_height + vpadding;
158 i = 0;
159 }
160 }
161
162 cairo_surface_flush(surface);
163 cairo_surface_destroy(surface);
164 window_flush(shell->homescreen);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500165}
166
167
168static void
169lockscreen_draw(struct tablet_shell *shell)
170{
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500171 cairo_surface_t *surface;
172 cairo_surface_t *icon;
173 struct rectangle allocation;
174 cairo_t *cr;
175 int width, height;
176
177 window_draw(shell->lockscreen);
178 window_get_child_allocation(shell->lockscreen, &allocation);
179 surface = window_get_surface(shell->lockscreen);
180 cr = cairo_create(surface);
181
182 paint_background(cr, key_lockscreen_background, &allocation);
183
184 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
185 icon = cairo_image_surface_create_from_png(key_lockscreen_icon);
186 width = cairo_image_surface_get_width(icon);
187 height = cairo_image_surface_get_height(icon);
188 cairo_set_source_surface(cr, icon,
189 allocation.x + (allocation.width - width) / 2,
190 allocation.y + (allocation.height - height) / 2);
191 cairo_paint(cr);
192 cairo_surface_destroy(icon);
193
194 cairo_surface_flush(surface);
195 cairo_surface_destroy(surface);
196 window_flush(shell->lockscreen);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500197}
198
199static int
200lockscreen_motion_handler(struct window *window,
201 struct input *input, uint32_t time,
202 int32_t x, int32_t y,
203 int32_t sx, int32_t sy, void *data)
204{
205 return POINTER_LEFT_PTR;
206}
207
208static void
209lockscreen_button_handler(struct window *window,
210 struct input *input, uint32_t time,
211 int button, int state, void *data)
212{
213 struct tablet_shell *shell = data;
214
215 window_destroy(shell->lockscreen);
216 shell->lockscreen = NULL;
217}
218
219static void
220show_lockscreen(void *data, struct tablet_shell *tablet_shell)
221{
222 struct tablet_shell *shell = data;
223
224 shell->lockscreen = window_create(shell->display,
225 shell->allocation.width,
226 shell->allocation.height);
227 window_set_user_data(shell->lockscreen, shell);
228 window_set_decoration(shell->lockscreen, 0);
229 window_set_custom(shell->lockscreen);
230 window_set_button_handler(shell->lockscreen,
231 lockscreen_button_handler);
232 window_set_motion_handler(shell->lockscreen,
233 lockscreen_motion_handler);
234
235
236 tablet_shell_set_lockscreen(shell->tablet_shell,
237 window_get_wl_surface(shell->lockscreen));
238 lockscreen_draw(shell);
239}
240
241static void
242show_switcher(void *data, struct tablet_shell *tablet_shell)
243{
244 struct tablet_shell *shell = data;
245
246 shell->switcher = window_create(shell->display, 0, 0);
247 window_set_user_data(shell->switcher, shell);
248 window_set_decoration(shell->switcher, 0);
249 window_set_custom(shell->switcher);
250 tablet_shell_set_switcher(shell->tablet_shell,
251 window_get_wl_surface(shell->switcher));
252}
253
254static void
255hide_switcher(void *data, struct tablet_shell *tablet_shell)
256{
257}
258
259static const struct tablet_shell_listener tablet_shell_listener = {
260 show_lockscreen,
261 show_switcher,
262 hide_switcher
263};
264
265static struct tablet_shell *
266tablet_shell_create(struct display *display, uint32_t id)
267{
268 struct tablet_shell *shell;
269 struct output *output;
270
271 shell = malloc(sizeof *shell);
272
273 shell->display = display;
274 shell->tablet_shell =
275 wl_display_bind(display_get_display(display),
276 id, &tablet_shell_interface);
277 tablet_shell_add_listener(shell->tablet_shell,
278 &tablet_shell_listener, shell);
279 output = display_get_output(display);
280 output_get_allocation(output, &shell->allocation);
281
282 shell->homescreen = window_create(display,
283 shell->allocation.width,
284 shell->allocation.height);
285 window_set_user_data(shell->homescreen, shell);
286 window_set_decoration(shell->homescreen, 0);
287 window_set_custom(shell->homescreen);
288
289 tablet_shell_set_homescreen(shell->tablet_shell,
290 window_get_wl_surface(shell->homescreen));
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500291 wl_list_init(&shell->launcher_list);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500292
293 return shell;
294}
295
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500296static void
297tablet_shell_add_launcher(struct tablet_shell *shell,
298 const char *icon, const char *path)
299{
300 struct launcher *launcher;
301
302 launcher = malloc(sizeof *launcher);
303 launcher->path = strdup(path);
304 launcher->icon = cairo_image_surface_create_from_png(icon);
305 if (cairo_surface_status (launcher->icon) != CAIRO_STATUS_SUCCESS) {
306 fprintf(stderr, "couldn't load %s\n", icon);
307 free(launcher);
308 return;
309 }
310
311 wl_list_insert(&shell->launcher_list, &launcher->link);
312}
313
314static void
315launcher_section_done(void *data)
316{
317 struct tablet_shell *shell = data;
318
319 if (key_launcher_icon == NULL || key_launcher_path == NULL) {
320 fprintf(stderr, "invalid launcher section\n");
321 return;
322 }
323
324 tablet_shell_add_launcher(shell, key_launcher_icon, key_launcher_path);
325
326 free(key_launcher_icon);
327 key_launcher_icon = NULL;
328 free(key_launcher_path);
329 key_launcher_path = NULL;
330}
331
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500332int main(int argc, char *argv[])
333{
334 struct display *display;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500335 char *config_file;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500336 uint32_t id;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500337 struct tablet_shell *shell;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500338
339 display = display_create(&argc, &argv, NULL);
340 if (display == NULL) {
341 fprintf(stderr, "failed to create display: %m\n");
342 return -1;
343 }
344
345 wl_display_roundtrip(display_get_display(display));
346 id = wl_display_get_global(display_get_display(display),
347 "tablet_shell", 1);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500348 shell = tablet_shell_create(display, id);
349
350 config_file = config_file_path("wayland-tablet-shell.ini");
351 parse_config_file(config_file,
352 config_sections, ARRAY_LENGTH(config_sections),
353 shell);
354 free(config_file);
355
356 homescreen_draw(shell);
357
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500358 display_run(display);
359
360 return 0;
361}