Each time a managed_surface receives a "presented" event, a red tooltip will be created on the panel and stacked on the right side (near the clock).
The user can click on the tooltip to make the shell send an "activate" request, and raise the surface to the foreground of its current workspace. The tooltip is destroyed after having been clicked, or whenever the corresponding shell surface gets destroyed by any means. Signed-off-by: Manuel Bachmann <[email protected]> --- clients/desktop-shell.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 203 insertions(+), 6 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 3c63c28..5c5a1aa 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -72,6 +72,7 @@ struct desktop { struct desktop_managed_surface { struct managed_surface *managed_surface; char *title; + struct desktop *desktop; struct wl_list link; }; @@ -87,6 +88,7 @@ struct panel { struct window *window; struct widget *widget; struct wl_list launcher_list; + struct wl_list notifier_list; struct panel_clock *clock; int painted; uint32_t color; @@ -123,6 +125,13 @@ struct panel_launcher { struct wl_array argv; }; +struct panel_notifier { + struct widget *widget; + struct panel *panel; + struct desktop_managed_surface *mgsurf; + struct wl_list link; +}; + struct panel_clock { struct widget *widget; struct panel *panel; @@ -172,6 +181,16 @@ show_menu(struct panel *panel, struct input *input, uint32_t time) x - 10, y - 10, menu_func, entries, 4); } +static void +update_window(struct window *window) +{ + struct rectangle allocation; + + window_get_allocation(window, &allocation); + window_schedule_resize(window, allocation.width, + allocation.height); +} + static int is_desktop_painted(struct desktop *desktop) { @@ -204,6 +223,25 @@ check_desktop_ready(struct window *window) } } +static struct panel_notifier * +managed_surface_get_notifier(struct output *output, + struct desktop_managed_surface *mgsurf) +{ + struct panel *panel; + struct panel_notifier *notifier; + + panel = output->panel; + if (!panel) + return NULL; + + wl_list_for_each(notifier, &panel->notifier_list, link) { + if (notifier->mgsurf == mgsurf) + return notifier; + } + + return NULL; +} + static void panel_launcher_activate(struct panel_launcher *widget) { @@ -358,6 +396,112 @@ panel_launcher_touch_up_handler(struct widget *widget, struct input *input, } static void +panel_destroy_notifier(struct panel_notifier *notifier) +{ + wl_list_remove(¬ifier->link); + update_window(notifier->panel->window); + + widget_destroy(notifier->widget); + notifier->mgsurf = NULL; + free(notifier); +} + +static void +panel_notifier_activate(struct panel_notifier *notifier) +{ + if (notifier->mgsurf) + managed_surface_activate(notifier->mgsurf->managed_surface); + + panel_destroy_notifier(notifier); +} + +static void +panel_notifier_touch_up_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + void *data) +{ + struct panel_notifier *notifier; + + notifier = widget_get_user_data(widget); + widget_schedule_redraw(widget); + panel_notifier_activate(notifier); +} + +static void +panel_notifier_button_handler(struct widget *widget, struct input *input, + uint32_t time, uint32_t button, + enum wl_pointer_button_state state, + void *data) +{ + struct panel_notifier *notifier; + + notifier = widget_get_user_data(widget); + widget_schedule_redraw(widget); + if (state == WL_POINTER_BUTTON_STATE_RELEASED) + panel_notifier_activate(notifier); +} + +static void +panel_notifier_redraw_handler(struct widget *widget, void *data) +{ + struct panel_notifier *notifier = data; + struct rectangle allocation; + char *title; + cairo_text_extents_t extents; + cairo_t *cr; + + widget_get_allocation(widget, &allocation); + if (allocation.width == 0 || !notifier->mgsurf) + return; + + cr = widget_cairo_create(notifier->panel->widget); + + rounded_rect(cr, allocation.x, allocation.y, + allocation.x + allocation.width + 3, + allocation.y + allocation.height + 3, 3); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 0.8); + cairo_fill(cr); + + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + title = (notifier->mgsurf->title) ? + notifier->mgsurf->title : "<Default>"; + cairo_text_extents(cr, title, &extents); + cairo_move_to(cr, + allocation.x + (allocation.width - extents.width) / 2, + allocation.y + allocation.height); + cairo_show_text(cr, title); + + cairo_destroy(cr); +} + +static struct panel_notifier * +panel_add_notifier(struct panel *panel, + struct desktop_managed_surface *mgsurf) +{ + struct panel_notifier *notifier; + + notifier = xzalloc(sizeof *notifier); + notifier->panel = panel; + notifier->mgsurf = mgsurf; + + wl_list_insert(panel->notifier_list.prev, ¬ifier->link); + + notifier->widget = widget_add_widget(panel->widget, notifier); + widget_set_touch_up_handler(notifier->widget, + panel_notifier_touch_up_handler); + widget_set_button_handler(notifier->widget, + panel_notifier_button_handler); + widget_set_redraw_handler(notifier->widget, + panel_notifier_redraw_handler); + + widget_schedule_redraw(notifier->widget); + update_window(panel->window); + + return notifier; +} + +static void clock_func(struct task *task, uint32_t events) { struct panel_clock *clock = @@ -477,8 +621,12 @@ panel_resize_handler(struct widget *widget, int32_t width, int32_t height, void *data) { struct panel_launcher *launcher; + struct panel_notifier *notifier; struct panel *panel = data; + cairo_t *cr; + cairo_text_extents_t extents; int x, y, w, h; + int last_launcher_x; x = 10; y = 16; @@ -489,6 +637,26 @@ panel_resize_handler(struct widget *widget, x, y - h / 2, w + 1, h + 1); x += w + 10; } + + last_launcher_x = x; + x = width - 180; + wl_list_for_each(notifier, &panel->notifier_list, link) { + widget_set_allocation(notifier->widget, 0, 0, 0, 0); + if (!notifier->mgsurf) + continue; + cr = widget_cairo_create(notifier->widget); + cairo_text_extents(cr, (notifier->mgsurf->title) ? + notifier->mgsurf->title : "<Default>", + &extents); + x -= extents.width + 10; + if (x > last_launcher_x) + widget_set_allocation(notifier->widget, + x, y - extents.height /2, + extents.width + 1, + extents.height + 1); + cairo_destroy(cr); + } + h=20; w=170; @@ -528,14 +696,17 @@ panel_destroy_launcher(struct panel_launcher *launcher) static void panel_destroy(struct panel *panel) { - struct panel_launcher *tmp; - struct panel_launcher *launcher; + struct panel_launcher *launcher, *l_tmp; + struct panel_notifier *notifier, *n_tmp; panel_destroy_clock(panel->clock); - wl_list_for_each_safe(launcher, tmp, &panel->launcher_list, link) + wl_list_for_each_safe(launcher, l_tmp, &panel->launcher_list, link) panel_destroy_launcher(launcher); + wl_list_for_each_safe(notifier, n_tmp, &panel->notifier_list, link) + panel_destroy_notifier(notifier); + widget_destroy(panel->widget); window_destroy(panel->window); @@ -554,6 +725,7 @@ panel_create(struct desktop *desktop) panel->window = window_create_custom(desktop->display); panel->widget = window_add_widget(panel->window, panel); wl_list_init(&panel->launcher_list); + wl_list_init(&panel->notifier_list); window_set_title(panel->window, "panel"); window_set_user_data(panel->window, panel); @@ -952,6 +1124,17 @@ static void managed_surface_presented(void *data, struct managed_surface *managed_surface) { + struct desktop_managed_surface *mgsurf = data; + struct desktop *desktop = mgsurf->desktop; + struct output *output; + struct panel_notifier *notifier; + + wl_list_for_each(output, &desktop->outputs, link) { + notifier = managed_surface_get_notifier(output, mgsurf); + + if (!notifier && output->panel) + notifier = panel_add_notifier(output->panel, mgsurf); + } } static void @@ -972,13 +1155,26 @@ managed_surface_removed(void *data, struct managed_surface *managed_surface) { struct desktop_managed_surface *mgsurf = data; + struct desktop *desktop = mgsurf->desktop; + struct output *output; + struct panel_notifier *notifier; + + wl_list_for_each(output, &desktop->outputs, link) { + notifier = managed_surface_get_notifier(output, mgsurf); + + if (notifier) + panel_destroy_notifier(notifier); + } + + managed_surface_destroy(mgsurf->managed_surface); if (mgsurf->title) free(mgsurf->title); + mgsurf->title = NULL; + mgsurf->desktop = NULL; wl_list_remove(&mgsurf->link); - free(mgsurf); - managed_surface_destroy(managed_surface); + free(mgsurf); } static const struct managed_surface_listener managed_surface_listener = { @@ -1076,6 +1272,7 @@ desktop_shell_add_managed_surface(void *data, mgsurf = xzalloc(sizeof *mgsurf); mgsurf->managed_surface = managed_surface; mgsurf->title = (title) ? xstrdup(title) : NULL; + mgsurf->desktop = desktop; wl_list_insert(desktop->managed_surfaces.prev, &mgsurf->link); -- 1.8.3.1 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
