[PATCH 3/5] shell: add managed_surface interface, request and events

Manuel Bachmann manuel.bachmann at open.eurogiciel.org
Tue Feb 18 21:18:18 PST 2014


We create a new "managed_surface" object which will track
a surface compositor-side, and receive events shell-side
to handle 3 cases :
- a toplevel surface has been created ;
- a toplevel surface has been destroyed ;
- a toplevel surface has a new title ;

Signed-off-by: Manuel Bachmann <manuel.bachmann at open.eurogiciel.org>
---
 clients/desktop-shell.c    |   69 ++++++++++++++++++++++++++++++++++++++++++++
 desktop-shell/shell.c      |   63 ++++++++++++++++++++++++++++++++++++++++
 desktop-shell/shell.h      |    8 +++++
 protocol/desktop-shell.xml |   49 +++++++++++++++++++++++++++++++
 4 files changed, 189 insertions(+)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index c341a91..5f861b2 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -139,6 +139,7 @@ struct taskbar_handler {
 	struct taskbar *taskbar;
 	cairo_surface_t *icon;
 	int focused, pressed;
+	struct managed_surface *surface;
 	char *title;
 	int state;
 	struct wl_list link;
@@ -186,6 +187,14 @@ 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)
 {
@@ -1113,6 +1122,20 @@ desktop_shell_prepare_lock_surface(void *data,
 }
 
 static void
+desktop_shell_add_managed_surface(void *data,
+				   struct desktop_shell *desktop_shell,
+				   struct managed_surface *managed_surface)
+{
+	struct desktop *desktop = data;
+	struct output *output;
+
+	wl_list_for_each(output, &desktop->outputs, link) {
+		/* will follow in next patch : add the actual handler here */
+		update_window(output->taskbar->window);
+	}
+}
+
+static void
 desktop_shell_grab_cursor(void *data,
 			  struct desktop_shell *desktop_shell,
 			  uint32_t cursor)
@@ -1162,10 +1185,56 @@ desktop_shell_grab_cursor(void *data,
 static const struct desktop_shell_listener listener = {
 	desktop_shell_configure,
 	desktop_shell_prepare_lock_surface,
+	desktop_shell_add_managed_surface,
 	desktop_shell_grab_cursor
 };
 
 static void
+managed_surface_state_changed(void *data,
+		struct managed_surface *managed_surface,
+		uint32_t state)
+{
+	struct taskbar_handler *handler = data;
+
+	if (handler->surface == managed_surface) {
+		/* set the handler state */
+		handler->state = state;
+	}
+}
+
+static void
+managed_surface_title_changed(void *data,
+		struct managed_surface *managed_surface,
+		const char *title)
+{
+	struct taskbar_handler *handler = data;
+
+	if (handler->surface == managed_surface) {
+		/* change the handler title text */
+		handler->title = strdup(title);
+		update_window(handler->taskbar->window);
+	}
+}
+
+static void
+managed_surface_removed(void *data,
+		struct managed_surface *managed_surface)
+{
+	struct taskbar_handler *handler = data;
+
+	if (handler->surface == managed_surface) {
+		/* will follow in next patch : destroy the actual handler here */
+		update_window(handler->taskbar->window);
+	}
+}
+
+static const struct managed_surface_listener managed_surface_listener = {
+	managed_surface_state_changed,
+	managed_surface_title_changed,
+	managed_surface_removed
+};
+
+static void
 background_destroy(struct background *background)
 {
 	widget_destroy(background->widget);
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index b9b4ad9..57afe5b 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2023,6 +2023,14 @@ set_title(struct shell_surface *shsurf, const char *title)
 {
 	free(shsurf->title);
 	shsurf->title = strdup(title);
+
+	if (shsurf->type == SHELL_SURFACE_TOPLEVEL) {
+		struct managed_surface *managed_surface;
+		wl_list_for_each(managed_surface, &shsurf->shell->managed_surfaces_list, link) {
+			if (managed_surface->surface == shsurf->surface)
+				managed_surface_send_title_changed (managed_surface->resource, shsurf->title);
+		}
+	}
 }
 
 static void
@@ -2991,6 +2999,16 @@ destroy_shell_surface(struct shell_surface *shsurf)
 		remove_popup_grab(shsurf);
 	}
 
+	if (shsurf->type == SHELL_SURFACE_TOPLEVEL) {
+		struct managed_surface *managed_surface;
+		wl_list_for_each(managed_surface, &shsurf->shell->managed_surfaces_list, link) {
+			if (managed_surface->surface == shsurf->surface) {
+				managed_surface_send_removed (managed_surface->resource);
+				wl_list_remove(&managed_surface->link);
+			}
+		}
+	}
+
 	if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
 	    shell_surface_is_top_fullscreen(shsurf))
 		restore_output_mode (shsurf->fullscreen_output);
@@ -3941,6 +3959,27 @@ static const struct desktop_shell_interface desktop_shell_implementation = {
 	desktop_shell_desktop_ready
 };
 
+static void
+managed_surface_set_state(struct wl_client *client,
+			struct wl_resource *resource,
+			uint32_t state)
+{
+	 /* receive desktop-shell taskbar signal to show/hide */
+	struct managed_surface *managed_surface = wl_resource_get_user_data(resource);
+	struct weston_surface *surface = managed_surface->surface;
+
+	if (state)
+		 /* compositor hides surface on its own ; will follow in next patch */
+		weston_log ("minimize stub\n");
+	else
+		 /* compositor unhides surface on its own ; will follow in next patch */
+		weston_log ("unminimize stub\n");
+}
+
+static const struct managed_surface_interface managed_surface_implementation = {
+	managed_surface_set_state
+};
+
 static enum shell_surface_type
 get_shell_surface_type(struct weston_surface *surface)
 {
@@ -4849,6 +4888,28 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf,
 		break;
 	}
 
+	if (shsurf->type == SHELL_SURFACE_TOPLEVEL) {
+		struct managed_surface *surface;
+		surface = calloc(1, sizeof *surface);
+
+		if (surface) {
+			struct wl_client *client;
+			client = wl_resource_get_client(shsurf->shell->child.desktop_shell);
+			surface->surface = shsurf->surface;
+			surface->resource = wl_resource_create(client,
+			                                       &managed_surface_interface, 1, 0);
+			wl_resource_set_implementation(surface->resource,
+					                       &managed_surface_implementation,
+					                       surface, NULL);
+
+			desktop_shell_send_add_managed_surface(shsurf->shell->child.desktop_shell,
+			                                       surface->resource);
+			wl_list_insert(shsurf->shell->managed_surfaces_list.prev, &surface->link);
+		} else {
+			weston_log("Could not create managed surface\n");
+		}
+	}
+
 	if (shsurf->type == SHELL_SURFACE_TOPLEVEL &&
 	    !shsurf->state.maximized && !shsurf->state.fullscreen)
 	{
@@ -5957,6 +6018,8 @@ module_init(struct weston_compositor *ec,
 	}
 	activate_workspace(shell, 0);
 
+	wl_list_init(&shell->managed_surfaces_list);
+
 	wl_list_init(&shell->workspaces.anim_sticky_list);
 	wl_list_init(&shell->workspaces.animation.link);
 	shell->workspaces.animation.frame = animate_workspace_change_frame;
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 104e621..ed563b9 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -93,6 +93,12 @@ struct focus_surface {
 	struct weston_transform workspace_transform;
 };
 
+struct managed_surface {
+	struct wl_resource *resource;
+	struct weston_surface *surface;
+	struct wl_list link;
+};
+
 struct workspace {
 	struct weston_layer layer;
 
@@ -198,6 +204,8 @@ struct desktop_shell {
 	enum animation_type startup_animation_type;
 	enum animation_type focus_animation_type;
 
+	struct wl_list managed_surfaces_list;
+
 	struct wl_listener output_create_listener;
 	struct wl_listener output_move_listener;
 	struct wl_list output_list;
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index 3ae5d33..2262ade 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -68,6 +68,14 @@
       </description>
     </event>
 
+    <event name="add_managed_surface">
+      <description summary="tell client to manage a new surface">
+	Tell the shell there is a new surface to manage, informing some
+	GUI components such as the taskbar.
+      </description>
+      <arg name="id" type="new_id" interface="managed_surface"/>
+    </event>
+
     <event name="grab_cursor">
       <description summary="tell client what cursor to show during a grab">
 	This event will be sent immediately before a fake enter event on the
@@ -98,6 +106,47 @@
     </enum>
   </interface>
 
+  <interface name="managed_surface" version="1">
+    <description summary="interface for handling managed surfaces">
+      Only one client can bind this interface at a time.
+    </description>
+
+     <request name="set_state">
+      <description summary="set managed surface state">
+	The client can ask the state of the shell surface linked to a managed
+	surface to be changed. It currently supports minimization.
+      </description>
+       <arg name="state" type="uint"/>
+     </request>
+
+     <event name="state_changed">
+      <description summary="tell client managed surface state was changed">
+	This event will be sent immediately after the shell suface linked to a
+	managed surface had its state changed. It currently supports minimization.
+      </description>
+       <arg name="state" type="uint"/>
+     </event>
+
+     <event name="title_changed">
+      <description summary="tell client managed surface title was changed">
+	This event will be sent immediately after the title of the shell surface
+	linked to a managed surface has been changed.
+      </description>
+       <arg name="title" type="string"/>
+     </event>
+
+     <event name="removed">
+      <description summary="remove a managed surface">
+	This event will be sent when a managed surface is removed.
+      </description>
+     </event>
+
+     <enum name="state">
+       <entry name="normal" value="0"/>
+       <entry name="minimized" value="1"/>
+     </enum>
+  </interface>
+
   <interface name="screensaver" version="1">
     <description summary="interface for implementing screensavers">
       Only one client can bind this interface at a time.
-- 
1.7.10.4



More information about the wayland-devel mailing list