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); + 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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel