This patch uses the special surface_data interface to send information about the surface to the shell. The shell then uses this information to render a window list in the panel. --- clients/desktop-shell.c | 479 +++++++++++++++++++++++++++++++++++++++++++++-- data/Makefile.am | 1 + data/list_item_icon.png | Bin 0 -> 176 bytes src/compositor.c | 3 + src/compositor.h | 1 + src/shell.c | 201 ++++++++++++++++++++ 6 files changed, 671 insertions(+), 14 deletions(-) create mode 100644 data/list_item_icon.png
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 41e7daa..2b5f7c8 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -44,6 +44,8 @@ #include "desktop-shell-client-protocol.h" +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + extern char **environ; /* defined by libc */ struct desktop { @@ -51,31 +53,55 @@ struct desktop { struct desktop_shell *shell; struct unlock_dialog *unlock_dialog; struct task unlock_task; + struct wl_list surfaces; struct wl_list outputs; + uint32_t output_count; struct window *grab_window; struct widget *grab_widget; enum cursor_type grab_cursor; + + struct surface_data_manager *surface_data_manager; }; struct surface { + struct surface_data *surface_data; + struct desktop *desktop; + uint32_t output_mask; + char *title; + + /* One window list item per panel of the surface's output_mask */ + struct wl_list item_list; + + struct wl_list link; +}; + +struct resize { void (*configure)(void *data, struct desktop_shell *desktop_shell, uint32_t edges, struct window *window, int32_t width, int32_t height); }; +struct rgba { + float r, g, b, a; +}; + struct panel { - struct surface base; + struct resize base; struct window *window; struct widget *widget; struct wl_list launcher_list; + struct wl_list window_list; + struct rectangle window_list_rect; + uint32_t surface_count; + struct rgba focused_item; struct panel_clock *clock; }; struct background { - struct surface base; + struct resize base; struct window *window; struct widget *widget; }; @@ -83,11 +109,22 @@ struct background { struct output { struct wl_output *output; struct wl_list link; + uint32_t id; struct panel *panel; struct background *background; }; +struct list_item { + struct surface *surface; + struct widget *widget; + struct panel *panel; + cairo_surface_t *icon; + int focused, highlight; + struct wl_list link; + struct wl_list surface_link; +}; + struct panel_launcher { struct widget *widget; struct panel *panel; @@ -249,6 +286,15 @@ set_hex_color(cairo_t *cr, uint32_t color) } static void +get_hex_color_rgba(uint32_t color, float *r, float *g, float *b, float *a) +{ + *r = ((color >> 16) & 0xff) / 255.0; + *g = ((color >> 8) & 0xff) / 255.0; + *b = ((color >> 0) & 0xff) / 255.0; + *a = ((color >> 24) & 0xff) / 255.0; +} + +static void panel_redraw_handler(struct widget *widget, void *data) { cairo_surface_t *surface; @@ -421,15 +467,46 @@ panel_button_handler(struct widget *widget, } static void +panel_window_list_schedule_redraw(struct panel *panel) +{ + struct list_item *item; + int item_width, padding, x, w; + + /* If there are no window list items, redraw the panel to clear it */ + if (wl_list_empty(&panel->window_list)) { + widget_schedule_redraw(panel->widget); + return; + } + + item_width = (panel->window_list_rect.width / panel->surface_count); + padding = 2; + + x = panel->window_list_rect.x + padding; + w = MIN(item_width - padding, 200); + + wl_list_for_each(item, &panel->window_list, link) { + widget_set_allocation(item->widget, x, 4, w, 24); + + x += w + padding; + widget_schedule_redraw(item->widget); + } +} + +static void panel_resize_handler(struct widget *widget, int32_t width, int32_t height, void *data) { struct panel_launcher *launcher; + struct rectangle launcher_rect; + struct rectangle clock_rect; struct panel *panel = data; int x, y, w, h; - + x = 10; y = 16; + + launcher_rect.x = x; + wl_list_for_each(launcher, &panel->launcher_list, link) { w = cairo_image_surface_get_width(launcher->icon); h = cairo_image_surface_get_height(launcher->icon); @@ -437,12 +514,25 @@ panel_resize_handler(struct widget *widget, x, y - h / 2, w + 1, h + 1); x += w + 10; } - h=20; + + launcher_rect.width = x - launcher_rect.x; + w=170; + h=20; if (panel->clock) widget_set_allocation(panel->clock->widget, - width - w - 8, y - h / 2, w + 1, h + 1); + width - w - 8, 4, w, 24); + + widget_get_allocation(panel->clock->widget, &clock_rect); + + panel->window_list_rect.x = launcher_rect.x + launcher_rect.width; + panel->window_list_rect.y = 2; + panel->window_list_rect.width = width - + panel->window_list_rect.x - + (clock_rect.width + 20); + panel->window_list_rect.height = 28; + panel_window_list_schedule_redraw(panel); } static void @@ -451,8 +541,8 @@ panel_configure(void *data, uint32_t edges, struct window *window, int32_t width, int32_t height) { - struct surface *surface = window_get_user_data(window); - struct panel *panel = container_of(surface, struct panel, base); + struct resize *resize = window_get_user_data(window); + struct panel *panel = container_of(resize, struct panel, base); window_schedule_resize(panel->window, width, 32); } @@ -490,6 +580,22 @@ panel_destroy(struct panel *panel) free(panel); } +static void +panel_set_list_item_focus_color(struct panel *panel) +{ + float r, g, b, a; + + /* Consider panel color when choosing item highlight color */ + get_hex_color_rgba(key_panel_color, &r, &b, &g, &a); + r += 0.2; + g += 0.2; + b += 0.2; + panel->focused_item.r = r > 1.0 ? 0.6 : r; + panel->focused_item.g = g > 1.0 ? 0.6 : g; + panel->focused_item.b = b > 1.0 ? 0.6 : b; + panel->focused_item.a = 0.75; +} + static struct panel * panel_create(struct display *display) { @@ -502,6 +608,7 @@ panel_create(struct display *display) panel->window = window_create_custom(display); panel->widget = window_add_widget(panel->window, panel); wl_list_init(&panel->launcher_list); + wl_list_init(&panel->window_list); window_set_title(panel->window, "panel"); window_set_user_data(panel->window, panel); @@ -509,7 +616,9 @@ panel_create(struct display *display) widget_set_redraw_handler(panel->widget, panel_redraw_handler); widget_set_resize_handler(panel->widget, panel_resize_handler); widget_set_button_handler(panel->widget, panel_button_handler); - + + panel->surface_count = 0; + panel_set_list_item_focus_color(panel); panel_add_clock(panel); return panel; @@ -518,18 +627,17 @@ panel_create(struct display *display) static cairo_surface_t * load_icon_or_fallback(const char *icon) { - cairo_surface_t *surface = cairo_image_surface_create_from_png(icon); + cairo_surface_t *surface = load_cairo_surface(icon); cairo_t *cr; - if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) + if (surface) return surface; cairo_surface_destroy(surface); fprintf(stderr, "ERROR loading icon from file '%s'\n", icon); /* draw fallback icon */ - surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - 20, 20); + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 20, 20); cr = cairo_create(surface); cairo_set_source_rgba(cr, 0.8, 0.8, 0.8, 1); @@ -862,9 +970,9 @@ desktop_shell_configure(void *data, int32_t width, int32_t height) { struct window *window = wl_surface_get_user_data(surface); - struct surface *s = window_get_user_data(window); + struct resize *r = window_get_user_data(window); - s->configure(data, desktop_shell, edges, window, width, height); + r->configure(data, desktop_shell, edges, window, width, height); } static void @@ -946,6 +1054,328 @@ background_destroy(struct background *background) free(background); } +static void +panel_list_item_redraw_handler(struct widget *widget, void *data) +{ + cairo_t *cr; + cairo_surface_t *surface; + struct list_item *item = data; + struct rectangle rect; + cairo_text_extents_t extents; + cairo_font_extents_t font_extents; + int icon_width, icon_height; + unsigned int dots; + double padding; + char title[128]; + + widget_get_allocation(widget, &rect); + if (rect.width == 0) + return; + + surface = window_get_surface(item->panel->window); + cr = cairo_create(surface); + + if (item->focused) { + cairo_set_source_rgba(cr, item->panel->focused_item.r, + item->panel->focused_item.g, + item->panel->focused_item.b, + item->panel->focused_item.a); + cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height); + cairo_fill(cr); + } + + icon_width = cairo_image_surface_get_width(item->icon); + icon_height = cairo_image_surface_get_height(item->icon); + padding = (rect.height / 2.f) - (icon_height / 2.f); + if (rect.width > icon_width * 2) { + cairo_set_source_surface(cr, item->icon, + rect.x + padding, + rect.y + padding); + cairo_paint(cr); + } else { + icon_width = 0; + icon_height = 0; + padding = 1; + } + + strcpy(title, item->surface->title); + cairo_select_font_face(cr, "sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 14); + cairo_text_extents(cr, title, &extents); + + /* If the string is too long, clip text to button width */ + while (extents.width > (rect.width - (icon_width + padding * 3))) { + title[strlen(title) - 1] = '\0'; + cairo_text_extents(cr, title, &extents); + if (extents.width <= 0) { + title[0] = '\0'; + break; + } + } + + /* If the text is clipped, add an ellipsis */ + dots = 3; + if (strlen(title) < dots) + dots = strlen(title) + 1; + if (strlen(title) != strlen(item->surface->title)) + while (dots-- > 0) + title[strlen(title) - dots] = '.'; + + cairo_font_extents (cr, &font_extents); + cairo_move_to(cr, rect.x + icon_width + padding * 3 + 1, + rect.y + 3 * (rect.height >> 2) + 1); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_show_text(cr, title); + cairo_move_to(cr, rect.x + icon_width + padding * 3, + rect.y + 3 * (rect.height >> 2)); + if (item->highlight) + cairo_set_source_rgb(cr, 1, 1, 1); + else + cairo_set_source_rgb(cr, 0.85, 0.85, 0.85); + cairo_show_text(cr, title); + cairo_destroy(cr); +} + +static int +panel_list_item_motion_handler(struct widget *widget, struct input *input, + uint32_t time, float x, float y, void *data) +{ + struct list_item *item = data; + + widget_set_tooltip(widget, basename((char *)item->surface->title), x, y); + + return CURSOR_LEFT_PTR; +} + +static int +panel_list_item_enter_handler(struct widget *widget, struct input *input, + float x, float y, void *data) +{ + struct list_item *item = data; + + item->highlight = 1; + widget_schedule_redraw(widget); + + return CURSOR_LEFT_PTR; +} + +static void +panel_list_item_leave_handler(struct widget *widget, + struct input *input, void *data) +{ + struct list_item *item = data; + + item->highlight = 0; + widget_destroy_tooltip(widget); + widget_schedule_redraw(widget); +} + +static void +panel_list_item_button_handler(struct widget *widget, + struct input *input, uint32_t time, + uint32_t button, + enum wl_pointer_button_state state, void *data) +{ + widget_schedule_redraw(widget); + /* TODO: Toggle minimize */ +} + +static struct list_item * +panel_list_item_add(struct panel *panel, const char *icon, const char *text) +{ + struct list_item *item; + item = malloc(sizeof *item); + memset(item, 0, sizeof *item); + + item->icon = load_icon_or_fallback(icon); + + item->panel = panel; + wl_list_insert(panel->window_list.prev, &item->link); + panel->surface_count++; + + item->widget = widget_add_widget(panel->widget, item); + widget_set_enter_handler(item->widget, panel_list_item_enter_handler); + widget_set_leave_handler(item->widget, panel_list_item_leave_handler); + widget_set_button_handler(item->widget, panel_list_item_button_handler); + widget_set_redraw_handler(item->widget, panel_list_item_redraw_handler); + widget_set_motion_handler(item->widget, panel_list_item_motion_handler); + + return item; +} + +static void +panel_list_item_remove(struct list_item *item) +{ + item->panel->surface_count--; + wl_list_remove(&item->link); + wl_list_remove(&item->surface_link); + widget_destroy(item->widget); + panel_window_list_schedule_redraw(item->panel); + cairo_surface_destroy(item->icon); + free(item); +} + +static int +panel_list_item_exists(struct panel *panel, struct surface *surface) +{ + struct list_item *p_item, *s_item; + + wl_list_for_each(p_item, &panel->window_list, link) { + wl_list_for_each(s_item, &surface->item_list, surface_link) { + if (p_item == s_item) + return 1; + } + } + + return 0; +} + +static void +output_update_window_list(struct output *output, struct surface *surface) +{ + struct list_item *item, *next; + struct panel *panel; + + panel = output->panel; + + /* Make a list item for each panel of the surfaces output mask */ + if ((1 << output->id) & surface->output_mask) { + if (!panel_list_item_exists(panel, surface)) { + item = panel_list_item_add(panel, + DATADIR "/weston/list_item_icon.png", + surface->title); + wl_list_insert(surface->item_list.prev, + &item->surface_link); + item->surface = surface; + } + } else { + /* Remove item from panel if surface + * is no longer on the output */ + wl_list_for_each_safe(item, next, &surface->item_list, + surface_link) { + if (item->panel == panel) + panel_list_item_remove(item); + } + } + + panel_window_list_schedule_redraw(panel); +} + +static void +desktop_destroy_surface(struct surface *surface) +{ + struct list_item *item, *next; + + wl_list_for_each_safe(item, next, &surface->item_list, surface_link) + panel_list_item_remove(item); + + wl_list_remove(&surface->link); + free(surface->title); + free(surface); +} + +static void +desktop_update_list_items(struct desktop *desktop, struct surface *surface) +{ + struct output *output; + + wl_list_for_each(output, &desktop->outputs, link) + output_update_window_list(output, surface); +} + +static void +surface_data_set_output_mask(void *data, + struct surface_data *surface_data, + uint32_t output_mask) +{ + struct desktop *desktop; + struct surface *surface = data; + + desktop = surface->desktop; + + surface->output_mask = output_mask; + + desktop_update_list_items(desktop, surface); +} + +static void +surface_data_set_title(void *data, + struct surface_data *surface_data, + const char *title) +{ + struct desktop *desktop; + struct surface *surface = data; + + desktop = surface->desktop; + + if (surface->title) + free(surface->title); + surface->title = strdup(title); + + desktop_update_list_items(desktop, surface); +} + +static void +surface_data_destroy_handler(void *data, struct surface_data *surface_data) +{ + struct list_item *item, *next; + struct desktop *desktop; + struct surface *surface = data; + struct output *output; + struct panel *panel; + + desktop = surface->desktop; + + surface_data_destroy(surface_data); + + wl_list_for_each(output, &desktop->outputs, link) { + panel = output->panel; + wl_list_for_each_safe(item, next, &panel->window_list, link) { + if (surface_data == item->surface->surface_data) { + desktop_destroy_surface(item->surface); + return; + } + } + } +} + +static const struct surface_data_listener surface_data_listener = { + surface_data_set_output_mask, + surface_data_set_title, + surface_data_destroy_handler +}; + +static void +surface_data_receive_surface_object(void *data, + struct surface_data_manager *manager, + struct surface_data *surface_data) +{ + struct desktop *desktop = data; + struct surface *surface; + + surface = calloc(1, sizeof *surface); + + if (!surface) { + fprintf(stderr, "ERROR: Failed to allocate memory!\n"); + exit(EXIT_FAILURE); + } + + surface->surface_data = surface_data; + surface->desktop = desktop; + surface->title = strdup("unknown"); + surface->output_mask = 1; + wl_list_init(&surface->item_list); + wl_list_insert(&desktop->surfaces, &surface->link); + surface_data_add_listener(surface_data, + &surface_data_listener, surface); +} + +static const struct surface_data_manager_listener surface_data_manager_listener = { + surface_data_receive_surface_object +}; + static struct background * background_create(struct desktop *desktop) { @@ -1022,6 +1452,15 @@ desktop_destroy_outputs(struct desktop *desktop) } static void +desktop_destroy_surfaces(struct desktop *desktop) +{ + struct surface *surface, *next; + + wl_list_for_each_safe(surface, next, &desktop->surfaces, link) + desktop_destroy_surface(surface); +} + +static void create_output(struct desktop *desktop, uint32_t id) { struct output *output; @@ -1033,6 +1472,8 @@ create_output(struct desktop *desktop, uint32_t id) output->output = display_bind(desktop->display, id, &wl_output_interface, 1); + output->id = desktop->output_count++; + wl_list_insert(&desktop->outputs, &output->link); } @@ -1048,6 +1489,12 @@ global_handler(struct display *display, uint32_t id, desktop_shell_add_listener(desktop->shell, &listener, desktop); } else if (!strcmp(interface, "wl_output")) { create_output(desktop, id); + } else if (!strcmp(interface, "surface_data_manager")) { + desktop->surface_data_manager = + display_bind(display, id, + &surface_data_manager_interface, 1); + surface_data_manager_add_listener(desktop->surface_data_manager, + &surface_data_manager_listener, desktop); } } @@ -1100,6 +1547,9 @@ int main(int argc, char *argv[]) return -1; } + wl_list_init(&desktop.surfaces); + desktop.output_count = 0; + display_set_user_data(desktop.display, &desktop); display_set_global_handler(desktop.display, global_handler); @@ -1133,6 +1583,7 @@ int main(int argc, char *argv[]) /* Cleanup */ grab_surface_destroy(&desktop); + desktop_destroy_surfaces(&desktop); desktop_destroy_outputs(&desktop); if (desktop.unlock_dialog) unlock_dialog_destroy(desktop.unlock_dialog); diff --git a/data/Makefile.am b/data/Makefile.am index a7cc944..293d2bc 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -7,6 +7,7 @@ dist_westondata_DATA = \ terminal.png \ border.png \ icon_window.png \ + list_item_icon.png \ sign_close.png \ sign_maximize.png \ sign_minimize.png diff --git a/data/list_item_icon.png b/data/list_item_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ac987e997313910ec3e02a11be8ccda0dfa581c7 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPaH$RJ!-UgFp7lA^yo-U3d7N_4%cI0AE;5i(0^Z))B z|EBQpgWZ)55eu3H82wmS6TZt#lE`$@S@Cy{aM-usE&4llHh-IQIlXHpO8~cw3TFo| P&>#j+S3j3^P6<r_g#|R0 literal 0 HcmV?d00001 diff --git a/src/compositor.c b/src/compositor.c index a2860fd..c6637c3 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -509,6 +509,8 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask) if (1 << output->id & left) wl_surface_send_leave(&es->surface.resource, resource); } + + wl_signal_emit(&es->compositor->output_mask_update_signal, es); } static void @@ -3049,6 +3051,7 @@ weston_compositor_init(struct weston_compositor *ec, wl_signal_init(&ec->wake_signal); wl_signal_init(&ec->show_input_panel_signal); wl_signal_init(&ec->hide_input_panel_signal); + wl_signal_init(&ec->output_mask_update_signal); wl_signal_init(&ec->seat_created_signal); ec->launcher_sock = weston_environment_get_fd("WESTON_LAUNCHER_SOCK"); diff --git a/src/compositor.h b/src/compositor.h index 4a0c1e3..36ec337 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -301,6 +301,7 @@ struct weston_compositor { struct wl_signal show_input_panel_signal; struct wl_signal hide_input_panel_signal; + struct wl_signal output_mask_update_signal; struct wl_signal seat_created_signal; diff --git a/src/shell.c b/src/shell.c index 3da5321..5f09a45 100644 --- a/src/shell.c +++ b/src/shell.c @@ -88,6 +88,7 @@ struct desktop_shell { struct wl_listener destroy_listener; struct wl_listener show_input_panel_listener; struct wl_listener hide_input_panel_listener; + struct wl_listener output_mask_update_listener; struct weston_layer fullscreen_layer; struct weston_layer panel_layer; @@ -107,6 +108,8 @@ struct desktop_shell { uint32_t deathstamp; } child; + struct wl_resource *surface_data_manager; + bool locked; bool showing_input_panels; bool prepare_event_sent; @@ -217,6 +220,7 @@ struct shell_surface { struct wl_list link; const struct weston_shell_client *client; + struct wl_resource *surface_data; }; struct shell_grab { @@ -1415,6 +1419,110 @@ shell_surface_pong(struct wl_client *client, struct wl_resource *resource, } static void +surface_data_object_destroy(struct wl_resource *resource) +{ + struct shell_surface *shsurf = resource->data; + + free(resource); + + if (!shsurf) + return; + + shsurf->surface_data = NULL; +} + +static void +surface_data_destroy_handler(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct surface_data_interface + surface_data_implementation = { + surface_data_destroy_handler +}; + +static int +create_surface_data(struct desktop_shell *shell, struct shell_surface *shsurf) +{ + struct wl_resource *surface_data; + + if (shsurf->surface_data) + return -1; + + surface_data = malloc(sizeof *surface_data); + if (surface_data == NULL) + return -1; + + surface_data->data = shsurf; + surface_data->object.id = 0; + surface_data->object.interface = &surface_data_interface; + surface_data->destroy = surface_data_object_destroy; + surface_data->object.implementation = + (void (**)(void)) &surface_data_implementation; + wl_signal_init(&surface_data->destroy_signal); + + wl_client_add_resource(shell->surface_data_manager->client, surface_data); + + shsurf->surface_data = surface_data; + + surface_data_manager_send_surface_object(shell->surface_data_manager, + shsurf->surface_data); + + return 0; +} + +static bool +surface_is_window_list_candidate(struct weston_surface *surface) +{ + struct desktop_shell *shell; + struct shell_surface *shsurf; + + shsurf = get_shell_surface(surface); + if (!shsurf) + return false; + + shell = shsurf->shell; + + if (!shell->surface_data_manager) + return false; + + switch (shsurf->type) { + default: + case SHELL_SURFACE_TRANSIENT: + case SHELL_SURFACE_POPUP: + case SHELL_SURFACE_NONE: + return false; + case SHELL_SURFACE_FULLSCREEN: + case SHELL_SURFACE_MAXIMIZED: + case SHELL_SURFACE_TOPLEVEL: + return true; + } +} + +static void +send_surface_data_output_mask(struct weston_surface *surface) +{ + struct shell_surface *shsurf = get_shell_surface(surface); + + if (shsurf && shsurf->surface_data) + surface_data_send_output_mask(shsurf->surface_data, + surface->output_mask); +} + +static void +send_surface_data_title(struct weston_surface *surface) +{ + struct shell_surface *shsurf = get_shell_surface(surface); + + if (shsurf && shsurf->surface_data) + surface_data_send_title(shsurf->surface_data, + shsurf->title == NULL ? + "Surface" : shsurf->title); +} + +static void shell_surface_set_title(struct wl_client *client, struct wl_resource *resource, const char *title) { @@ -1422,6 +1530,7 @@ shell_surface_set_title(struct wl_client *client, free(shsurf->title); shsurf->title = strdup(title); + send_surface_data_title(shsurf->surface); } static void @@ -1538,6 +1647,10 @@ set_surface_type(struct shell_surface *shsurf) default: break; } + + if (surface_is_window_list_candidate(shsurf->surface)) + create_surface_data(shsurf->shell, shsurf); + send_surface_data_title(surface); } static void @@ -1984,6 +2097,8 @@ static const struct wl_shell_surface_interface shell_surface_implementation = { static void destroy_shell_surface(struct shell_surface *shsurf) { + if (shsurf->surface_data) + surface_data_send_gone(shsurf->surface_data); if (shsurf->popup.grab.pointer) wl_pointer_end_grab(shsurf->popup.grab.pointer); @@ -2390,6 +2505,37 @@ static const struct desktop_shell_interface desktop_shell_implementation = { desktop_shell_set_grab_surface }; +static void +surface_data_create_all_objects(struct desktop_shell *shell) +{ + struct weston_surface *surface; + struct shell_surface *shsurf; + struct workspace *ws; + + ws = get_current_workspace(shell); + + wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { + if (surface_is_window_list_candidate(surface)) { + shsurf = get_shell_surface(surface); + create_surface_data(shell, shsurf); + } + } +} + +static void +surface_data_send_all_info(struct desktop_shell *shell) +{ + struct weston_surface *surface; + struct workspace *ws; + + ws = get_current_workspace(shell); + + wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { + send_surface_data_output_mask(surface); + send_surface_data_title(surface); + } +} + static enum shell_surface_type get_shell_surface_type(struct weston_surface *surface) { @@ -2946,6 +3092,22 @@ show_input_panels(struct wl_listener *listener, void *data) } static void +output_mask_update(struct wl_listener *listener, void *data) +{ + struct weston_surface *surface = data; + struct shell_surface *shsurf; + + if (!surface) + return; + + shsurf = get_shell_surface(surface); + + if (shsurf && shsurf->surface_data) + surface_data_send_output_mask(shsurf->surface_data, + surface->output_mask); +} + +static void hide_input_panels(struct wl_listener *listener, void *data) { struct desktop_shell *shell = @@ -3304,6 +3466,38 @@ bind_desktop_shell(struct wl_client *client, } static void +unbind_surface_data_manager(struct wl_resource *resource) +{ + struct desktop_shell *shell = resource->data; + + shell->surface_data_manager = NULL; + free(resource); +} + +static void +bind_surface_data_manager(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct desktop_shell *shell = data; + struct wl_resource *resource; + + resource = wl_client_add_object(client, &surface_data_manager_interface, + NULL, id, shell); + + if (client == shell->child.client) { + resource->destroy = unbind_surface_data_manager; + shell->surface_data_manager = resource; + surface_data_create_all_objects(shell); + surface_data_send_all_info(shell); + return; + } + + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "permission to bind desktop_shell denied"); + wl_resource_destroy(resource); +} + +static void screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height) { struct desktop_shell *shell = surface->private; @@ -3978,6 +4172,7 @@ shell_destroy(struct wl_listener *listener, void *data) wl_list_remove(&shell->wake_listener.link); wl_list_remove(&shell->show_input_panel_listener.link); wl_list_remove(&shell->hide_input_panel_listener.link); + wl_list_remove(&shell->output_mask_update_listener.link); wl_array_for_each(ws, &shell->workspaces.array) workspace_destroy(*ws); @@ -4087,6 +4282,8 @@ module_init(struct weston_compositor *ec, wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener); shell->hide_input_panel_listener.notify = hide_input_panels; wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener); + shell->output_mask_update_listener.notify = output_mask_update; + wl_signal_add(&ec->output_mask_update_signal, &shell->output_mask_update_listener); ec->ping_handler = ping_handler; ec->shell_interface.shell = shell; ec->shell_interface.create_shell_surface = create_shell_surface; @@ -4144,6 +4341,10 @@ module_init(struct weston_compositor *ec, if (wl_display_add_global(ec->wl_display, &workspace_manager_interface, shell, bind_workspace_manager) == NULL) return -1; + if (wl_display_add_global(ec->wl_display, &surface_data_manager_interface, + shell, bind_surface_data_manager) == NULL) + return -1; + shell->child.deathstamp = weston_compositor_get_time(); -- 1.7.10.4 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel