[PATCH weston] xwayland: Forward global position to X

Tiago Vignatti tiago.vignatti at intel.com
Wed Jun 12 11:43:21 PDT 2013


xeyes works as expected now. subwindows are popped also as expected. This
patch should fix the following:

https://bugs.freedesktop.org/show_bug.cgi?id=59983

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---

Hey guys,

This fix the problem mentioned above but exposes something that was already
buggy before: XWM (and probably all X clients) is getting wrong EnterNotify,
setting wrong cursor. This happens sometimes only.

To check the problem, I've added a printf in weston_wm_handle_enter and set
WAYLAND_DEBUG=1. You will see that the coordinates wl_pointer_enter comes to 
XWayland vary from what it sends along to the X clients. It's not all the
time as I said, so probably there's a race between the two protocols. Another
way to check is clobber one window with another, leaving the cursor right on
the decoration border where it should change the icon if you alternate the
windows with ctrl+tab: 

http://i.troll.ws/4c2cbb1b.png

Grab cursor not being set all the times is another way to see the bug.

I hope this help someone else find the problem. I'm not continuing the
investigations here in principle.

    Tiago


 src/compositor.c              |    1 +
 src/compositor.h              |    5 +++
 src/shell.c                   |   30 ++++++++++++++++-
 src/xwayland/window-manager.c |   73 ++++++++++++++++++++++++++---------------
 src/xwayland/xwayland.h       |    2 +-
 5 files changed, 83 insertions(+), 28 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 099600d..f019441 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2777,6 +2777,7 @@ weston_compositor_init(struct weston_compositor *ec,
 	ec->wl_display = display;
 	wl_signal_init(&ec->destroy_signal);
 	wl_signal_init(&ec->activate_signal);
+	wl_signal_init(&ec->position_signal);
 	wl_signal_init(&ec->kill_signal);
 	wl_signal_init(&ec->idle_signal);
 	wl_signal_init(&ec->wake_signal);
diff --git a/src/compositor.h b/src/compositor.h
index 22700b7..bcca468 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -94,6 +94,8 @@ struct weston_shell_interface {
 			       uint32_t method,
 			       uint32_t framerate,
 			       struct weston_output *output);
+	void (*set_xwayland)(struct shell_surface *shsurf,
+			       int x, int y, uint32_t flags);
 	int (*move)(struct shell_surface *shsurf, struct weston_seat *ws);
 	int (*resize)(struct shell_surface *shsurf,
 		      struct weston_seat *ws, uint32_t edges);
@@ -502,7 +504,10 @@ struct weston_compositor {
 	struct weston_shell_interface shell_interface;
 	struct weston_config *config;
 
+	/* xwayland */
 	struct wl_signal activate_signal;
+	struct wl_signal position_signal;
+
 	struct wl_signal kill_signal;
 	struct wl_signal idle_signal;
 	struct wl_signal wake_signal;
diff --git a/src/shell.c b/src/shell.c
index 3d10eef..d9038b2 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -171,7 +171,8 @@ enum shell_surface_type {
 	SHELL_SURFACE_TRANSIENT,
 	SHELL_SURFACE_FULLSCREEN,
 	SHELL_SURFACE_MAXIMIZED,
-	SHELL_SURFACE_POPUP
+	SHELL_SURFACE_POPUP,
+	SHELL_SURFACE_XWAYLAND
 };
 
 struct ping_timer {
@@ -340,9 +341,13 @@ shell_grab_start(struct shell_grab *grab,
 static void
 shell_grab_end(struct shell_grab *grab)
 {
+	struct weston_compositor *compositor =
+		grab->shsurf->surface->compositor;
+
 	if (grab->shsurf)
 		wl_list_remove(&grab->shsurf_destroy_listener.link);
 
+	wl_signal_emit(&compositor->position_signal, grab->shsurf->surface);
 	weston_pointer_end_grab(grab->pointer);
 }
 
@@ -1581,6 +1586,7 @@ reset_shell_surface_type(struct shell_surface *surface)
 	case SHELL_SURFACE_TOPLEVEL:
 	case SHELL_SURFACE_TRANSIENT:
 	case SHELL_SURFACE_POPUP:
+	case SHELL_SURFACE_XWAYLAND:
 		break;
 	}
 
@@ -1622,6 +1628,11 @@ set_surface_type(struct shell_surface *shsurf)
 		}
 		break;
 
+	case SHELL_SURFACE_XWAYLAND:
+		weston_surface_set_position(surface, shsurf->transient.x,
+					    shsurf->transient.y);
+		break;
+
 	default:
 		break;
 	}
@@ -1925,6 +1936,16 @@ shell_surface_set_fullscreen(struct wl_client *client,
 	set_fullscreen(shsurf, method, framerate, output);
 }
 
+static void
+set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
+{
+	/* XXX: using the same fields for transient type */
+	shsurf->transient.x = x;
+	shsurf->transient.y = y;
+	shsurf->transient.flags = flags;
+	shsurf->next_type = SHELL_SURFACE_XWAYLAND;
+}
+
 static const struct weston_pointer_grab_interface popup_grab_interface;
 
 static void
@@ -3399,6 +3420,7 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
 	case SHELL_SURFACE_FULLSCREEN:
 	case SHELL_SURFACE_NONE:
 		break;
+	case SHELL_SURFACE_XWAYLAND:
 	default:
 		ws = get_current_workspace(shell);
 		wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
@@ -3412,6 +3434,8 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
 	}
 
 	switch (surface_type) {
+	/* XXX: xwayland's using the same fields for transient type */
+	case SHELL_SURFACE_XWAYLAND:
 	case SHELL_SURFACE_TRANSIENT:
 		if (shsurf->transient.flags ==
 				WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
@@ -3490,6 +3514,7 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32
 {
 	struct shell_surface *shsurf = get_shell_surface(es);
 	struct desktop_shell *shell = shsurf->shell;
+	struct weston_compositor *compositor = shsurf->surface->compositor;
 
 	int type_changed = 0;
 
@@ -3521,6 +3546,8 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32
 			  es->geometry.y + to_y - from_y,
 			  width, height);
 	}
+
+	wl_signal_emit(&compositor->position_signal, shsurf->surface);
 }
 
 static void launch_desktop_shell_process(void *data);
