From f05d18f3ee8b7d25017bf3ca58561ec5ababbd63 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 11 Dec 2015 20:57:05 +0200 Subject: [PATCH] xwm: let the shells decide the position of X windows The xwm used to automatically send to Xwayland the position of X windows when that changed, using the x,y of the primary view of the surface. This works fine for the desktop shell but less so for others. This patch adds a 'send_position' vfunc to the weston_shell_client that the shell will call when it wants to let Xwayland know what the position of a window is. The logic used by the desktop-shell for that is exactly the same the xwm used to have. Reviewed-by: Derek Foreman Reviewed-by: David Fort --- desktop-shell/shell.c | 40 ++++++++++++++++------ desktop-shell/shell.h | 1 + src/compositor.h | 4 +-- xwayland/window-manager.c | 72 +++++++++++++++++---------------------- xwayland/xwayland.h | 1 - 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 780902d0..85664c63 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1813,7 +1813,8 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height) } static const struct weston_shell_client shell_client = { - send_configure + send_configure, + NULL }; static void @@ -3704,12 +3705,6 @@ create_shell_surface(void *shell, struct weston_surface *surface, return create_common_surface(NULL, shell, surface, client); } -static struct weston_view * -get_primary_view(void *shell, struct shell_surface *shsurf) -{ - return shsurf->view; -} - static void shell_get_shell_surface(struct wl_client *client, struct wl_resource *resource, @@ -3995,7 +3990,8 @@ xdg_send_configure(struct weston_surface *surface, } static const struct weston_shell_client xdg_client = { - xdg_send_configure + xdg_send_configure, + NULL }; static void @@ -4119,7 +4115,8 @@ xdg_popup_send_configure(struct weston_surface *surface, } static const struct weston_shell_client xdg_popup_client = { - xdg_popup_send_configure + xdg_popup_send_configure, + NULL }; static struct shell_surface * @@ -5411,6 +5408,27 @@ wake_handler(struct wl_listener *listener, void *data) unlock(shell); } +static void +transform_handler(struct wl_listener *listener, void *data) +{ + struct weston_surface *surface = data; + struct shell_surface *shsurf = get_shell_surface(surface); + struct weston_view *view;; + int x, y; + + if (!shsurf || !shsurf->client->send_position) + return; + + view = shsurf->view; + if (!view || !weston_view_is_mapped(view)) + return; + + x = view->geometry.x; + y = view->geometry.y; + + shsurf->client->send_position(surface, x, y); +} + static void center_on_output(struct weston_view *view, struct weston_output *output) { @@ -6379,6 +6397,7 @@ shell_destroy(struct wl_listener *listener, void *data) wl_list_remove(&shell->idle_listener.link); wl_list_remove(&shell->wake_listener.link); + wl_list_remove(&shell->transform_listener.link); text_backend_destroy(shell->text_backend); input_panel_destroy(shell); @@ -6520,10 +6539,11 @@ module_init(struct weston_compositor *ec, wl_signal_add(&ec->idle_signal, &shell->idle_listener); shell->wake_listener.notify = wake_handler; wl_signal_add(&ec->wake_signal, &shell->wake_listener); + shell->transform_listener.notify = transform_handler; + wl_signal_add(&ec->transform_signal, &shell->transform_listener); ec->shell_interface.shell = shell; ec->shell_interface.create_shell_surface = create_shell_surface; - ec->shell_interface.get_primary_view = get_primary_view; ec->shell_interface.set_toplevel = set_toplevel; ec->shell_interface.set_transient = set_transient; ec->shell_interface.set_fullscreen = shell_interface_set_fullscreen; diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index 2ef23f49..c55a2255 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -121,6 +121,7 @@ struct desktop_shell { struct wl_listener idle_listener; struct wl_listener wake_listener; + struct wl_listener transform_listener; struct wl_listener destroy_listener; struct wl_listener show_input_panel_listener; struct wl_listener hide_input_panel_listener; diff --git a/src/compositor.h b/src/compositor.h index 8a5aa91b..a427088e 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -86,6 +86,7 @@ struct weston_mode { struct weston_shell_client { void (*send_configure)(struct weston_surface *surface, int32_t width, int32_t height); + void (*send_position)(struct weston_surface *surface, int32_t x, int32_t y); }; struct weston_shell_interface { @@ -94,9 +95,6 @@ struct weston_shell_interface { struct shell_surface *(*create_shell_surface)(void *shell, struct weston_surface *surface, const struct weston_shell_client *client); - struct weston_view *(*get_primary_view)(void *shell, - struct shell_surface *shsurf); - void (*set_toplevel)(struct shell_surface *shsurf); void (*set_transient)(struct shell_surface *shsurf, diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index dd873df7..f6f92bd5 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -145,6 +145,7 @@ struct weston_wm_window { xcb_atom_t type; int width, height; int x, y; + bool pos_dirty; int saved_width, saved_height; int decorate; int override_redirect; @@ -692,6 +693,8 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve window->x = configure_notify->x; window->y = configure_notify->y; + window->pos_dirty = false; + if (window->override_redirect) { window->width = configure_notify->width; window->height = configure_notify->height; @@ -808,41 +811,6 @@ weston_wm_window_activate(struct wl_listener *listener, void *data) } -static void -weston_wm_window_transform(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, transform_listener); - struct weston_view *view; - struct weston_shell_interface *shell_interface = - &wm->server->compositor->shell_interface; - uint32_t mask, values[2]; - - if (!window || !wm || !window->shsurf) - return; - - if (!shell_interface->get_primary_view) - return; - - view = shell_interface->get_primary_view(shell_interface->shell, - window->shsurf); - - if (!view || !weston_view_is_mapped(view)) - return; - - if (window->x != view->geometry.x || - window->y != view->geometry.y) { - values[0] = view->geometry.x; - values[1] = view->geometry.y; - mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; - - xcb_configure_window(wm->conn, window->frame_id, mask, values); - xcb_flush(wm->conn); - } -} - #define ICCCM_WITHDRAWN_STATE 0 #define ICCCM_NORMAL_STATE 1 #define ICCCM_ICONIC_STATE 3 @@ -1226,6 +1194,7 @@ weston_wm_window_create(struct weston_wm *wm, window->height = height; window->x = x; window->y = y; + window->pos_dirty = false; geometry_reply = xcb_get_geometry_reply(wm->conn, geometry_cookie, NULL); /* technically we should use XRender and check the visual format's @@ -2316,9 +2285,6 @@ weston_wm_create(struct weston_xserver *wxs, int fd) wm->activate_listener.notify = weston_wm_window_activate; wl_signal_add(&wxs->compositor->activate_signal, &wm->activate_listener); - wm->transform_listener.notify = weston_wm_window_transform; - wl_signal_add(&wxs->compositor->transform_signal, - &wm->transform_listener); wm->kill_listener.notify = weston_wm_kill_client; wl_signal_add(&wxs->compositor->kill_signal, &wm->kill_listener); @@ -2347,7 +2313,6 @@ weston_wm_destroy(struct weston_wm *wm) wl_list_remove(&wm->selection_listener.link); wl_list_remove(&wm->activate_listener.link); wl_list_remove(&wm->kill_listener.link); - wl_list_remove(&wm->transform_listener.link); wl_list_remove(&wm->create_surface_listener.link); free(wm); @@ -2438,8 +2403,35 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height) weston_wm_window_configure, window); } +static void +send_position(struct weston_surface *surface, int32_t x, int32_t y) +{ + struct weston_wm_window *window = get_wm_window(surface); + struct weston_wm *wm; + uint32_t mask, values[2]; + + if (!window || !window->wm) + return; + + wm = window->wm; + /* We use pos_dirty to tell whether a configure message is in flight. + * This is needed in case we send two configure events in a very + * short time, since window->x/y is set in after a roundtrip, hence + * we cannot just check if the current x and y are different. */ + if (window->x != x || window->y != y || window->pos_dirty) { + window->pos_dirty = true; + values[0] = x; + values[1] = y; + mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; + + xcb_configure_window(wm->conn, window->frame_id, mask, values); + xcb_flush(wm->conn); + } +} + static const struct weston_shell_client shell_client = { - send_configure + send_configure, + send_position }; static int diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h index bace0794..b1fd904e 100644 --- a/xwayland/xwayland.h +++ b/xwayland/xwayland.h @@ -70,7 +70,6 @@ struct weston_wm { xcb_colormap_t colormap; struct wl_listener create_surface_listener; struct wl_listener activate_listener; - struct wl_listener transform_listener; struct wl_listener kill_listener; struct wl_list unpaired_window_list;