diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 667748a12bf020623032710922da9aafd6486493..111d4fafdf89f7635c14b63b0a1fe8d9c07b4f78 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) @@ -506,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); @@ -581,25 +618,14 @@ 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); - 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) @@ -610,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) { @@ -656,8 +718,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); @@ -667,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, @@ -719,7 +801,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 +838,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 +1075,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; @@ -1128,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 85691d9d4ad6371cab9256229f1e94c428198411..abbffce9bfab3a9fa3364f0f99fe71bfc38092d9 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; @@ -175,7 +176,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;