diff --git a/libweston/desktop/xwayland.c b/libweston/desktop/xwayland.c index 649836132..628f93050 100644 --- a/libweston/desktop/xwayland.c +++ b/libweston/desktop/xwayland.c @@ -72,13 +72,14 @@ static void weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surface *surface, enum weston_desktop_xwayland_surface_state state, struct weston_desktop_surface *parent, - int32_t x, int32_t y) + const struct weston_coord_surface *offset) { struct weston_surface *wsurface; bool to_add = (parent == NULL && state != XWAYLAND); assert(state != NONE); assert(!parent || state == TRANSIENT); + assert(!parent || offset); if (to_add && surface->added) { surface->state = state; @@ -140,9 +141,15 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf } } - if (parent != NULL) + if (parent != NULL) { + struct weston_surface *psurface; + + psurface = weston_desktop_surface_get_surface(parent); + assert(offset->coordinate_space_id == psurface); weston_desktop_surface_set_relative_to(surface->surface, parent, - x, y, false); + offset->c.x, + offset->c.y, false); + } } static void @@ -328,7 +335,7 @@ set_toplevel(struct weston_desktop_xwayland_surface *surface) enum weston_desktop_xwayland_surface_state prev_state = surface->state; weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL, - 0, 0); + NULL); if (prev_state == FULLSCREEN) { weston_desktop_api_fullscreen_requested(surface->desktop, @@ -339,11 +346,12 @@ set_toplevel(struct weston_desktop_xwayland_surface *surface) static void set_toplevel_with_position(struct weston_desktop_xwayland_surface *surface, - int32_t x, int32_t y) + struct weston_coord_global pos) { set_toplevel(surface); weston_desktop_api_set_xwayland_position(surface->desktop, - surface->surface, x, y); + surface->surface, + pos.c.x, pos.c.y); } static void @@ -361,7 +369,8 @@ set_parent(struct weston_desktop_xwayland_surface *surface, static void set_transient(struct weston_desktop_xwayland_surface *surface, - struct weston_surface *wparent, int x, int y) + struct weston_surface *wparent, + struct weston_coord_surface offset) { struct weston_desktop_surface *parent; @@ -370,7 +379,7 @@ set_transient(struct weston_desktop_xwayland_surface *surface, parent = weston_surface_get_desktop_surface(wparent); weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent, - x, y); + &offset); } static void @@ -378,19 +387,17 @@ set_fullscreen(struct weston_desktop_xwayland_surface *surface, struct weston_output *output) { weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL, - 0, 0); + NULL); weston_desktop_api_fullscreen_requested(surface->desktop, surface->surface, true, output); } static void -set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y) +set_xwayland(struct weston_desktop_xwayland_surface *surface, + struct weston_coord_global pos) { - struct weston_coord_global pos; - - pos.c = weston_coord(x, y); weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL, - x, y); + NULL); weston_view_set_position(surface->view, pos); } @@ -440,7 +447,7 @@ static void set_maximized(struct weston_desktop_xwayland_surface *surface) { weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL, - 0, 0); + NULL); weston_desktop_api_maximized_requested(surface->desktop, surface->surface, true); } diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index 60425fc4e..272f61416 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -159,11 +159,10 @@ struct weston_wm_window { uint32_t protocols; xcb_atom_t type; int width, height; - int x; - int y; + struct weston_coord_global pos; bool pos_dirty; - int map_request_x; - int map_request_y; + bool map_request_valid; + struct weston_coord_global map_request; struct weston_output_weak_ref legacy_fullscreen_output; int saved_width, saved_height; int decorate; @@ -884,8 +883,8 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve if (!wm_lookup_window(wm, configure_notify->window, &window)) return; - window->x = configure_notify->x; - window->y = configure_notify->y; + window->pos.c = weston_coord(configure_notify->x, + configure_notify->y); window->pos_dirty = false; if (window->override_redirect) { @@ -900,7 +899,7 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve * (configure_notify is sent before xserver_map_surface) */ if (window->shsurf) xwayland_api->set_xwayland(window->shsurf, - window->x, window->y); + window->pos); } } @@ -1258,8 +1257,8 @@ weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event) */ assert(!window->shsurf); - window->map_request_x = window->x; - window->map_request_y = window->y; + window->map_request_valid = true; + window->map_request = window->pos; if (window->frame_id == XCB_WINDOW_NONE) weston_wm_window_create_frame(window); /* sets frame_id */ @@ -1268,7 +1267,7 @@ weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event) wm_printf(wm, "XCB_MAP_REQUEST (window %d, %p, frame %d, %dx%d @ %d,%d)\n", window->id, window, window->frame_id, window->width, window->height, - window->map_request_x, window->map_request_y); + (int)window->map_request.c.x, (int)window->map_request.c.y); weston_wm_window_set_allow_commits(window, false); weston_wm_window_set_wm_state(window, ICCCM_NORMAL_STATE); @@ -1581,7 +1580,8 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even static void weston_wm_window_create(struct weston_wm *wm, - xcb_window_t id, int width, int height, int x, int y, int override) + xcb_window_t id, int width, int height, + struct weston_coord_global initial_pos, int override) { struct weston_wm_window *window; uint32_t values[1]; @@ -1612,11 +1612,9 @@ weston_wm_window_create(struct weston_wm *wm, */ window->saved_width = 512; window->saved_height = 512; - window->x = x; - window->y = y; + window->pos = initial_pos; window->pos_dirty = false; - window->map_request_x = INT_MIN; /* out of range for valid positions */ - window->map_request_y = INT_MIN; /* out of range for valid positions */ + window->map_request_valid = false; window->decor_top = -1; window->decor_bottom = -1; window->decor_left = -1; @@ -1679,6 +1677,7 @@ weston_wm_handle_create_notify(struct weston_wm *wm, xcb_generic_event_t *event) { xcb_create_notify_event_t *create_notify = (xcb_create_notify_event_t *) event; + struct weston_coord_global pos; wm_printf(wm, "XCB_CREATE_NOTIFY (window %d, at (%d, %d), width %d, height %d%s%s)\n", create_notify->window, @@ -1690,10 +1689,10 @@ weston_wm_handle_create_notify(struct weston_wm *wm, xcb_generic_event_t *event) if (our_resource(wm, create_notify->window)) return; + pos.c = weston_coord(create_notify->x, create_notify->y); weston_wm_window_create(wm, create_notify->window, create_notify->width, create_notify->height, - create_notify->x, create_notify->y, - create_notify->override_redirect); + pos, create_notify->override_redirect); } static void @@ -1731,9 +1730,11 @@ weston_wm_handle_reparent_notify(struct weston_wm *wm, xcb_generic_event_t *even reparent_notify->override_redirect ? ", override" : ""); if (reparent_notify->parent == wm->screen->root) { + struct weston_coord_global c; + + c.c = weston_coord(reparent_notify->x, reparent_notify->y); weston_wm_window_create(wm, reparent_notify->window, 10, 10, - reparent_notify->x, reparent_notify->y, - reparent_notify->override_redirect); + c, reparent_notify->override_redirect); } else if (!our_resource(wm, reparent_notify->parent)) { if (!wm_lookup_window(wm, reparent_notify->window, &window)) return; @@ -3109,7 +3110,9 @@ send_position(struct weston_surface *surface, int32_t x, int32_t y) struct weston_wm *wm; uint32_t values[2]; uint16_t mask; + struct weston_coord_global pos; + pos.c = weston_coord(x, y); if (!window || !window->wm) return; @@ -3118,7 +3121,8 @@ send_position(struct weston_surface *surface, int32_t x, int32_t y) * 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) { + if (window->pos.c.x != pos.c.x || window->pos.c.y != pos.c.y || + window->pos_dirty) { window->pos_dirty = true; values[0] = x; values[1] = y; @@ -3169,8 +3173,8 @@ legacy_fullscreen(struct weston_wm *wm, /* Heuristics for detecting legacy fullscreen windows... */ wl_list_for_each(output, &compositor->output_list, link) { - if ((int)output->pos.c.x == window->x && - (int)output->pos.c.y == window->y && + if (output->pos.c.x == window->pos.c.x && + output->pos.c.y == window->pos.c.y && output->width == window->width && output->height == window->height && window->override_redirect) { @@ -3205,15 +3209,22 @@ legacy_fullscreen(struct weston_wm *wm, static bool weston_wm_window_is_positioned(struct weston_wm_window *window) { - if (window->map_request_x == INT_MIN || - window->map_request_y == INT_MIN) + if (!window->map_request_valid) { weston_log("XWM warning: win %d did not see map request\n", window->id); + /* Before map_request_valid existed, we used a sentinel + * value for the map_request coordinates. This return + * preserves the behaviour this function had at that + * time. + */ + return true; + } + if (window->size_hints.flags & (USPosition | PPosition)) return true; - return window->map_request_x != 0 || window->map_request_y != 0; + return window->map_request.c.x != 0 || window->map_request.c.y != 0; } static bool @@ -3292,16 +3303,19 @@ xserver_map_shell_surface(struct weston_wm_window *window, window->legacy_fullscreen_output.output); } else if (window->override_redirect) { xwayland_interface->set_xwayland(window->shsurf, - window->x, window->y); + window->pos); } else if (window->transient_for && !window->transient_for->override_redirect && window->transient_for->surface) { parent = window->transient_for; if (weston_wm_window_type_inactive(window)) { + struct weston_coord_surface offset; + + offset.c = weston_coord_sub(window->pos.c, parent->pos.c); + offset.coordinate_space_id = parent->surface; xwayland_interface->set_transient(window->shsurf, parent->surface, - window->x - parent->x, - window->y - parent->y); + offset); } else { xwayland_interface->set_toplevel(window->shsurf); xwayland_interface->set_parent(window->shsurf, @@ -3313,13 +3327,10 @@ xserver_map_shell_surface(struct weston_wm_window *window, xwayland_interface->set_maximized(window->shsurf); } else { if (weston_wm_window_type_inactive(window)) { - xwayland_interface->set_xwayland(window->shsurf, - window->x, - window->y); + xwayland_interface->set_xwayland(window->shsurf, window->pos); } else if (weston_wm_window_is_positioned(window)) { xwayland_interface->set_toplevel_with_position(window->shsurf, - window->map_request_x, - window->map_request_y); + window->map_request); } else { xwayland_interface->set_toplevel(window->shsurf); } diff --git a/xwayland/xwayland-internal-interface.h b/xwayland/xwayland-internal-interface.h index 36aaca183..6ad33cc42 100644 --- a/xwayland/xwayland-internal-interface.h +++ b/xwayland/xwayland-internal-interface.h @@ -41,15 +41,16 @@ struct weston_desktop_xwayland_interface { const struct weston_xwayland_client_interface *client); void (*set_toplevel)(struct weston_desktop_xwayland_surface *shsurf); void (*set_toplevel_with_position)(struct weston_desktop_xwayland_surface *shsurf, - int32_t x, int32_t y); + struct weston_coord_global coord); void (*set_parent)(struct weston_desktop_xwayland_surface *shsurf, struct weston_surface *parent); void (*set_transient)(struct weston_desktop_xwayland_surface *shsurf, - struct weston_surface *parent, int x, int y); + struct weston_surface *parent, + struct weston_coord_surface offset); void (*set_fullscreen)(struct weston_desktop_xwayland_surface *shsurf, struct weston_output *output); void (*set_xwayland)(struct weston_desktop_xwayland_surface *shsurf, - int x, int y); + struct weston_coord_global coord); int (*move)(struct weston_desktop_xwayland_surface *shsurf, struct weston_pointer *pointer); int (*resize)(struct weston_desktop_xwayland_surface *shsurf,