This patch uses the special surface_data interface to send surface_data to the shell. The shell then uses this information to render a window list in the panel.
--- v5: * Removed unneeded calls in map(). The call to send_output_mask() in weston_surface_update_output_mask() takes care of sending the output_mask. The calls in map() were left over from before the send_output_mask function pointer existed. * Changed inital value of the title string in desktop-shell clients/desktop-shell.c | 504 ++++++++++++++++++++++++++++++++++++++++++++++-- src/compositor.c | 2 + src/compositor.h | 1 + src/shell.c | 182 +++++++++++++++++ 4 files changed, 671 insertions(+), 18 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 588dc1c..8718c82 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 { @@ -52,36 +54,55 @@ struct desktop { struct unlock_dialog *unlock_dialog; struct task unlock_task; 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 wl_list item_list; + struct surface_data *surface_data; + uint32_t output_mask; + char *title; +}; + +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; }; struct output { struct wl_output *output; + uint32_t id; struct wl_list link; struct panel *panel; @@ -99,6 +120,16 @@ struct panel_launcher { struct wl_array argv; }; +struct list_item { + struct surface *surface; + struct widget *widget; + struct panel *panel; + cairo_surface_t *icon; + int focused, pressed; + struct wl_list link; + struct wl_list surface_link; +}; + struct panel_clock { struct widget *widget; struct panel *panel; @@ -249,6 +280,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; @@ -337,7 +377,7 @@ panel_clock_redraw_handler(struct widget *widget, void *data) surface = window_get_surface(clock->panel->window); cr = cairo_create(surface); - cairo_select_font_face(cr, "sans", + cairo_select_font_face(cr, "helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 14); @@ -411,15 +451,49 @@ panel_button_handler(struct widget *widget, } static void +panel_window_list_schedule_redraw(struct panel *panel) +{ + struct list_item *item; + float x, y, w, h; + float item_width, padding; + + /* 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 = ((float) panel->window_list_rect.width / + panel->surface_count); + padding = MIN(item_width * 0.1f, 10.0f); + + x = panel->window_list_rect.x + padding; + y = 16; + w = MIN(item_width - padding, 200); + h = 24; + + wl_list_for_each(item, &panel->window_list, link) { + widget_set_allocation(item->widget, x, y - h / 2, w + 1, h + 1); + 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); @@ -427,12 +501,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); + + 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 @@ -441,12 +528,31 @@ 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 resize *surface = window_get_user_data(window); struct panel *panel = container_of(surface, struct panel, base); window_schedule_resize(panel->window, width, 32); } +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); + if (r += 0.2, g += 0.2, b += 0.2, r > 1.0 || g > 1.0 || b > 1.0) { + panel->focused_item.r = 0.6; + panel->focused_item.g = 0.6; + panel->focused_item.b = 0.6; + } else { + panel->focused_item.r = r; + panel->focused_item.g = g; + panel->focused_item.b = b; + } + panel->focused_item.a = 0.75; +} + static struct panel * panel_create(struct display *display) { @@ -459,6 +565,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); @@ -466,7 +573,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; @@ -475,18 +584,21 @@ 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; cairo_t *cr; - - if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) - return surface; - - cairo_surface_destroy(surface); - fprintf(stderr, "ERROR loading icon from file '%s'\n", icon); +#ifdef CAIRO_HAS_PNG_FUNCTIONS + if (icon) { + surface = cairo_image_surface_create_from_png(icon); + if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) + return surface; + + cairo_surface_destroy(surface); + fprintf(stderr, "ERROR loading icon from file '%s'\n", icon); + } +#endif /* 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); @@ -810,7 +922,7 @@ 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 *s = window_get_user_data(window); s->configure(data, desktop_shell, edges, window, width, height); } @@ -885,6 +997,352 @@ static const struct desktop_shell_listener listener = { desktop_shell_grab_cursor }; +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; + unsigned int dots = 3; + 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_move_to(cr, rect.x, rect.y); + cairo_line_to(cr, rect.x + rect.width, rect.y); + cairo_line_to(cr, rect.x + rect.width, rect.y + rect.height); + cairo_line_to(cr, rect.x, rect.y + rect.height); + cairo_line_to(cr, rect.x, rect.y); + cairo_fill(cr); + } + + icon_width = cairo_image_surface_get_width(item->icon); + if (rect.width > icon_width * 2) { + cairo_set_source_surface(cr, item->icon, + rect.x, rect.y); + cairo_paint(cr); + } else + icon_width = 0; + + strcpy(title, item->surface->title); + cairo_select_font_face(cr, "helvetica", + 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 - (10 + icon_width))) { + 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 */ + 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 + 10 + icon_width, + 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 + 9 + icon_width, + rect.y + 3 * (rect.height >> 2)); + if (item->focused) + 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->focused = 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->focused = 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); + 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)) { + /* TODO: Use a real icon instead of + * passing NULL for the fallback */ + item = panel_list_item_add(panel, NULL, 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 struct surface* +surface_data_create_surface(struct surface_data *surface_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->title = strdup("unknown"); + surface->output_mask = 1; + wl_list_init(&surface->item_list); + + return surface; +} + +static void +surface_data_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); + + free(surface->title); + free(surface); +} + +static struct surface * +surface_data_get_surface(struct desktop *desktop, struct surface_data *surface_data) +{ + struct output *output; + struct list_item *item; + + wl_list_for_each(output, &desktop->outputs, link) { + wl_list_for_each(item, &output->panel->window_list, link) { + if (surface_data == item->surface->surface_data) + return item->surface; + } + } + + return NULL; +} + +static void +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; + + desktop = data; + + surface = surface_data_get_surface(desktop, surface_data); + + if (!surface) + surface = surface_data_create_surface(surface_data); + + surface->output_mask = output_mask; + + 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; + + desktop = data; + + surface = surface_data_get_surface(desktop, surface_data); + + if (!surface) + surface = surface_data_create_surface(surface_data); + + if (surface->title) + free(surface->title); + surface->title = strdup(title); + + 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 output *output; + struct panel *panel; + + desktop = data; + + 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) { + surface_data_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) +{ + surface_data_add_listener(surface_data, + &surface_data_listener, data); +} + +static const struct surface_data_manager_listener surface_data_manager_listener = { + surface_data_receive_surface_object +}; + static struct background * background_create(struct desktop *desktop) { @@ -941,10 +1399,12 @@ create_output(struct desktop *desktop, uint32_t id) if (!output) return; + output->id = desktop->output_count++; + output->output = wl_display_bind(display_get_display(desktop->display), id, &wl_output_interface); - wl_list_insert(&desktop->outputs, &output->link); + wl_list_insert(desktop->outputs.prev, &output->link); } static void @@ -957,6 +1417,12 @@ global_handler(struct wl_display *display, uint32_t id, desktop->shell = wl_display_bind(display, id, &desktop_shell_interface); desktop_shell_add_listener(desktop->shell, &listener, desktop); + } else if (strcmp(interface, "surface_data_manager") == 0) { + desktop->surface_data_manager = + wl_display_bind(display, id, + &surface_data_manager_interface); + surface_data_manager_add_listener(desktop->surface_data_manager, + &surface_data_manager_listener, desktop); } else if (!strcmp(interface, "wl_output")) { create_output(desktop, id); } @@ -1011,6 +1477,8 @@ int main(int argc, char *argv[]) return -1; } + desktop.output_count = 0; + display_set_user_data(desktop.display, &desktop); wl_display_add_global_listener(display_get_display(desktop.display), global_handler, &desktop); diff --git a/src/compositor.c b/src/compositor.c index 417c508..bcaaf2d 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -368,6 +368,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); } + + es->compositor->shell_interface.send_output_mask(es); } static void diff --git a/src/compositor.h b/src/compositor.h index aea4f8d..ec5e5a5 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -89,6 +89,7 @@ struct weston_shell_interface { int (*move)(struct shell_surface *shsurf, struct weston_seat *ws); int (*resize)(struct shell_surface *shsurf, struct weston_seat *ws, uint32_t edges); + void (*send_output_mask)(struct weston_surface *surface); }; diff --git a/src/shell.c b/src/shell.c index e2715d6..f9fcae3 100644 --- a/src/shell.c +++ b/src/shell.c @@ -97,6 +97,8 @@ struct desktop_shell { uint32_t deathstamp; } child; + struct wl_resource *surface_data_manager; + bool locked; bool showing_input_panels; bool prepare_event_sent; @@ -152,6 +154,11 @@ struct ping_timer { uint32_t serial; }; +struct surface_data { + struct shell_surface *shsurf; + struct wl_resource resource; +}; + struct shell_surface { struct wl_resource resource; @@ -202,6 +209,7 @@ struct shell_surface { struct wl_list link; const struct weston_shell_client *client; + struct surface_data *surface_data; }; struct shell_grab { @@ -1392,6 +1400,123 @@ 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; + struct surface_data *surface_data = resource->data; + + shsurf = surface_data->shsurf; + + free(surface_data); + + 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 surface_data *surface_data; + + surface_data = malloc(sizeof *surface_data); + if (surface_data == NULL) + return -1; + + surface_data->resource.data = surface_data; + surface_data->resource.object.id = 0; + surface_data->resource.object.interface = &surface_data_interface; + surface_data->resource.destroy = surface_data_object_destroy; + surface_data->resource.object.implementation = + (void (**)(void)) &surface_data_implementation; + surface_data->shsurf = shsurf; + wl_signal_init(&surface_data->resource.destroy_signal); + + wl_client_add_resource(shell->surface_data_manager->client, + &surface_data->resource); + + shsurf->surface_data = surface_data; + + return 0; +} + +static void +send_surface_data_object(struct desktop_shell *shell, struct shell_surface *shsurf) +{ + surface_data_manager_send_surface_object(shell->surface_data_manager, + &shsurf->surface_data->resource); +} + +static bool +surface_is_window_list_candidate(struct weston_surface *surface, + struct shell_surface *out) +{ + 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: + if (!shsurf->surface_data) { + if (create_surface_data(shell, shsurf)) + return 0; + send_surface_data_object(shell, shsurf); + } + *out = *shsurf; + return true; + } +} + +static void +send_surface_data_output_mask(struct weston_surface *surface) +{ + struct shell_surface shsurf; + + if (surface_is_window_list_candidate(surface, &shsurf)) + surface_data_send_output_mask(&shsurf.surface_data->resource, + surface->output_mask); +} + +static void +send_surface_data_title(struct weston_surface *surface) +{ + struct shell_surface shsurf; + + if (surface_is_window_list_candidate(surface, &shsurf)) + surface_data_send_title(&shsurf.surface_data->resource, + shsurf.title == NULL ? + "Surface" : shsurf.title); +} + +static void shell_surface_set_title(struct wl_client *client, struct wl_resource *resource, const char *title) { @@ -1399,6 +1524,7 @@ shell_surface_set_title(struct wl_client *client, free(shsurf->title); shsurf->title = strdup(title); + send_surface_data_title(shsurf->surface); } static void @@ -1510,6 +1636,8 @@ set_surface_type(struct shell_surface *shsurf) default: break; } + + send_surface_data_title(surface); } static void @@ -1907,6 +2035,10 @@ static const struct wl_shell_surface_interface shell_surface_implementation = { static void destroy_shell_surface(struct shell_surface *shsurf) { + if (shsurf->surface_data) { + shsurf->surface_data->shsurf = NULL; + surface_data_send_gone(&shsurf->surface_data->resource); + } if (shsurf->popup.grab.pointer) wl_pointer_end_grab(shsurf->popup.grab.pointer); @@ -2291,6 +2423,20 @@ static const struct desktop_shell_interface desktop_shell_implementation = { desktop_shell_set_grab_surface }; +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) { @@ -3118,6 +3264,37 @@ 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_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) { struct desktop_shell *shell = surface->private; @@ -3723,6 +3900,7 @@ module_init(struct weston_compositor *ec) ec->shell_interface.set_transient = set_transient; ec->shell_interface.move = surface_move; ec->shell_interface.resize = surface_resize; + ec->shell_interface.send_output_mask = send_surface_data_output_mask; wl_list_init(&shell->screensaver.surfaces); wl_list_init(&shell->input_panel.surfaces); @@ -3774,6 +3952,10 @@ module_init(struct weston_compositor *ec) 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(); if (launch_desktop_shell_process(shell) != 0) return -1; -- 1.7.11.4 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel