[PATCH 1/5] shell: add taskbar and taskbar_handler widgets
Manuel Bachmann
manuel.bachmann at open.eurogiciel.org
Tue Feb 18 21:17:00 PST 2014
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.bachmann at 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);
+ wl_list_init(&taskbar->handler_list);
+
+ window_set_title(taskbar->window, "taskbar");
+ window_set_user_data(taskbar->window, taskbar);
+
+ widget_set_redraw_handler(taskbar->widget, taskbar_redraw_handler);
+ widget_set_resize_handler(taskbar->widget, taskbar_resize_handler);
+
+ s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
+ weston_config_section_get_uint(s, "taskbar-color",
+ &taskbar->color, 0xaabbbbbb);
+
+ return taskbar;
+}
+
static cairo_surface_t *
load_icon_or_fallback(const char *icon)
{
@@ -1128,6 +1264,7 @@ output_destroy(struct output *output)
{
background_destroy(output->background);
panel_destroy(output->panel);
+ taskbar_destroy(output->taskbar);
wl_output_destroy(output->output);
wl_list_remove(&output->link);
@@ -1158,6 +1295,7 @@ output_handle_geometry(void *data,
struct output *output = data;
window_set_buffer_transform(output->panel->window, transform);
+ window_set_buffer_transform(output->taskbar->window, transform);
window_set_buffer_transform(output->background->window, transform);
}
@@ -1185,6 +1323,7 @@ output_handle_scale(void *data,
struct output *output = data;
window_set_buffer_scale(output->panel->window, scale);
+ window_set_buffer_scale(output->taskbar->window, scale);
window_set_buffer_scale(output->background->window, scale);
}
@@ -1205,6 +1344,11 @@ output_init(struct output *output, struct desktop *desktop)
desktop_shell_set_panel(desktop->shell,
output->output, surface);
+ output->taskbar = taskbar_create(desktop);
+ surface = window_get_wl_surface(output->taskbar->window);
+ desktop_shell_set_taskbar(desktop->shell,
+ output->output, surface);
+
output->background = background_create(desktop);
surface = window_get_wl_surface(output->background->window);
desktop_shell_set_background(desktop->shell,
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 7811962..7d7efaa 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -73,7 +73,7 @@ enum shell_surface_type {
* • Lock layer (only ever displayed on its own)
* • Cursor layer
* • Fullscreen layer
- * • Panel layer
+ * • Panel layer - Taskbar layer
* • Input panel layer
* • Workspace layers
* • Background layer
@@ -3747,6 +3747,53 @@ desktop_shell_set_panel(struct wl_client *client,
}
static void
+taskbar_configure(struct weston_surface *es, int32_t sx, int32_t sy)
+{
+ struct desktop_shell *shell = es->configure_private;
+ struct weston_view *view;
+
+ view = container_of(es->views.next, struct weston_view, surface_link);
+
+ configure_static_view(view, &shell->taskbar_layer);
+
+ weston_view_set_position(view, 0, view->output->height
+ - view->surface->height);
+}
+
+static void
+desktop_shell_set_taskbar(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource,
+ struct wl_resource *surface_resource)
+{
+ struct desktop_shell *shell = wl_resource_get_user_data(resource);
+ struct weston_surface *surface =
+ wl_resource_get_user_data(surface_resource);
+ struct weston_view *view, *next;
+
+ if (surface->configure) {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "surface role already assigned");
+ return;
+ }
+
+ wl_list_for_each_safe(view, next, &surface->views, surface_link)
+ weston_view_destroy(view);
+ view = weston_view_create(surface);
+
+ /* send post-creation configure request to desktop-shell taskbar */
+ surface->configure = taskbar_configure;
+ surface->configure_private = shell;
+ surface->output = wl_resource_get_user_data(output_resource);
+ view->output = surface->output;
+ desktop_shell_send_configure(resource, 0,
+ surface_resource,
+ surface->output->width,
+ surface->output->height);
+}
+
+static void
lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
{
struct desktop_shell *shell = surface->configure_private;
@@ -3865,6 +3912,7 @@ desktop_shell_desktop_ready(struct wl_client *client,
static const struct desktop_shell_interface desktop_shell_implementation = {
desktop_shell_set_background,
desktop_shell_set_panel,
+ desktop_shell_set_taskbar,
desktop_shell_set_lock_surface,
desktop_shell_unlock,
desktop_shell_set_grab_surface,
@@ -5859,7 +5907,8 @@ module_init(struct weston_compositor *ec,
ec->shell_interface.set_title = set_title;
weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
- weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
+ weston_layer_init(&shell->taskbar_layer, &shell->fullscreen_layer.link);
+ weston_layer_init(&shell->panel_layer, &shell->taskbar_layer.link);
weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
weston_layer_init(&shell->lock_layer, NULL);
weston_layer_init(&shell->input_panel_layer, NULL);
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 48ac250..104e621 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -124,6 +124,7 @@ struct desktop_shell {
struct weston_layer fullscreen_layer;
struct weston_layer panel_layer;
+ struct weston_layer taskbar_layer;
struct weston_layer background_layer;
struct weston_layer lock_layer;
struct weston_layer input_panel_layer;
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index 65e44a7..3ae5d33 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -17,6 +17,11 @@
<arg name="surface" type="object" interface="wl_surface"/>
</request>
+ <request name="set_taskbar">
+ <arg name="output" type="object" interface="wl_output"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+
<request name="set_lock_surface">
<arg name="surface" type="object" interface="wl_surface"/>
</request>
--
1.7.10.4
More information about the wayland-devel
mailing list