[PATCH weston] xwayland: Forward global position to X

Kristian Høgsberg hoegsberg at gmail.com
Fri Jun 14 12:42:39 PDT 2013


On Wed, Jun 12, 2013 at 03:43:21PM -0300, Tiago Vignatti wrote:
> 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.

Thanks Tiago, that patch looks good.  I applied it with one change: I
renamed position_signal to transform_signal and emit it from the
bottom of weston_surface_update_transform().  This way, all weston
surfaces will emit this signal whenever they update their transform.

> 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.

Ok.  I see the problem - you can also try to put xev below a wayland
surface and then alt-tab to xev.  xev gets the correct enter event,
but it then gets a spurious leave event.  It doesn't seem like it's
something that this patch introduces though.

Kristian

>     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
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list