[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