We draw a taskbar surface in desktop-shell, extend the
desktop-shell protocol to send it to the compositor, and
the compositor will draw it in a new taskbar layer at the
bottom.
Signed-off-by: Manuel Bachmann manuel.bachm...@open.eurogiciel.org
---
clients/desktop-shell.c| 144
desktop-shell/shell.c | 53 +++-
desktop-shell/shell.h |1 +
protocol/desktop-shell.xml |5 ++
4 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index a0c6b6d..c341a91 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -85,6 +85,16 @@ struct panel {
uint32_t color;
};
+struct taskbar {
+ struct surface base;
+ struct window *window;
+ struct widget *widget;
+ struct wl_list handler_list;
+ struct desktop *desktop;
+ int painted;
+ uint32_t color;
+};
+
struct background {
struct surface base;
struct window *window;
@@ -102,6 +112,7 @@ struct output {
struct wl_list link;
struct panel *panel;
+ struct taskbar *taskbar;
struct background *background;
};
@@ -123,6 +134,16 @@ struct panel_clock {
int clock_fd;
};
+struct taskbar_handler {
+ struct widget *widget;
+ struct taskbar *taskbar;
+ cairo_surface_t *icon;
+ int focused, pressed;
+ char *title;
+ int state;
+ struct wl_list link;
+};
+
struct unlock_dialog {
struct window *window;
struct widget *widget;
@@ -173,6 +194,8 @@ is_desktop_painted(struct desktop *desktop)
wl_list_for_each(output, desktop-outputs, link) {
if (output-panel !output-panel-painted)
return 0;
+ if (output-taskbar !output-taskbar-painted)
+ return 0;
if (output-background !output-background-painted)
return 0;
}
@@ -566,6 +589,119 @@ panel_create(struct desktop *desktop)
return panel;
}
+static void
+taskbar_redraw_handler(struct widget *widget, void *data)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ struct taskbar *taskbar = data;
+
+ cr = widget_cairo_create(taskbar-widget);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ set_hex_color(cr, taskbar-color);
+ cairo_paint(cr);
+
+ cairo_destroy(cr);
+ surface = window_get_surface(taskbar-window);
+ cairo_surface_destroy(surface);
+ taskbar-painted = 1;
+ check_desktop_ready(taskbar-window);
+}
+
+static void
+taskbar_resize_handler(struct widget *widget,
+int32_t width, int32_t height, void *data)
+{
+ struct taskbar_handler *handler;
+ struct taskbar *taskbar = data;
+ cairo_t *cr;
+ cairo_text_extents_t extents;
+ int x, y, w, h;
+
+ x = 10;
+ y = 16;
+ wl_list_for_each(handler, taskbar-handler_list, link) {
+ cr = cairo_create (handler-icon);
+ cairo_text_extents (cr, handler-title, extents);
+
+ w = cairo_image_surface_get_width(handler-icon) +
extents.width + 8;
+ h = cairo_image_surface_get_height(handler-icon);
+ widget_set_allocation(handler-widget,
+ x, y - h / 2, w + 1, h + 1);
+ x += w + 10;
+
+ cairo_destroy (cr);
+ }
+}
+
+static void
+taskbar_configure(void *data,
+ struct desktop_shell *desktop_shell,
+ uint32_t edges, struct window *window,
+ int32_t width, int32_t height)
+{
+ struct surface *surface = window_get_user_data(window);
+ struct taskbar *taskbar = container_of(surface, struct taskbar, base);
+
+ window_schedule_resize(taskbar-window, width, 32);
+}
+
+static void
+taskbar_destroy_handler(struct taskbar_handler *handler)
+{
+ free(handler-title);
+
+ cairo_surface_destroy(handler-icon);
+
+ widget_destroy(handler-widget);
+ wl_list_remove(handler-link);
+
+ free(handler);
+}
+
+static void
+taskbar_destroy(struct taskbar *taskbar)
+{
+ struct taskbar_handler *tmp;
+ struct taskbar_handler *handler;
+
+ wl_list_for_each_safe(handler, tmp, taskbar-handler_list, link) {
+ taskbar_destroy_handler(handler);
+ }
+
+ widget_destroy(taskbar-widget);
+ window_destroy(taskbar-window);
+
+ free(taskbar);
+}
+
+static struct taskbar *
+taskbar_create(struct desktop *desktop)
+{
+ struct taskbar *taskbar;
+ struct weston_config_section *s;
+
+ taskbar = xzalloc(sizeof *taskbar);
+
+ taskbar-base.configure = taskbar_configure;
+ taskbar-desktop = desktop;
+ taskbar-window = window_create_custom(desktop-display);
+ taskbar-widget = window_add_widget(taskbar-window, taskbar);
+