[PATCH weston 8/8] compositor: hook xserver transient windows with shell_interface

Tiago Vignatti tiago.vignatti at intel.com
Mon May 7 05:23:14 PDT 2012


In special, I cared about tooltip type of windows.

Transient surfaces are, by the protocol, positioned surface relative to the
upper left corner of the parent surface. So for tooltips, I needed to subtract
the parent surface geometry in order to get the device's position, via a
hacked interface. I don't think that's the perfect solution but it works well.

Now tooltip windows created via xwayland on Firefox works nicely. Also, when
typing into the URL field in Firefox, an utility window shows up trying to
figure out the link you're looking for; that window was getting the keyboard
focus and messing with the user typing experience. Now, I marked by default
all non-toplevel windows as inactive, so typing there behaves as expected.

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
 src/compositor.h       |    6 ++++++
 src/shell.c            |   27 +++++++++++++++++++++------
 src/xserver-launcher.c |   42 +++++++++++++++++++++++++++++++++---------
 3 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/src/compositor.h b/src/compositor.h
index f258066..01f6e66 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -63,6 +63,9 @@ struct weston_shell_interface {
 				     struct weston_surface *surface,
 				     struct shell_surface **ret);
 	void (*set_toplevel)(struct shell_surface *shsurf);
+	void (*set_transient)(struct shell_surface *shsurf,
+			struct shell_surface *pshsurf, int x, int y,
+			uint32_t flags);
 };
 
 struct weston_border {
@@ -617,4 +620,7 @@ backend_init(struct wl_display *display, int argc, char *argv[]);
 int
 weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode);
 
+struct weston_surface *
+shell_surface_get_surface(struct shell_surface *shsurf);
+
 #endif
diff --git a/src/shell.c b/src/shell.c
index b30e2d9..cc9c12b 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -825,19 +825,27 @@ shell_surface_set_toplevel(struct wl_client *client,
 }
 
 static void
+set_transient(struct shell_surface *shsurf, struct shell_surface *pshsurf,
+	      int x, int y, uint32_t flags)
+{
+	/* assign to parents output */
+	shsurf->parent = pshsurf;
+	shsurf->transient.x = x;
+	shsurf->transient.y = y;
+	shsurf->transient.flags = flags;
+	shsurf->next_type = SHELL_SURFACE_TRANSIENT;
+}
+
+static void
 shell_surface_set_transient(struct wl_client *client,
 			    struct wl_resource *resource,
 			    struct wl_resource *parent_resource,
 			    int x, int y, uint32_t flags)
 {
 	struct shell_surface *shsurf = resource->data;
+	struct shell_surface *pshsurf = parent_resource->data;
 
-	/* assign to parents output */
-	shsurf->parent = parent_resource->data;
-	shsurf->transient.x = x;
-	shsurf->transient.y = y;
-	shsurf->transient.flags = flags;
-	shsurf->next_type = SHELL_SURFACE_TRANSIENT;
+	set_transient(shsurf, pshsurf, x, y, flags);
 }
 
 static struct desktop_shell *
@@ -1238,6 +1246,12 @@ get_surface(struct shell_surface *shsurf, struct weston_surface **surface)
 	*surface = shsurf->surface;
 }
 
+WL_EXPORT struct weston_surface *
+shell_surface_get_surface(struct shell_surface *shsurf)
+{
+	return shsurf->surface;
+}
+
 static void
 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
 
@@ -2602,6 +2616,7 @@ shell_init(struct weston_compositor *ec)
 	ec->shell_interface.get_surface = get_surface;
 	ec->shell_interface.create_shell_surface = create_shell_surface;
 	ec->shell_interface.set_toplevel = set_toplevel;
+	ec->shell_interface.set_transient = set_transient;
 
 	wl_list_init(&shell->backgrounds);
 	wl_list_init(&shell->panels);
diff --git a/src/xserver-launcher.c b/src/xserver-launcher.c
index 95c6546..9634091 100644
--- a/src/xserver-launcher.c
+++ b/src/xserver-launcher.c
@@ -1515,6 +1515,38 @@ read_window_properties(struct weston_wm *wm, struct weston_wm_window *window)
 }
 
 static void
+xserver_set_shell(struct weston_wm *wm, struct weston_wm_window *window)
+{
+	struct weston_shell_interface *shell_interface =
+		&wm->server->compositor->shell_interface;
+	struct weston_wm_window *parent;
+	struct wl_input_device *device;
+	struct weston_surface *surface;
+	const int offset_y = 20;
+
+	if (!shell_interface->create_shell_surface)
+		return;
+
+	shell_interface->create_shell_surface(shell_interface->shell,
+					window->surface, &window->shsurf);
+
+	if (!window->transient_for)
+		shell_interface->set_toplevel(window->shsurf);
+	else {
+		parent = hash_table_lookup(wm->window_hash,
+				window->transient_for->id);
+		device = wm->server->compositor->input_device;
+		shell_interface->get_surface(parent->shsurf, &surface);
+		shell_interface->set_transient(window->shsurf,
+				parent->shsurf,
+				device->x - surface->geometry.x,
+				device->y - surface->geometry.y + offset_y,
+				WL_SHELL_SURFACE_TRANSIENT_METHOD_INACTIVE);
+
+	}
+}
+
+static void
 xserver_set_window_id(struct wl_client *client, struct wl_resource *resource,
 		      struct wl_resource *surface_resource, uint32_t id)
 {
@@ -1522,8 +1554,6 @@ xserver_set_window_id(struct wl_client *client, struct wl_resource *resource,
 	struct weston_wm *wm = wxs->wm;
 	struct wl_surface *surface = surface_resource->data;
 	struct weston_wm_window *window;
-	struct weston_shell_interface *shell_interface =
-		&wm->server->compositor->shell_interface;
 
 	if (client != wxs->client)
 		return;
@@ -1543,13 +1573,7 @@ xserver_set_window_id(struct wl_client *client, struct wl_resource *resource,
 	wl_signal_add(&surface->resource.destroy_signal,
 		      &window->surface_destroy_listener);
 
-	if (shell_interface->create_shell_surface) {
-		shell_interface->create_shell_surface(shell_interface->shell,
-						      window->surface,
-						      &window->shsurf);
-
-		shell_interface->set_toplevel(window->shsurf);
-	}
+	xserver_set_shell(wm, window);
 }
 
 static const struct xserver_interface xserver_implementation = {
-- 
1.7.9.5



More information about the wayland-devel mailing list