@@ -4434,6 +4461,7 @@ module_init(struct weston_compositor *ec,
 	ec->shell_interface.set_toplevel = set_toplevel;
 	ec->shell_interface.set_transient = set_transient;
 	ec->shell_interface.set_fullscreen = set_fullscreen;
+	ec->shell_interface.set_xwayland = set_xwayland;
 	ec->shell_interface.move = surface_move;
 	ec->shell_interface.resize = surface_resize;
 
diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 366f2e0..466f049 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -584,12 +584,49 @@ weston_wm_window_activate(struct wl_listener *listener, void *data)
 	if (wm->focus_window)
 		weston_wm_window_schedule_repaint(wm->focus_window);
 	wm->focus_window = window;
-	if (window)
-		wm->focus_latest = window;
 	if (wm->focus_window)
 		weston_wm_window_schedule_repaint(wm->focus_window);
 }
 
+static void
+weston_wm_window_position(struct wl_listener *listener, void *data)
+{
+	struct weston_surface *surface = data;
+	struct weston_wm_window *window = get_wm_window(surface);
+	struct weston_wm *wm =
+		container_of(listener, struct weston_wm, position_listener);
+	struct weston_output *output = surface->output;
+	uint32_t mask, values[2];
+	float sxf, syf;
+	int sx, sy;
+	static int old_sx = -1, old_sy = -1;
+
+	if (!window || !wm)
+		return;
+
+	if (!weston_surface_is_mapped(surface))
+		return;
+
+	weston_surface_to_global_float(surface, output->x, output->y,
+				       &sxf, &syf);
+
+	sx = (int) sxf;
+	sy = (int) syf;
+
+	if (old_sx == sx && old_sy == sy)
+		return;
+
+	values[0] = sx;
+	values[1] = sy;
+	mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
+
+	xcb_configure_window(wm->conn, window->frame_id, mask, values);
+	xcb_flush(wm->conn);
+
+	old_sx = sx;
+	old_sy = sy;
+}
+
 static int
 our_resource(struct weston_wm *wm, uint32_t id)
 {
@@ -1675,6 +1712,9 @@ weston_wm_create(struct weston_xserver *wxs)
 	wm->activate_listener.notify = weston_wm_window_activate;
 	wl_signal_add(&wxs->compositor->activate_signal,
 		      &wm->activate_listener);
+	wm->position_listener.notify = weston_wm_window_position;
+	wl_signal_add(&wxs->compositor->position_signal,
+		      &wm->position_listener);
 	wm->kill_listener.notify = weston_wm_kill_client;
 	wl_signal_add(&wxs->compositor->kill_signal,
 		      &wm->kill_listener);
@@ -1799,9 +1839,7 @@ xserver_map_shell_surface(struct weston_wm *wm,
 {
 	struct weston_shell_interface *shell_interface =
 		&wm->server->compositor->shell_interface;
-	struct weston_wm_window *parent;
 	struct theme *t = window->wm->theme;
-	int parent_id, x = 0, y = 0;
 
 	if (!shell_interface->create_shell_surface)
 		return;
@@ -1819,31 +1857,14 @@ xserver_map_shell_surface(struct weston_wm *wm,
 						0, NULL);
 		return;
 	} else if (!window->override_redirect) {
-		/* ICCCM 4.1.1 */
 		shell_interface->set_toplevel(window->shsurf);
 		return;
+	} else {
+		shell_interface->set_xwayland(window->shsurf,
+					      window->x + t->margin,
+					      window->y + t->margin,
+					      WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
 	}
-
-	/* not all non-toplevel has transient_for set. So we need this
-	 * workaround to guess a parent that will determine the relative
-	 * position of the transient surface */
-	if (!window->transient_for)
-		parent_id = wm->focus_latest->id;
-	else
-		parent_id = window->transient_for->id;
-
-	parent = hash_table_lookup(wm->window_hash, parent_id);
-
-	/* non-decorated and non-toplevel windows, e.g. sub-menus */
-	if (!parent->decorate && parent->override_redirect) {
-		x = parent->x + t->margin;
-		y = parent->y + t->margin;
-	}
-
-	shell_interface->set_transient(window->shsurf, parent->surface,
-				       window->x + t->margin - x,
-				       window->y + t->margin - y,
-				       WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
 }
 
 static void
diff --git a/src/xwayland/xwayland.h b/src/xwayland/xwayland.h
index 9151cce..1b957ca 100644
--- a/src/xwayland/xwayland.h
+++ b/src/xwayland/xwayland.h
@@ -53,7 +53,6 @@ struct weston_wm {
 	struct weston_xserver *server;
 	xcb_window_t wm_window;
 	struct weston_wm_window *focus_window;
-	struct weston_wm_window *focus_latest;
 	struct theme *theme;
 	xcb_cursor_t *cursors;
 	int last_cursor;
@@ -61,6 +60,7 @@ struct weston_wm {
 	xcb_visualid_t visual_id;
 	xcb_colormap_t colormap;
 	struct wl_listener activate_listener;
+	struct wl_listener position_listener;
 	struct wl_listener kill_listener;
 
 	xcb_window_t selection_window;
-- 
1.7.9.5



More information about the wayland-devel mailing list