[PATCH 1/2 weston] Install infrastructure for surface_data objects.
Scott Moreau
oreaus at gmail.com
Tue Oct 2 23:20:16 PDT 2012
We needed a way to send surface data to the shell client. This patch introduces
a new surface_data_manager interface that allows the compositor to send surface
data to the shell client, using the new surface_data object interface. This
allows the shell client to receive information about surfaces to build a window
list, for example.
---
clients/desktop-shell.c | 63 +++++++++++++++---
protocol/desktop-shell.xml | 51 ++++++++++++++
src/compositor.c | 2 +
src/compositor.h | 1 +
src/shell.c | 163 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 272 insertions(+), 8 deletions(-)
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 588dc1c..5c629cb 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -57,9 +57,17 @@ struct desktop {
struct widget *grab_widget;
enum cursor_type grab_cursor;
+
+ struct surface_data_manager *surface_data_manager;
};
struct surface {
+ 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,
@@ -67,7 +75,7 @@ struct surface {
};
struct panel {
- struct surface base;
+ struct resize base;
struct window *window;
struct widget *widget;
struct wl_list launcher_list;
@@ -75,7 +83,7 @@ struct panel {
};
struct background {
- struct surface base;
+ struct resize base;
struct window *window;
struct widget *widget;
};
@@ -417,7 +425,7 @@ panel_resize_handler(struct widget *widget,
struct panel_launcher *launcher;
struct panel *panel = data;
int x, y, w, h;
-
+
x = 10;
y = 16;
wl_list_for_each(launcher, &panel->launcher_list, link) {
@@ -441,7 +449,7 @@ 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);
@@ -466,7 +474,7 @@ 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_add_clock(panel);
return panel;
@@ -485,8 +493,7 @@ load_icon_or_fallback(const char *icon)
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);
@@ -810,7 +817,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 +892,38 @@ static const struct desktop_shell_listener listener = {
desktop_shell_grab_cursor
};
+static void
+surface_data_receive_info(void *data,
+ struct surface_data *surface_data,
+ uint32_t output_mask,
+ const char *title)
+{
+}
+
+static void
+surface_data_destroy_handler(void *data, struct surface_data *surface_data)
+{
+ surface_data_destroy_request(surface_data);
+}
+
+static const struct surface_data_listener surface_data_listener = {
+ surface_data_receive_info,
+ 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)
{
@@ -957,6 +996,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);
}
@@ -1041,6 +1086,8 @@ int main(int argc, char *argv[])
signal(SIGCHLD, sigchild_handler);
+ surface_data_manager_get_surface_info(desktop.surface_data_manager);
+
display_run(desktop.display);
return 0;
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index 2b6afbd..7030786 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -82,6 +82,57 @@
</enum>
</interface>
+ <interface name="surface_data" version="1">
+ <description summary="the surface data offer object">
+ The wl_shell client can use this interface to receive surface information
+ or make requests for this surface.
+ </description>
+ <event name="info">
+ <description summary="surface information">
+ Surface information sent to a wl_shell client. This information is
+ intended to give the wl_shell client additional information about the
+ surface.
+ </description>
+ <arg name="output_mask" type="uint"/>
+ <arg name="title" type="string"/>
+ </event>
+ <request name="destroy_request" type="destructor">
+ <description summary="destroy surface request">
+ The wl_shell client must send this request in response to a gone event
+ so the compositor can destroy the object properly.
+ </description>
+ </request>
+ <event name="gone" type="destructor">
+ <description summary="destroy surface notification">
+ The compositor should send this event to notify the wl_shell client that
+ a surface has been destroyed. The client must respond with a destroy
+ request.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="surface_data_manager" version="1">
+ <description summary="send surface object to shell client">
+ The compositor can offer surface data to a wl_shell client. The client can
+ use this interface as a way to receive special surface_data objects.
+ </description>
+ <request name="get_surface_info">
+ <description summary="request surface list">
+ The wl_shell client can use this request to ask the window manager to
+ send surface_info events for all surfaces. The window manager should
+ send only normal surfaces that can be part of a common window list.
+ </description>
+ </request>
+ <event name="surface_object">
+ <description summary="surface object">
+ Surface object sent to a wl_shell client. This object is intended to
+ allow the wl_shell to initiate a surface_data object interface. It
+ should be sent once, when a wl_shell_surface is created.
+ </description>
+ <arg name="id" type="new_id" interface="surface_data"/>
+ </event>
+ </interface>
+
<interface name="screensaver" version="1">
<description summary="interface for implementing screensavers">
Only one client can bind this interface at a time.
diff --git a/src/compositor.c b/src/compositor.c
index 417c508..7afdbdb 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_info(es);
}
static void
diff --git a/src/compositor.h b/src/compositor.h
index aea4f8d..4304d21 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_info)(struct weston_surface *surface);
};
diff --git a/src/shell.c b/src/shell.c
index e2715d6..2d86265 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,101 @@ 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_object(struct desktop_shell *shell, struct shell_surface *shsurf)
+{
+ surface_data_manager_send_surface_object(shell->surface_data_manager,
+ &shsurf->surface_data->resource);
+}
+
+static void
+send_surface_info(struct weston_surface *surface)
+{
+ struct desktop_shell *shell;
+ struct shell_surface *shsurf;
+
+ shsurf = get_shell_surface(surface);
+ if (!shsurf)
+ return;
+
+ shell = shsurf->shell;
+
+ switch (shsurf->type) {
+ default:
+ case SHELL_SURFACE_TRANSIENT:
+ case SHELL_SURFACE_POPUP:
+ case SHELL_SURFACE_NONE:
+ return;
+ case SHELL_SURFACE_FULLSCREEN:
+ case SHELL_SURFACE_MAXIMIZED:
+ case SHELL_SURFACE_TOPLEVEL:
+ if (!shsurf->surface_data) {
+ if (create_surface_data(shell, shsurf))
+ return;
+ send_surface_object(shell, shsurf);
+ }
+ surface_data_send_info(&shsurf->surface_data->resource,
+ shsurf->surface->output_mask,
+ shsurf->title == NULL ?
+ "Surface" : shsurf->title);
+ return;
+ }
+}
+
+static void
shell_surface_set_title(struct wl_client *client,
struct wl_resource *resource, const char *title)
{
@@ -1399,6 +1502,7 @@ shell_surface_set_title(struct wl_client *client,
free(shsurf->title);
shsurf->title = strdup(title);
+ send_surface_info(shsurf->surface);
}
static void
@@ -1907,6 +2011,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 +2399,26 @@ static const struct desktop_shell_interface desktop_shell_implementation = {
desktop_shell_set_grab_surface
};
+static void
+surface_data_surface_info_requested(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct weston_surface *surface;
+ struct desktop_shell *shell;
+ struct workspace *ws;
+
+ shell = resource->data;
+ ws = get_current_workspace(shell);
+
+ wl_list_for_each(surface, &ws->layer.surface_list, layer_link)
+ send_surface_info(surface);
+}
+
+static const struct surface_data_manager_interface
+ surface_data_manager_implementation = {
+ surface_data_surface_info_requested
+};
+
static enum shell_surface_type
get_shell_surface_type(struct weston_surface *surface)
{
@@ -2915,6 +3043,8 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
default:
ws = get_current_workspace(shell);
wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
+ weston_surface_update_transform(surface);
+ send_surface_info(surface);
break;
}
@@ -3118,6 +3248,34 @@ bind_desktop_shell(struct wl_client *client,
}
static void
+unbind_surface_data_manager(struct wl_resource *resource)
+{
+ 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,
+ &surface_data_manager_implementation,
+ id, shell);
+
+ if (client == shell->child.client) {
+ resource->destroy = unbind_surface_data_manager;
+ shell->surface_data_manager = resource;
+ 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 +3881,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_info = send_surface_info;
wl_list_init(&shell->screensaver.surfaces);
wl_list_init(&shell->input_panel.surfaces);
@@ -3774,6 +3933,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
More information about the wayland-devel
mailing list