From ddc6979cd9d4518aa7a265ee8ad21a112621f73a Mon Sep 17 00:00:00 2001 From: Hideyuki Nagase Date: Tue, 25 May 2021 14:06:18 -0700 Subject: [PATCH] fix android emulator window is not movable when no frame (#17) Co-authored-by: Hideyuki Nagase --- include/libweston-desktop/libweston-desktop.h | 6 +++ libweston-desktop/internal.h | 5 ++ libweston-desktop/libweston-desktop.c | 10 ++++ libweston-desktop/xwayland.c | 48 ++++++++--------- rdprail-shell/shell.c | 40 ++++++++++++++- xwayland/window-manager.c | 51 ++++++++++++++----- xwayland/xwayland-internal-interface.h | 4 +- 7 files changed, 122 insertions(+), 42 deletions(-) diff --git a/include/libweston-desktop/libweston-desktop.h b/include/libweston-desktop/libweston-desktop.h index a63249372..47295cf16 100644 --- a/include/libweston-desktop/libweston-desktop.h +++ b/include/libweston-desktop/libweston-desktop.h @@ -117,6 +117,12 @@ struct weston_desktop_api { */ void (*set_xwayland_position)(struct weston_desktop_surface *surface, int32_t x, int32_t y, void *user_data); + /* + * In contrast to above set_xwayland_position(), move_xwayland_position() + * to be used to move window after mapped. + */ + void (*move_xwayland_position)(struct weston_desktop_surface *surface, + int32_t x, int32_t y, void *user_data); }; void diff --git a/libweston-desktop/internal.h b/libweston-desktop/internal.h index 67172766c..26ff30c93 100644 --- a/libweston-desktop/internal.h +++ b/libweston-desktop/internal.h @@ -91,6 +91,11 @@ weston_desktop_api_set_xwayland_position(struct weston_desktop *desktop, struct weston_desktop_surface *surface, int32_t x, int32_t y); +void +weston_desktop_api_move_xwayland_position(struct weston_desktop *desktop, + struct weston_desktop_surface *surface, + int32_t x, int32_t y); + struct weston_desktop_seat * weston_desktop_seat_from_seat(struct weston_seat *wseat); diff --git a/libweston-desktop/libweston-desktop.c b/libweston-desktop/libweston-desktop.c index d1d0f2011..c72039211 100644 --- a/libweston-desktop/libweston-desktop.c +++ b/libweston-desktop/libweston-desktop.c @@ -262,3 +262,13 @@ weston_desktop_api_set_xwayland_position(struct weston_desktop *desktop, desktop->api.set_xwayland_position(surface, x, y, desktop->user_data); } + +void +weston_desktop_api_move_xwayland_position(struct weston_desktop *desktop, + struct weston_desktop_surface *surface, + int32_t x, int32_t y) +{ + if (desktop->api.move_xwayland_position != NULL) + desktop->api.move_xwayland_position(surface, x, y, + desktop->user_data); +} diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c index cc93fc05b..14b883ea0 100644 --- a/libweston-desktop/xwayland.c +++ b/libweston-desktop/xwayland.c @@ -328,6 +328,29 @@ set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y) weston_view_set_position(surface->view, x, y); } +static void +move_position(struct weston_desktop_xwayland_surface *surface, int x, int y) +{ + if (surface->state == XWAYLAND) { + /* For XWAYLAND surface, here directly set view position, + just like set_xwayland() when view is associated. */ + if (surface->view) + weston_view_set_position(surface->view, x, y); + } else if (surface->state == TOPLEVEL) { + weston_desktop_api_move_xwayland_position(surface->desktop, + surface->surface, x, y); + } +#ifdef WM_DEBUG + weston_log("%s: %s window (%p) move to (%d,%d)\n", + __func__, + (surface->state == XWAYLAND) ? "XWAYLAND" : \ + (surface->state == TOPLEVEL) ? "TOPLEVEL" : \ + (surface->state == MAXIMIZED) ? "MAXIMIZED" : \ + (surface->state == FULLSCREEN) ? "FULLSCREEN" : "UNKNOWN", + surface, x, y); +#endif +} + static int move(struct weston_desktop_xwayland_surface *surface, struct weston_pointer *pointer) @@ -375,29 +398,6 @@ set_window_geometry(struct weston_desktop_xwayland_surface *surface, } } -static void -set_position(struct weston_desktop_xwayland_surface *surface, - int x, int y, int width, int height) -{ - if (surface->state == XWAYLAND) { - /* For XWAYLAND surface, here directly set view position, - just like set_xwayland() when view is associated. */ - if (surface->view) - weston_view_set_position(surface->view, x, y); - } else { - /* TODO what to do these? need a way to move shell surface! */ - } -#ifdef WM_DEBUG - weston_log("%s: %s window (%p) move to (%d,%d)\n", - __func__, - (surface->state == XWAYLAND) ? "XWAYLAND" : \ - (surface->state == TOPLEVEL) ? "TOPLEVEL" : \ - (surface->state == MAXIMIZED) ? "MAXIMIZED" : \ - (surface->state == FULLSCREEN) ? "FULLSCREEN" : "UNKNOWN", - surface, x, y); -#endif -} - static void set_maximized(struct weston_desktop_xwayland_surface *surface) { @@ -436,7 +436,7 @@ static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_in .set_transient = set_transient, .set_fullscreen = set_fullscreen, .set_xwayland = set_xwayland, - .set_position = set_position, + .move_position = move_position, .move = move, .resize = resize, .set_title = set_title, diff --git a/rdprail-shell/shell.c b/rdprail-shell/shell.c index c059701be..6f1db1bab 100644 --- a/rdprail-shell/shell.c +++ b/rdprail-shell/shell.c @@ -2138,8 +2138,8 @@ set_position_from_xwayland(struct shell_surface *shsurf) /* Use xwayland position as this is the X app's origin of client area */ if (shsurf->xwayland.x >= area.x && shsurf->xwayland.y >= area.y && - shsurf->xwayland.x <= (int32_t)(area.x + area.width - (area.width / 10)) && - shsurf->xwayland.y <= (int32_t)(area.y + area.width - (area.width / 10))) { + shsurf->xwayland.x < (int32_t)(area.x + area.width - (area.width / 10)) && + shsurf->xwayland.y < (int32_t)(area.y + area.height - (area.height / 10))) { weston_view_set_position(shsurf->view, x, y); @@ -2808,6 +2808,41 @@ desktop_surface_set_xwayland_position(struct weston_desktop_surface *surface, shsurf->xwayland.is_set = true; } +static void +desktop_surface_move_xwayland_position(struct weston_desktop_surface *desktop_surface, + int32_t x, int32_t y, void *shell_) +{ + struct weston_surface *surface = + weston_desktop_surface_get_surface(desktop_surface); + struct shell_surface *shsurf = + weston_desktop_surface_get_user_data(desktop_surface); + struct desktop_shell *shell = shsurf->shell; + const struct weston_xwayland_surface_api *api; + + assert(shell == shell_); + + api = shell->xwayland_surface_api; + if (!api) { + api = weston_xwayland_surface_get_api(shell->compositor); + shell->xwayland_surface_api = api; + } + if (api && api->is_xwayland_surface(surface)) { + /* TODO: Make sure the position given from xwayland is a part of workarea, + But this is not simple, for example, app can have accompanying + window which move along with other main window, in such case, + often, it's totally fine the accompanying goes out of workarea. */ + + weston_view_set_position(shsurf->view, x, y); + weston_compositor_schedule_repaint(shell->compositor); + + shell_rdp_debug_verbose(shell, "%s: surface:%p, position (%d,%d)\n", + __func__, surface, x, y); + } else { + shell_rdp_debug_error(shell, "%s: surface:%p is not from xwayland\n", + __func__, surface); + } +} + static const struct weston_desktop_api shell_desktop_api = { .struct_size = sizeof(struct weston_desktop_api), .surface_added = desktop_surface_added, @@ -2822,6 +2857,7 @@ static const struct weston_desktop_api shell_desktop_api = { .ping_timeout = desktop_surface_ping_timeout, .pong = desktop_surface_pong, .set_xwayland_position = desktop_surface_set_xwayland_position, + .move_xwayland_position = desktop_surface_move_xwayland_position, .set_window_icon = desktop_surface_set_window_icon, }; diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index eb82144f2..407404288 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -157,6 +157,8 @@ struct weston_wm_window { int x; int y; bool pos_dirty; + int frame_x; + int frame_y; int map_request_x; int map_request_y; struct weston_output_weak_ref legacy_fullscreen_output; @@ -757,6 +759,7 @@ weston_wm_window_send_configure_notify(struct weston_wm_window *window) { xcb_configure_notify_event_t configure_notify; struct weston_wm *wm = window->wm; + bool is_our_resource = our_resource(wm, window->id); int x, y; weston_wm_window_get_child_position(window, &x, &y); @@ -776,13 +779,18 @@ weston_wm_window_send_configure_notify(struct weston_wm_window *window) xcb_send_event(wm->conn, 0, window->id, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *) &configure_notify); + + wm_printf(wm, "XWM: send_configure_notify (window %d) %d,%d @ %dx%d%s\n", + window->id, x, y, window->width, window->height, + is_our_resource ? ", ours" : ""); } static void -weston_wm_window_send_event_configure_notify_window_position(struct weston_wm_window *window, int x, int y) +weston_wm_window_send_event_configure_notify_with_position(struct weston_wm_window *window, int x, int y) { xcb_configure_notify_event_t configure_notify; struct weston_wm *wm = window->wm; + bool is_our_resource = our_resource(wm, window->id); configure_notify.response_type = XCB_CONFIGURE_NOTIFY; configure_notify.pad0 = 0; @@ -800,6 +808,10 @@ weston_wm_window_send_event_configure_notify_window_position(struct weston_wm_wi xcb_send_event(wm->conn, 0, window->id, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *) &configure_notify); + + wm_printf(wm, "XWM: send_event_configure_notify_window_position (window %d) %d,%d @ %dx%d%s\n", + window->id, x, y, window->width, window->height, + is_our_resource ? ", ours" : ""); } static void @@ -1018,8 +1030,16 @@ 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; + if (window->override_redirect || is_our_resource) { + /* override or frame */ + window->frame_x = configure_notify->x; + window->frame_y = configure_notify->y; + } + if (window->override_redirect || !is_our_resource) { + /* override or not frame */ + window->x = configure_notify->x; + window->y = configure_notify->y; + } window->pos_dirty = false; if (window->override_redirect) { @@ -1037,9 +1057,8 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve window->x, window->y); } else if (is_our_resource) { if (window->shsurf) - xwayland_api->set_position(window->shsurf, - window->x, window->y, - window->width, window->height); + xwayland_api->move_position(window->shsurf, + window->frame_x, window->frame_y); } } @@ -1755,6 +1774,8 @@ weston_wm_window_create(struct weston_wm *wm, window->x = x; window->y = y; window->pos_dirty = false; + window->frame_x = INT_MIN; + window->frame_y = INT_MIN; window->map_request_x = INT_MIN; /* out of range for valid positions */ window->map_request_y = INT_MIN; /* out of range for valid positions */ weston_output_weak_ref_init(&window->legacy_fullscreen_output); @@ -3068,24 +3089,26 @@ 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 values[2]; - uint16_t mask; int dx, dy; if (!window || !window->wm) return; wm = window->wm; + + wm_printf(wm, "XWM: send_position (window %d) input %d,%d frame %d,%d window %d,%d%s\n", + window->id, x, y, + window->frame_x, window->frame_y, + window->x, window->y, + window->override_redirect ? ", override" : ""); + /* 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) { + if (window->frame_x != x || window->frame_y != y || window->pos_dirty) { window->pos_dirty = true; - values[0] = x; - values[1] = y; - mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; - weston_wm_configure_window(wm, window->frame_id, mask, values); + weston_wm_window_configure_frame_with_position(window, x, y); // !!! need further investigation !!! /* Xwayland reparents app's window with our own frame window @@ -3097,7 +3120,7 @@ send_position(struct weston_surface *surface, int32_t x, int32_t y) event to let application knows actual app's window position (rather than offset from parent/frame window */ weston_wm_window_get_child_position(window, &dx, &dy); - weston_wm_window_send_event_configure_notify_window_position(window, x + dx, y + dy); + weston_wm_window_send_event_configure_notify_with_position(window, x + dx, y + dy); xcb_flush(wm->conn); } diff --git a/xwayland/xwayland-internal-interface.h b/xwayland/xwayland-internal-interface.h index bf7ed7705..88d153fd5 100644 --- a/xwayland/xwayland-internal-interface.h +++ b/xwayland/xwayland-internal-interface.h @@ -48,8 +48,8 @@ struct weston_desktop_xwayland_interface { struct weston_output *output); void (*set_xwayland)(struct weston_desktop_xwayland_surface *shsurf, int x, int y); - void (*set_position)(struct weston_desktop_xwayland_surface *shsurf, - int x, int y, int width, int height); + void (*move_position)(struct weston_desktop_xwayland_surface *shsurf, + int x, int y); int (*move)(struct weston_desktop_xwayland_surface *shsurf, struct weston_pointer *pointer); int (*resize)(struct weston_desktop_xwayland_surface *shsurf,