From 4e50440ae20c537d6a4edf356cda67dd33d4e5a8 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 7 Jan 2019 15:20:05 +0100 Subject: [PATCH 1/3] xwayland: Separate DamagePtr into separate window data This will be dissociated in future commits to handle the cases where windows are being realized before there is a compositor handling redirection. In that case, we still want the DamagePtr to be registered upfront on RealizeWindowProc before a corresponding xwl_window might be created. Most notably, it cannot be lazily created on SetWindowPixmapProc as damage accounting gets broken. Signed-off-by: Carlos Garnacho --- hw/xwayland/xwayland.c | 74 +++++++++++++++++++++++++++++++++--------- hw/xwayland/xwayland.h | 1 - 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 667748a12..7cbd7c0c4 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -161,6 +161,7 @@ ddxProcessArgument(int argc, char *argv[], int i) static DevPrivateKeyRec xwl_window_private_key; static DevPrivateKeyRec xwl_screen_private_key; static DevPrivateKeyRec xwl_pixmap_private_key; +static DevPrivateKeyRec xwl_damage_private_key; static struct xwl_window * xwl_window_get(WindowPtr window) @@ -403,8 +404,14 @@ xwl_cursor_confined_to(DeviceIntPtr device, static void damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) { - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + WindowPtr window = data; + struct xwl_window *xwl_window = xwl_window_get(window); + struct xwl_screen *xwl_screen; + + if (!xwl_window) + return; + + xwl_screen = xwl_window->xwl_screen; #ifdef GLAMOR_HAS_GBM if (xwl_window->present_flipped) { @@ -426,6 +433,47 @@ damage_destroy(DamagePtr pDamage, void *data) { } +static Bool +register_damage(WindowPtr window) +{ + DamagePtr damage; + + damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty, + FALSE, window->drawable.pScreen, window); + if (damage == NULL) { + ErrorF("Failed creating damage\n"); + return FALSE; + } + + DamageRegister(&window->drawable, damage); + DamageSetReportAfterOp(damage, TRUE); + + dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage); + + return TRUE; +} + +static void +unregister_damage(WindowPtr window) +{ + DamagePtr damage; + + damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key); + if (!damage) + return; + + DamageUnregister(damage); + DamageDestroy(damage); + + dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL); +} + +static DamagePtr +window_get_damage(WindowPtr window) +{ + return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key); +} + static void shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) @@ -581,18 +629,10 @@ xwl_realize_window(WindowPtr window) wl_surface_set_user_data(xwl_window->surface, xwl_window); - xwl_window->damage = - DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty, - FALSE, screen, xwl_window); - if (xwl_window->damage == NULL) { - ErrorF("Failed creating damage\n"); - goto err_surf; - } - compRedirectWindow(serverClient, window, CompositeRedirectManual); - DamageRegister(&window->drawable, xwl_window->damage); - DamageSetReportAfterOp(xwl_window->damage, TRUE); + if (!register_damage(window)) + goto err_surf; dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); xorg_list_init(&xwl_window->link_damage); @@ -656,8 +696,8 @@ xwl_unrealize_window(WindowPtr window) wl_surface_destroy(xwl_window->surface); xorg_list_del(&xwl_window->link_damage); - DamageUnregister(xwl_window->damage); - DamageDestroy(xwl_window->damage); + unregister_damage(window); + if (xwl_window->frame_callback) wl_callback_destroy(xwl_window->frame_callback); @@ -719,7 +759,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window) assert(!xwl_window->frame_callback); - region = DamageRegion(xwl_window->damage); + region = DamageRegion(window_get_damage(xwl_window->window)); pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window); #ifdef XWL_HAS_GLAMOR @@ -756,7 +796,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window) wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, xwl_window); wl_surface_commit(xwl_window->surface); - DamageEmpty(xwl_window->damage); + DamageEmpty(window_get_damage(xwl_window->window)); xorg_list_del(&xwl_window->link_damage); } @@ -993,6 +1033,8 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) return FALSE; if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0)) return FALSE; + if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0)) + return FALSE; dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen); xwl_screen->screen = pScreen; diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 85691d9d4..456df1e6d 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -175,7 +175,6 @@ struct xwl_window { struct wl_surface *surface; struct wl_shell_surface *shell_surface; WindowPtr window; - DamagePtr damage; struct xorg_list link_damage; struct wl_callback *frame_callback; Bool allow_commits; -- GitLab From c2e8ae964052944312c5023ca7ea5c41a92990e5 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 7 Jan 2019 15:33:31 +0100 Subject: [PATCH 2/3] xwayland: Refactor surface creation into a separate function This is just called from xwl_window_realize() ATM, but will be useful in future commits. Signed-off-by: Carlos Garnacho --- hw/xwayland/xwayland.c | 64 ++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 7cbd7c0c4..c9b9967a3 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -554,36 +554,25 @@ send_surface_id_event(struct xwl_window *xwl_window) } static Bool -xwl_realize_window(WindowPtr window) +ensure_surface_for_window(WindowPtr window) { ScreenPtr screen = window->drawable.pScreen; struct xwl_screen *xwl_screen; struct xwl_window *xwl_window; struct wl_region *region; - Bool ret; - - xwl_screen = xwl_screen_get(screen); - - screen->RealizeWindow = xwl_screen->RealizeWindow; - ret = (*screen->RealizeWindow) (window); - xwl_screen->RealizeWindow = screen->RealizeWindow; - screen->RealizeWindow = xwl_realize_window; - if (xwl_screen->rootless && !window->parent) { - BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height }; + if (xwl_window_get(window)) + return TRUE; - RegionReset(&window->winSize, &box); - RegionNull(&window->clipList); - RegionNull(&window->borderClip); - } + xwl_screen = xwl_screen_get(screen); if (xwl_screen->rootless) { if (window->redirectDraw != RedirectDrawManual) - return ret; + return TRUE; } else { if (window->parent) - return ret; + return TRUE; } xwl_window = calloc(1, sizeof *xwl_window); @@ -631,15 +620,12 @@ xwl_realize_window(WindowPtr window) compRedirectWindow(serverClient, window, CompositeRedirectManual); - if (!register_damage(window)) - goto err_surf; - dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); xorg_list_init(&xwl_window->link_damage); xwl_window_init_allow_commits(xwl_window); - return ret; + return TRUE; err_surf: if (xwl_window->shell_surface) @@ -650,6 +636,42 @@ err: return FALSE; } +static Bool +xwl_realize_window(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + struct xwl_screen *xwl_screen; + Bool ret; + + xwl_screen = xwl_screen_get(screen); + + screen->RealizeWindow = xwl_screen->RealizeWindow; + ret = (*screen->RealizeWindow) (window); + xwl_screen->RealizeWindow = screen->RealizeWindow; + screen->RealizeWindow = xwl_realize_window; + + if (!ret) + return FALSE; + + if (xwl_screen->rootless && !window->parent) { + BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height }; + + RegionReset(&window->winSize, &box); + RegionNull(&window->clipList); + RegionNull(&window->borderClip); + } + + if (xwl_screen->rootless ? + (window->drawable.class == InputOutput && + window->parent == window->drawable.pScreen->root) : + !window->parent) { + if (!register_damage(window)) + return FALSE; + } + + return ensure_surface_for_window(window); +} + static Bool xwl_unrealize_window(WindowPtr window) { -- GitLab From 78cc8b6f9613fc71f6ecc7e8848d54364a250634 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 7 Jan 2019 15:33:35 +0100 Subject: [PATCH 3/3] xwayland: Handle the case of windows being realized before redirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Xwayland gets to realize a window meant for composition before the compositor redirected windows (i.e. redirect mode is not RedirectDrawManual yet), the window would stay "invisible" as we wouldn't create a wl_surface/wl_shell_surface for it at any later point. This scenario may happen if the wayland compositor sets up a X11 socket upfront, but waits to raise Xwayland until there are X11 clients. In this case the first data on the socket is the client's, the compositor can hardly beat that in order to redirect subwindows before the client realizes a Window. In order to jump across this hurdle, allow the late creation of a matching (shell) surface for the WindowPtr on SetWindowPixmapProc, so it is ensured to be created after the compositor set up redirection. Signed-off-by: Carlos Garnacho Reviewed-by: Michel Dänzer Reviewed-by: Olivier Fourdan --- hw/xwayland/xwayland.c | 25 +++++++++++++++++++++++++ hw/xwayland/xwayland.h | 1 + 2 files changed, 26 insertions(+) diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index c9b9967a3..111d4fafd 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -729,6 +729,26 @@ xwl_unrealize_window(WindowPtr window) return ret; } +static void +xwl_set_window_pixmap(WindowPtr window, + PixmapPtr pixmap) +{ + ScreenPtr screen = window->drawable.pScreen; + struct xwl_screen *xwl_screen; + + xwl_screen = xwl_screen_get(screen); + + screen->SetWindowPixmap = xwl_screen->SetWindowPixmap; + (*screen->SetWindowPixmap) (window, pixmap); + xwl_screen->SetWindowPixmap = screen->SetWindowPixmap; + screen->SetWindowPixmap = xwl_set_window_pixmap; + + if (!RegionNotEmpty(&window->winSize)) + return; + + ensure_surface_for_window(window); +} + static void frame_callback(void *data, struct wl_callback *callback, @@ -1192,6 +1212,11 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) xwl_screen->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = xwl_close_screen; + if (xwl_screen->rootless) { + xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; + pScreen->SetWindowPixmap = xwl_set_window_pixmap; + } + pScreen->CursorWarpedTo = xwl_cursor_warped_to; pScreen->CursorConfinedTo = xwl_cursor_confined_to; diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 456df1e6d..abbffce9b 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -130,6 +130,7 @@ struct xwl_screen { UnrealizeWindowProcPtr UnrealizeWindow; DestroyWindowProcPtr DestroyWindow; XYToWindowProcPtr XYToWindow; + SetWindowPixmapProcPtr SetWindowPixmap; struct xorg_list output_list; struct xorg_list seat_list; -- GitLab