2 * Copyright © 2011 Kristian Høgsberg
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.
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
32 #include <linux/input.h>
34 #include "wayland-client.h"
35 #include "cairo-util.h"
38 #include <desktop-shell-client-protocol.h>
41 struct display *display;
42 struct desktop_shell *shell;
44 struct window *background;
45 const char *background_path;
49 struct window *window;
56 cairo_surface_t *icon;
62 sigchild_handler(int s)
67 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
68 fprintf(stderr, "child %d exited\n", pid);
72 show_menu(struct panel *panel, struct input *input)
74 int32_t x, y, width = 200, height = 200;
75 struct display *display;
77 input_get_position(input, &x, &y);
78 display = window_get_display(panel->window);
79 panel->menu = window_create_transient(display, panel->window,
80 x - 10, y - 10, width, height);
82 window_draw(panel->menu);
83 window_flush(panel->menu);
87 panel_activate_item(struct panel *panel, struct panel_item *item)
93 fprintf(stderr, "fork failed: %m\n");
100 if (execl(item->path, item->path, NULL) < 0) {
101 fprintf(stderr, "execl failed: %m\n");
107 panel_draw_item(struct item *item, void *data)
110 struct panel_item *pi;
111 int x, y, width, height;
114 pi = item_get_user_data(item);
115 width = cairo_image_surface_get_width(pi->icon);
116 height = cairo_image_surface_get_height(pi->icon);
126 cairo_user_to_device(cr, &dx, &dy);
127 item_set_allocation(item, dx, dy, width, height);
129 cairo_set_source_surface(cr, pi->icon, x, y);
132 if (window_get_focus_item(pi->panel->window) == item) {
133 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
134 cairo_mask_surface(cr, pi->icon, x, y);
137 cairo_translate(cr, width + 10, 0);
141 panel_redraw_handler(struct window *window, void *data)
143 cairo_surface_t *surface;
147 surface = window_get_surface(window);
148 cr = cairo_create(surface);
149 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
150 cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0.9);
153 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
154 cairo_translate(cr, 10, 32 / 2);
155 window_for_each_item(window, panel_draw_item, cr);
158 cairo_surface_destroy(surface);
159 window_flush(window);
163 panel_item_focus_handler(struct window *window,
164 struct item *focus, void *data)
166 window_schedule_redraw(window);
170 panel_button_handler(struct window *window,
171 struct input *input, uint32_t time,
172 int button, int state, void *data)
174 struct panel *panel = data;
175 struct panel_item *pi;
178 focus = window_get_focus_item(panel->window);
179 if (focus && button == BTN_LEFT) {
180 pi = item_get_user_data(focus);
181 window_schedule_redraw(panel->window);
183 panel_activate_item(panel, pi);
184 } else if (button == BTN_RIGHT) {
186 show_menu(panel, input);
188 window_destroy(panel->menu);
192 static struct panel *
193 panel_create(struct display *display)
197 panel = malloc(sizeof *panel);
198 memset(panel, 0, sizeof *panel);
200 panel->window = window_create(display, 0, 0);
202 window_set_title(panel->window, "panel");
203 window_set_decoration(panel->window, 0);
204 window_set_redraw_handler(panel->window, panel_redraw_handler);
205 window_set_custom(panel->window);
206 window_set_user_data(panel->window, panel);
207 window_set_button_handler(panel->window, panel_button_handler);
208 window_set_item_focus_handler(panel->window, panel_item_focus_handler);
214 panel_add_item(struct panel *panel, const char *icon, const char *path)
216 struct panel_item *item;
218 item = malloc(sizeof *item);
219 memset(item, 0, sizeof *item);
220 item->icon = cairo_image_surface_create_from_png(icon);
221 item->path = strdup(path);
223 window_add_item(panel->window, item);
227 background_draw(struct window *window, int width, int height, const char *path)
229 cairo_surface_t *surface, *image;
230 cairo_pattern_t *pattern;
231 cairo_matrix_t matrix;
235 window_set_child_size(window, width, height);
237 surface = window_get_surface(window);
239 cr = cairo_create(surface);
240 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
241 cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
245 image = load_jpeg(path);
246 pattern = cairo_pattern_create_for_surface(image);
247 sx = (double) cairo_image_surface_get_width(image) / width;
248 sy = (double) cairo_image_surface_get_height(image) / height;
249 cairo_matrix_init_scale(&matrix, sx, sy);
250 cairo_pattern_set_matrix(pattern, &matrix);
251 cairo_set_source(cr, pattern);
252 cairo_pattern_destroy (pattern);
254 cairo_surface_destroy(image);
258 cairo_surface_destroy(surface);
259 window_flush(window);
263 desktop_shell_configure(void *data,
264 struct desktop_shell *desktop_shell,
265 uint32_t time, uint32_t edges,
266 struct wl_surface *surface,
267 int32_t width, int32_t height)
269 struct desktop *desktop = data;
271 if (surface == window_get_wl_surface(desktop->panel->window)) {
272 window_set_child_size(desktop->panel->window, width, 32);
273 window_schedule_redraw(desktop->panel->window);
274 } else if (surface == window_get_wl_surface(desktop->background)) {
275 background_draw(desktop->background,
276 width, height, desktop->background_path);
280 static const struct desktop_shell_listener listener = {
281 desktop_shell_configure
285 global_handler(struct wl_display *display, uint32_t id,
286 const char *interface, uint32_t version, void *data)
288 struct desktop *desktop = data;
290 if (!strcmp(interface, "desktop_shell")) {
292 wl_display_bind(display, id, &desktop_shell_interface);
293 desktop_shell_add_listener(desktop->shell, &listener, desktop);
297 static const struct {
302 "/usr/share/icons/gnome/24x24/apps/utilities-terminal.png",
303 "/usr/bin/gnome-terminal"
306 "/usr/share/icons/gnome/24x24/apps/utilities-terminal.png",
310 "/usr/share/icons/hicolor/24x24/apps/google-chrome.png",
311 "/usr/bin/google-chrome"
315 int main(int argc, char *argv[])
317 struct desktop desktop;
320 desktop.display = display_create(&argc, &argv, NULL);
321 if (desktop.display == NULL) {
322 fprintf(stderr, "failed to create display: %m\n");
326 wl_display_add_global_listener(display_get_display(desktop.display),
327 global_handler, &desktop);
329 desktop.panel = panel_create(desktop.display);
331 for (i = 0; i < ARRAY_LENGTH(launchers); i++)
332 panel_add_item(desktop.panel,
333 launchers[i].icon, launchers[i].path);
335 desktop_shell_set_panel(desktop.shell,
336 window_get_wl_surface(desktop.panel->window));
338 desktop.background = window_create(desktop.display, 0, 0);
339 window_set_decoration(desktop.background, 0);
340 window_set_custom(desktop.background);
341 desktop.background_path = argv[1];
342 desktop_shell_set_background(desktop.shell,
343 window_get_wl_surface(desktop.background));
345 signal(SIGCHLD, sigchild_handler);
347 display_run(desktop.display);