xserver: Branch 'master' - 12 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Apr 10 08:59:38 UTC 2024
hw/xwayland/xwayland-dmabuf.c | 4
hw/xwayland/xwayland-glamor-gbm.c | 5
hw/xwayland/xwayland-glamor.c | 9
hw/xwayland/xwayland-glamor.h | 2
hw/xwayland/xwayland-input.c | 35 +--
hw/xwayland/xwayland-input.h | 4
hw/xwayland/xwayland-present.c | 89 ++++++-
hw/xwayland/xwayland-present.h | 6
hw/xwayland/xwayland-screen.c | 19 -
hw/xwayland/xwayland-screen.h | 6
hw/xwayland/xwayland-window-buffers.c | 17 -
hw/xwayland/xwayland-window.c | 381 ++++++++++++++++++++++++++--------
hw/xwayland/xwayland-window.h | 33 ++
13 files changed, 466 insertions(+), 144 deletions(-)
New commits:
commit c7d56b0e294f572c0685a572077b5bfdfbf33b49
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 15 18:34:13 2024 +0100
xwayland/present: Redirect surface window as needed for page flips
It's needed when the surface window is a depth 24 descendant of a depth
32 toplevel window.
xwl_source_validate ensures the toplevel window pixmap has valid
contents when a client reads from it, or when the window hierarchy /
geometry changes. It's never called in the normal fullscreen application
case, so there's no GPU copy overhead with that.
v2:
* Don't try to redirect a depth 32 descendant of different-depth
ancestors, the alpha channel wouldn't be handled correctly.
(Olivier Fourdan)
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index f03366437..ab56fe551 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -46,6 +46,7 @@
#include "xwayland-dmabuf.h"
#include "xwayland-glamor.h"
#include "xwayland-glamor-gbm.h"
+#include "xwayland-present.h"
#include "xwayland-screen.h"
#include "xwayland-window.h"
#include "xwayland-window-buffers.h"
@@ -96,8 +97,12 @@ xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap)
ScreenPtr screen = pixmap->drawable.pScreen;
PixmapPtr backing_pixmap = screen->GetWindowPixmap(present_window);
- if (pixmap->drawable.depth != backing_pixmap->drawable.depth)
- return FALSE;
+ if (pixmap->drawable.depth != backing_pixmap->drawable.depth) {
+ if (pixmap->drawable.depth == 32)
+ return FALSE;
+
+ return xwl_present_maybe_redirect_window(present_window, pixmap);
+ }
return TRUE;
}
commit 4495c696b5dfa78a4ba80b76888f85532386d1b8
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Tue Jan 9 17:35:21 2024 +0100
xwayland/present: Check window & source pixmap depth match last
Preparation for next commit, no functional change intended.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index ff0a560db..43f053dfb 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -773,16 +773,6 @@ xwl_present_check_flip(RRCrtcPtr crtc,
if (!RegionEqual(&present_window->clipList, &present_window->winSize))
return FALSE;
-#ifdef XWL_HAS_GLAMOR
- if (xwl_window->xwl_screen->glamor &&
- !xwl_glamor_check_flip(present_window, pixmap))
- return FALSE;
-
- if (!xwl_glamor_supports_implicit_sync(xwl_window->xwl_screen) &&
- !xwl_window->xwl_screen->explicit_sync)
- return FALSE;
-#endif /* XWL_HAS_GLAMOR */
-
/* Can't flip if the window pixmap doesn't match the xwl_window parent
* window's, e.g. because a client redirected this window or one of its
* parents.
@@ -798,6 +788,16 @@ xwl_present_check_flip(RRCrtcPtr crtc,
if (!RegionEqual(&xwl_window->toplevel->winSize, &present_window->winSize))
return FALSE;
+#ifdef XWL_HAS_GLAMOR
+ if (!xwl_glamor_supports_implicit_sync(xwl_window->xwl_screen) &&
+ !xwl_window->xwl_screen->explicit_sync)
+ return FALSE;
+
+ if (xwl_window->xwl_screen->glamor &&
+ !xwl_glamor_check_flip(present_window, pixmap))
+ return FALSE;
+#endif /* XWL_HAS_GLAMOR */
+
return TRUE;
}
commit aa05f38f3deb55b63759571a9c600ef8f71b489c
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Wed Jan 10 14:55:57 2024 +0100
xwayland: Add SourceValidate hook
A later commit will use it to ensure the toplevel window pixmap has
valid contents.
It's hooked up only while any xwl_window->surface_window_damage points
to a non-empty region. So far it's always NULL, so no functional change
intended.
v2:
* Fix trailing whitespace. (Olivier Fourdan)
v3:
* Use toplevel local variable more in xwl_window_update_surface_window.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 5b30c210b..757417ef6 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -81,6 +81,7 @@ struct xwl_screen {
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
ReparentWindowProcPtr ReparentWindow;
MoveWindowProcPtr MoveWindow;
+ SourceValidateProcPtr SourceValidate;
int (*GrabServer) (ClientPtr client);
int (*UngrabServer) (ClientPtr client);
@@ -91,6 +92,8 @@ struct xwl_screen {
struct xorg_list window_list;
Bool ignore_damage;
+ int need_source_validate;
+
int wayland_fd;
struct wl_display *display;
struct wl_registry *registry;
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index fe2983a25..c0938b9e4 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -189,6 +189,107 @@ xwl_window_update_property(struct xwl_window *xwl_window,
}
}
+static void
+need_source_validate_dec(struct xwl_screen *xwl_screen)
+{
+ xwl_screen->need_source_validate--;
+
+ if (!xwl_screen->need_source_validate)
+ xwl_screen->screen->SourceValidate = xwl_screen->SourceValidate;
+}
+
+static void
+xwl_source_validate(DrawablePtr drawable, int x, int y, int width, int height,
+ unsigned int sub_window_mode)
+{
+ struct xwl_window *xwl_window;
+ WindowPtr window, iterator;
+ RegionRec region;
+ BoxRec box;
+
+ if (sub_window_mode != IncludeInferiors ||
+ drawable->type != DRAWABLE_WINDOW)
+ return;
+
+ window = (WindowPtr)drawable;
+ xwl_window = xwl_window_from_window(window);
+ if (!xwl_window || !xwl_window->surface_window_damage ||
+ !RegionNotEmpty(xwl_window->surface_window_damage))
+ return;
+
+ for (iterator = xwl_window->toplevel;
+ ;
+ iterator = iterator->firstChild) {
+ if (iterator == xwl_window->surface_window)
+ return;
+
+ if (iterator == window)
+ break;
+ }
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ RegionInit(®ion, &box, 1);
+ RegionIntersect(®ion, ®ion, xwl_window->surface_window_damage);
+
+ if (RegionNotEmpty(®ion)) {
+ ScreenPtr screen = drawable->pScreen;
+ PixmapPtr dst_pix, src_pix;
+ BoxPtr pbox;
+ GCPtr pGC;
+ int nbox;
+
+ dst_pix = screen->GetWindowPixmap(window);
+ pGC = GetScratchGC(dst_pix->drawable.depth, screen);
+ if (!pGC)
+ FatalError("GetScratchGC failed for depth %d", dst_pix->drawable.depth);
+ ValidateGC(&dst_pix->drawable, pGC);
+
+ src_pix = screen->GetWindowPixmap(xwl_window->surface_window);
+
+ RegionSubtract(xwl_window->surface_window_damage,
+ xwl_window->surface_window_damage,
+ ®ion);
+
+ if (!RegionNotEmpty(xwl_window->surface_window_damage))
+ need_source_validate_dec(xwl_window->xwl_screen);
+
+#if defined(COMPOSITE)
+ if (dst_pix->screen_x || dst_pix->screen_y)
+ RegionTranslate(®ion, -dst_pix->screen_x, -dst_pix->screen_y);
+#endif
+
+ pbox = RegionRects(®ion);
+ nbox = RegionNumRects(®ion);
+ while (nbox--) {
+ (void) (*pGC->ops->CopyArea) (&src_pix->drawable,
+ &dst_pix->drawable,
+ pGC,
+ pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
+ pbox->x1, pbox->y1);
+ }
+ FreeScratchGC(pGC);
+ }
+
+ RegionUninit(®ion);
+}
+
+static void
+need_source_validate_inc(struct xwl_screen *xwl_screen)
+{
+ if (!xwl_screen->need_source_validate) {
+ ScreenPtr screen = xwl_screen->screen;
+
+ xwl_screen->SourceValidate = screen->SourceValidate;
+ screen->SourceValidate = xwl_source_validate;
+ }
+
+ xwl_screen->need_source_validate++;
+}
+
static void
damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
{
@@ -196,6 +297,16 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
PixmapPtr window_pixmap;
+ if (xwl_window->surface_window_damage &&
+ RegionNotEmpty(pRegion)) {
+ if (!RegionNotEmpty(xwl_window->surface_window_damage))
+ need_source_validate_inc(xwl_screen);
+
+ RegionUnion(xwl_window->surface_window_damage,
+ xwl_window->surface_window_damage,
+ DamageRegion(pDamage));
+ }
+
if (xwl_screen->ignore_damage)
return;
@@ -1259,6 +1370,25 @@ xwl_window_update_surface_window(struct xwl_window *xwl_window)
if (xwl_window->surface_window == surface_window)
return;
+ if (xwl_window->surface_window_damage) {
+ if (xwl_present_maybe_unredirect_window(xwl_window->surface_window) &&
+ screen->SourceValidate == xwl_source_validate) {
+ WindowPtr toplevel = xwl_window->toplevel;
+
+ xwl_source_validate(&toplevel->drawable,
+ toplevel->drawable.x, toplevel->drawable.y,
+ toplevel->drawable.width,
+ toplevel->drawable.height,
+ IncludeInferiors);
+ }
+
+ if (RegionNotEmpty(xwl_window->surface_window_damage))
+ need_source_validate_dec(xwl_window->xwl_screen);
+
+ RegionDestroy(xwl_window->surface_window_damage);
+ xwl_window->surface_window_damage = NULL;
+ }
+
window_damage = window_get_damage(xwl_window->surface_window);
if (window_damage) {
RegionInit(&damage_region, NullBox, 1);
@@ -1666,6 +1796,12 @@ xwl_config_notify(WindowPtr window,
xwl_window = xwl_window_from_window(window);
size_changed = width != window->drawable.width || height != window->drawable.height;
+ if (size_changed && xwl_window && xwl_window->toplevel == window &&
+ screen->SourceValidate == xwl_source_validate) {
+ xwl_source_validate(&window->drawable, window->drawable.x, window->drawable.y,
+ window->drawable.width, window->drawable.height,
+ IncludeInferiors);
+ }
screen->ConfigNotify = xwl_screen->ConfigNotify;
ret = screen->ConfigNotify(window, x, y, width, height, bw, sib);
commit fca63f8fb8e09d6c76f94e5682e9dc7d32495b87
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 15 18:27:27 2024 +0100
xwayland/present: Add xwl_present_maybe_(un)redirect_window
A later commit will use these to (un)redirect the surface window on
demand.
Not used yet, so no functional change intended.
v2:
* Use "surface_window_damage" instead of "surf_win_damage".
(Olivier Fourdan)
* Slightly simplify logic in xwl_unrealize_window.
v3:
* Add comment in xwl_present_maybe_unredirect_window explaining why we
use a timer. (Olivier Fourdan)
v4:
* Rename unredir_timer field to unredirect_timer.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 9def82fcd..ff0a560db 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -25,6 +25,7 @@
#include <xwayland-config.h>
+#include <compint.h>
#ifdef XWL_HAS_GLAMOR
#include <glamor.h>
#endif
@@ -484,6 +485,7 @@ xwl_present_cleanup(WindowPtr window)
/* Clear timer */
xwl_present_free_timer(xwl_present_window);
+ TimerFree(xwl_present_window->unredirect_timer);
/* Remove from privates so we don't try to access it later */
dixSetPrivate(&window->devPrivates,
@@ -1263,6 +1265,67 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window)
xwl_present_reset_timer(xwl_present_window);
}
+Bool
+xwl_present_maybe_redirect_window(WindowPtr window, PixmapPtr pixmap)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
+ struct xwl_window *xwl_window = xwl_window_from_window(window);
+
+ if (xwl_present_window->redirect_failed)
+ return FALSE;
+
+ if (compRedirectWindow(serverClient, window, CompositeRedirectManual) != Success) {
+ xwl_present_window->redirect_failed = TRUE;
+ return FALSE;
+ }
+
+ xwl_window_update_surface_window(xwl_window);
+ if (xwl_window->surface_window != window) {
+ compUnredirectWindow(serverClient, window, CompositeRedirectManual);
+ xwl_present_window->redirect_failed = TRUE;
+ return FALSE;
+ }
+
+ if (!xwl_window->surface_window_damage)
+ xwl_window->surface_window_damage = RegionCreate(NullBox, 1);
+
+ xwl_present_window->redirected = TRUE;
+ return TRUE;
+}
+
+static CARD32
+unredirect_window(OsTimerPtr timer, CARD32 time, void *arg)
+{
+ WindowPtr window = arg;
+ struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
+
+ compUnredirectWindow(serverClient, window, CompositeRedirectManual);
+ xwl_present_window->redirected = FALSE;
+
+ xwl_present_window->unredirect_timer = NULL;
+ return 0;
+}
+
+Bool
+xwl_present_maybe_unredirect_window(WindowPtr window)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
+
+ if (!xwl_present_window || !xwl_present_window->redirected)
+ return FALSE;
+
+ /* This function may get called from composite layer code, in which case
+ * calling compUnredirectWindow would blow up. To avoid this, set up a timer
+ * which will call it "as soon as possible".
+ */
+ if (!xwl_present_window->unredirect_timer) {
+ xwl_present_window->unredirect_timer =
+ TimerSet(NULL, 0, 1, unredirect_window, window);
+ }
+
+ return TRUE;
+}
+
Bool
xwl_present_init(ScreenPtr screen)
{
diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h
index c0efaa6bf..808e54182 100644
--- a/hw/xwayland/xwayland-present.h
+++ b/hw/xwayland/xwayland-present.h
@@ -54,6 +54,10 @@ struct xwl_present_window {
present_vblank_ptr flip_active;
uint64_t blocking_event;
+
+ OsTimerPtr unredirect_timer;
+ Bool redirected;
+ Bool redirect_failed;
};
struct xwl_present_event {
@@ -77,5 +81,7 @@ void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window);
Bool xwl_present_init(ScreenPtr screen);
void xwl_present_cleanup(WindowPtr window);
void xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window);
+Bool xwl_present_maybe_redirect_window(WindowPtr window, PixmapPtr pixmap);
+Bool xwl_present_maybe_unredirect_window(WindowPtr window);
#endif /* XWAYLAND_PRESENT_H */
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 93b689525..fe2983a25 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1221,7 +1221,7 @@ err_surf:
return FALSE;
}
-static void
+void
xwl_window_update_surface_window(struct xwl_window *xwl_window)
{
WindowPtr surface_window = xwl_window->toplevel;
@@ -1512,14 +1512,15 @@ xwl_unrealize_window(WindowPtr window)
xwl_screen = xwl_screen_get(screen);
- compUnredirectWindow(serverClient, window, CompositeRedirectManual);
+ xwl_window = xwl_window_get(window);
+ if (xwl_window)
+ compUnredirectWindow(serverClient, window, CompositeRedirectManual);
screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
ret = (*screen->UnrealizeWindow) (window);
xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
screen->UnrealizeWindow = xwl_unrealize_window;
- xwl_window = xwl_window_get(window);
if (!xwl_window)
return ret;
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index 8823b03ea..836f654a3 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -82,6 +82,7 @@ struct xwl_window {
* can also be used for the X dimensions of the Wayland surface though.
*/
WindowPtr surface_window;
+ RegionPtr surface_window_damage;
struct xorg_list link_damage;
struct xorg_list link_window;
@@ -121,6 +122,7 @@ void xwl_window_rootful_update_title(struct xwl_window *xwl_window);
void xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window,
struct xwl_output *xwl_output);
void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap);
+void xwl_window_update_surface_window(struct xwl_window *xwl_window);
void xwl_window_leave_output(struct xwl_window *xwl_window,
struct xwl_output *xwl_output);
commit fa7b1c20c4104dd134e502f85c9918216548c8c7
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 15 18:08:16 2024 +0100
xwayland: Use ConfigNotify screen hook instead of ResizeWindow
Preparation for later commits, no functional change intended.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 135ae7b74..284189912 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -1113,8 +1113,8 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = xwl_clip_notify;
- xwl_screen->ResizeWindow = pScreen->ResizeWindow;
- pScreen->ResizeWindow = xwl_resize_window;
+ xwl_screen->ConfigNotify = pScreen->ConfigNotify;
+ pScreen->ConfigNotify = xwl_config_notify;
xwl_screen->MoveWindow = pScreen->MoveWindow;
pScreen->MoveWindow = xwl_move_window;
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 9653d82c9..5b30c210b 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -71,6 +71,7 @@ struct xwl_screen {
ClipNotifyProcPtr ClipNotify;
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
+ ConfigNotifyProcPtr ConfigNotify;
CreateWindowProcPtr CreateWindow;
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
@@ -79,7 +80,6 @@ struct xwl_screen {
SetWindowPixmapProcPtr SetWindowPixmap;
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
ReparentWindowProcPtr ReparentWindow;
- ResizeWindowProcPtr ResizeWindow;
MoveWindowProcPtr MoveWindow;
int (*GrabServer) (ClientPtr client);
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 11a6b3adc..93b689525 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1649,25 +1649,29 @@ xwl_clip_notify(WindowPtr window, int dx, int dy)
xwl_window_update_surface_window(xwl_window);
}
-void
-xwl_resize_window(WindowPtr window,
+int
+xwl_config_notify(WindowPtr window,
int x, int y,
- unsigned int width, unsigned int height,
+ int width, int height, int bw,
WindowPtr sib)
{
ScreenPtr screen = window->drawable.pScreen;
struct xwl_screen *xwl_screen;
struct xwl_window *xwl_window;
+ Bool size_changed;
+ int ret;
xwl_screen = xwl_screen_get(screen);
xwl_window = xwl_window_from_window(window);
- screen->ResizeWindow = xwl_screen->ResizeWindow;
- (*screen->ResizeWindow) (window, x, y, width, height, sib);
- xwl_screen->ResizeWindow = screen->ResizeWindow;
- screen->ResizeWindow = xwl_resize_window;
+ size_changed = width != window->drawable.width || height != window->drawable.height;
- if (xwl_window) {
+ screen->ConfigNotify = xwl_screen->ConfigNotify;
+ ret = screen->ConfigNotify(window, x, y, width, height, bw, sib);
+ xwl_screen->ConfigNotify = screen->ConfigNotify;
+ screen->ConfigNotify = xwl_config_notify;
+
+ if (size_changed && xwl_window) {
if (xwl_window_get(window) || xwl_window_is_toplevel(window))
xwl_window_check_resolution_change_emulation(xwl_window);
if (window == screen->root) {
@@ -1682,6 +1686,8 @@ xwl_resize_window(WindowPtr window,
xwl_window_check_fractional_scale_viewport(xwl_window, width, height);
}
}
+
+ return ret;
}
void
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index fefb4969c..8823b03ea 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -129,10 +129,10 @@ Bool xwl_realize_window(WindowPtr window);
Bool xwl_unrealize_window(WindowPtr window);
Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask);
void xwl_clip_notify(WindowPtr window, int dx, int dy);
-void xwl_resize_window(WindowPtr window,
- int x, int y,
- unsigned int width, unsigned int height,
- WindowPtr sib);
+int xwl_config_notify(WindowPtr window,
+ int x, int y,
+ int width, int height, int bw,
+ WindowPtr sib);
void xwl_move_window(WindowPtr window,
int x, int y,
WindowPtr next_sib,
commit 3a0fc2684a037591725585c50760fda6e3c3c765
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Fri Dec 22 19:00:42 2023 +0100
xwayland: Add xwl_window::surface_window
It may track a non-toplevel window which fully covers the area of the
window pixmap / Wayland surface. It is now used instead of
xwl_window::toplevel for updating the Wayland surface contents.
The surface_window can now hit the Present page flip path while it's
automatically redirected.
v2:
* Use "surface_window" instead of "surf_win". (Olivier Fourdan)
* Add comment describing surface_window, and describe what
surface_window/toplevel are useful for respectively. (Olivier Fourdan)
* Use surface_window in xwl_realize_window.
v3:
* Backtrack up to the closest opaque ancestor in
xwl_window_update_surface_window. (Olivier Fourdan)
v4:
* Clean up logic for determining the surface window in
xwl_window_update_surface_window, and document it better.
* Handle window_get_damage(xwl_window->surface_window) returning NULL
in xwl_window_update_surface_window.
* Call xwl_window_update_surface_window after xwl_window_buffers_init
in ensure_surface_for_window, since the former may call
xwl_window_buffers_dispose.
* Rename surf/win_pix to surface/window_pixmap in
xwl_window_update_surface_window.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-dmabuf.c b/hw/xwayland/xwayland-dmabuf.c
index 97c501273..8119e1ddb 100644
--- a/hw/xwayland/xwayland-dmabuf.c
+++ b/hw/xwayland/xwayland-dmabuf.c
@@ -735,7 +735,7 @@ xwl_window_dmabuf_feedback_done(void *data,
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
{
struct xwl_window *xwl_window = data;
- uint32_t format = wl_drm_format_for_depth(xwl_window->toplevel->drawable.depth);
+ uint32_t format = wl_drm_format_for_depth(xwl_window->surface_window->drawable.depth);
xwl_dmabuf_feedback_done(&xwl_window->feedback, dmabuf_feedback);
@@ -743,7 +743,7 @@ xwl_window_dmabuf_feedback_done(void *data,
xwl_feedback_is_modifier_supported(&xwl_window->feedback, format,
DRM_FORMAT_MOD_INVALID, TRUE);
DebugF("XWAYLAND: Window 0x%x can%s get implicit scanout support\n",
- xwl_window->toplevel->drawable.id,
+ xwl_window->surface_window->drawable.id,
xwl_window->has_implicit_scanout_support ? "" : "not");
/* If the linux-dmabuf v4 per-surface feedback changed, make sure the
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 1198ca16b..745a9ed38 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -412,7 +412,7 @@ PixmapPtr
xwl_glamor_create_pixmap_for_window(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- WindowPtr window = xwl_window->toplevel;
+ WindowPtr window = xwl_window->surface_window;
unsigned border_width = 2 * window->borderWidth;
if (!xwl_screen->glamor)
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 1ac099da9..9def82fcd 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -785,7 +785,7 @@ xwl_present_check_flip(RRCrtcPtr crtc,
* window's, e.g. because a client redirected this window or one of its
* parents.
*/
- if (screen->GetWindowPixmap(xwl_window->toplevel) != screen->GetWindowPixmap(present_window))
+ if (screen->GetWindowPixmap(xwl_window->surface_window) != screen->GetWindowPixmap(present_window))
return FALSE;
/*
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 701425c08..135ae7b74 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -1110,6 +1110,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
pScreen->ChangeWindowAttributes = xwl_change_window_attributes;
+ xwl_screen->ClipNotify = pScreen->ClipNotify;
+ pScreen->ClipNotify = xwl_clip_notify;
+
xwl_screen->ResizeWindow = pScreen->ResizeWindow;
pScreen->ResizeWindow = xwl_resize_window;
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 2b3bdb29e..9653d82c9 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -68,6 +68,7 @@ struct xwl_screen {
int nokeymap;
int hidpi;
+ ClipNotifyProcPtr ClipNotify;
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
CreateWindowProcPtr CreateWindow;
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index bdae04945..2e8b0859c 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -339,7 +339,7 @@ xwl_window_allocate_pixmap(struct xwl_window *xwl_window)
return window_pixmap;
#endif /* XWL_HAS_GLAMOR */
- window_pixmap = screen->GetWindowPixmap(xwl_window->toplevel);
+ window_pixmap = screen->GetWindowPixmap(xwl_window->surface_window);
return screen->CreatePixmap(screen,
window_pixmap->drawable.width,
window_pixmap->drawable.height,
@@ -358,7 +358,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
if (!new_window_pixmap)
return;
- window = xwl_window->toplevel;
+ window = xwl_window->surface_window;
screen = window->drawable.pScreen;
window_pixmap = screen->GetWindowPixmap(window);
copy_pixmap_area(window_pixmap,
@@ -366,7 +366,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
0, 0,
window_pixmap->drawable.width,
window_pixmap->drawable.height);
- xwl_window_set_pixmap(xwl_window->toplevel, new_window_pixmap);
+ xwl_window_set_pixmap(xwl_window->surface_window, new_window_pixmap);
screen->DestroyPixmap(window_pixmap);
}
@@ -414,11 +414,12 @@ PixmapPtr
xwl_window_swap_pixmap(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ WindowPtr surface_window = xwl_window->surface_window;
struct xwl_window_buffer *xwl_window_buffer;
PixmapPtr window_pixmap;
Bool implicit_sync = TRUE;
- window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->toplevel);
+ window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (surface_window);
xwl_window_buffer_add_damage_region(xwl_window);
@@ -441,8 +442,8 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
while (nBox--) {
copy_pixmap_area(window_pixmap,
xwl_window_buffer->pixmap,
- pBox->x1 + xwl_window->toplevel->borderWidth,
- pBox->y1 + xwl_window->toplevel->borderWidth,
+ pBox->x1 + surface_window->borderWidth,
+ pBox->y1 + surface_window->borderWidth,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
@@ -451,7 +452,7 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
RegionEmpty(xwl_window_buffer->damage_region);
xorg_list_del(&xwl_window_buffer->link_buffer);
- xwl_window_set_pixmap(xwl_window->toplevel, xwl_window_buffer->pixmap);
+ xwl_window_set_pixmap(surface_window, xwl_window_buffer->pixmap);
/* Can't re-use client pixmap as a window buffer */
if (xwl_is_client_pixmap(window_pixmap)) {
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index e85827b82..11a6b3adc 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -87,7 +87,7 @@ window_get_damage(WindowPtr window)
RegionPtr
xwl_window_get_damage_region(struct xwl_window *xwl_window)
{
- return DamageRegion(window_get_damage(xwl_window->toplevel));
+ return DamageRegion(window_get_damage(xwl_window->surface_window));
}
struct xwl_window *
@@ -135,7 +135,7 @@ xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
DebugF("XWAYLAND: win %d allow_commits = %d (%s)\n",
xwl_window->toplevel->drawable.id, allow, debug_msg);
- damage = window_get_damage(xwl_window->toplevel);
+ damage = window_get_damage(xwl_window->surface_window);
if (allow &&
xorg_list_is_empty(&xwl_window->link_damage) &&
damage &&
@@ -202,7 +202,7 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
if (xorg_list_is_empty(&xwl_window->link_damage))
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
- window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->toplevel);
+ window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->surface_window);
if (xwl_is_client_pixmap(window_pixmap))
xwl_screen->screen->DestroyPixmap(xwl_window_swap_pixmap(xwl_window));
}
@@ -215,18 +215,18 @@ damage_destroy(DamagePtr pDamage, void *data)
static Bool
register_damage(struct xwl_window *xwl_window)
{
- WindowPtr toplevel = xwl_window->toplevel;
+ WindowPtr surface_window = xwl_window->surface_window;
DamagePtr damage;
damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
- FALSE, toplevel->drawable.pScreen, xwl_window);
+ FALSE, surface_window->drawable.pScreen, xwl_window);
if (damage == NULL) {
ErrorF("Failed creating damage\n");
return FALSE;
}
- DamageRegister(&toplevel->drawable, damage);
- dixSetPrivate(&toplevel->devPrivates, &xwl_damage_private_key, damage);
+ DamageRegister(&surface_window->drawable, damage);
+ dixSetPrivate(&surface_window->devPrivates, &xwl_damage_private_key, damage);
return TRUE;
}
@@ -234,17 +234,17 @@ register_damage(struct xwl_window *xwl_window)
static void
unregister_damage(struct xwl_window *xwl_window)
{
- WindowPtr toplevel = xwl_window->toplevel;
+ WindowPtr surface_window = xwl_window->surface_window;
DamagePtr damage;
- damage = dixLookupPrivate(&toplevel->devPrivates, &xwl_damage_private_key);
+ damage = dixLookupPrivate(&surface_window->devPrivates, &xwl_damage_private_key);
if (!damage)
return;
DamageUnregister(damage);
DamageDestroy(damage);
- dixSetPrivate(&toplevel->devPrivates, &xwl_damage_private_key, NULL);
+ dixSetPrivate(&surface_window->devPrivates, &xwl_damage_private_key, NULL);
}
static Bool
@@ -540,15 +540,15 @@ xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window)
Bool
xwl_window_is_toplevel(WindowPtr window)
{
- if (window_is_wm_window(window))
+ if (!window->parent || window_is_wm_window(window))
return FALSE;
/* CSD and override-redirect toplevel windows */
- if (window_get_damage(window))
+ if (!window->parent->parent)
return TRUE;
/* Normal toplevel client windows, reparented to a window-manager window */
- return window->parent && window_is_wm_window(window->parent);
+ return window_is_wm_window(window->parent);
}
static void
@@ -1221,6 +1221,65 @@ err_surf:
return FALSE;
}
+static void
+xwl_window_update_surface_window(struct xwl_window *xwl_window)
+{
+ WindowPtr surface_window = xwl_window->toplevel;
+ ScreenPtr screen = surface_window->drawable.pScreen;
+ PixmapPtr surface_pixmap;
+ DamagePtr window_damage;
+ RegionRec damage_region;
+ WindowPtr window;
+
+ surface_pixmap = screen->GetWindowPixmap(surface_window);
+
+ for (window = surface_window->firstChild; window; window = window->firstChild) {
+ PixmapPtr window_pixmap;
+
+ if (!RegionEqual(&window->winSize, &surface_window->winSize))
+ break;
+
+ /* The surface window must be top-level for its window pixmap */
+ window_pixmap = screen->GetWindowPixmap(window);
+ if (window_pixmap == surface_pixmap)
+ continue;
+
+ surface_pixmap = window_pixmap;
+
+ /* A descendant with alpha channel cannot be the surface window, since
+ * any non-opaque areas need to take the contents of ancestors into
+ * account.
+ */
+ if (window->drawable.depth == 32)
+ continue;
+
+ surface_window = window;
+ }
+
+ if (xwl_window->surface_window == surface_window)
+ return;
+
+ window_damage = window_get_damage(xwl_window->surface_window);
+ if (window_damage) {
+ RegionInit(&damage_region, NullBox, 1);
+ RegionCopy(&damage_region, DamageRegion(window_damage));
+ unregister_damage(xwl_window);
+ }
+
+ if (surface_window->drawable.depth != xwl_window->surface_window->drawable.depth)
+ xwl_window_buffers_dispose(xwl_window);
+
+ xwl_window->surface_window = surface_window;
+ register_damage(xwl_window);
+
+ if (window_damage) {
+ RegionPtr new_region = DamageRegion(window_get_damage(surface_window));
+
+ RegionUnion(new_region, new_region, &damage_region);
+ RegionUninit(&damage_region);
+ }
+}
+
static struct xwl_window *
ensure_surface_for_window(WindowPtr window)
{
@@ -1250,6 +1309,7 @@ ensure_surface_for_window(WindowPtr window)
xwl_window->xwl_screen = xwl_screen;
xwl_window->toplevel = window;
+ xwl_window->surface_window = window;
xwl_window->fractional_scale_numerator = FRACTIONAL_SCALE_DENOMINATOR;
xwl_window->viewport_scale_x = 1.0;
xwl_window->viewport_scale_y = 1.0;
@@ -1290,6 +1350,8 @@ ensure_surface_for_window(WindowPtr window)
xwl_window_buffers_init(xwl_window);
+ xwl_window_update_surface_window(xwl_window);
+
xwl_window_init_allow_commits(xwl_window);
/* When a new window-manager window is realized, then the randr emulation
@@ -1360,7 +1422,7 @@ xwl_realize_window(WindowPtr window)
if (!xwl_window)
return FALSE;
- if (window == xwl_window->toplevel &&
+ if (window == xwl_window->surface_window &&
!window_get_damage(window))
return register_damage(xwl_window);
@@ -1571,6 +1633,22 @@ xwl_change_window_attributes(WindowPtr window, unsigned long mask)
return ret;
}
+void
+xwl_clip_notify(WindowPtr window, int dx, int dy)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ struct xwl_window *xwl_window = xwl_window_from_window(window);
+
+ screen->ClipNotify = xwl_screen->ClipNotify;
+ (*screen->ClipNotify) (window, dx, dy);
+ xwl_screen->ClipNotify = screen->ClipNotify;
+ screen->ClipNotify = xwl_clip_notify;
+
+ if (xwl_window)
+ xwl_window_update_surface_window(xwl_window);
+}
+
void
xwl_resize_window(WindowPtr window,
int x, int y,
@@ -1696,6 +1774,7 @@ static Bool
xwl_window_attach_buffer(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ WindowPtr surface_window = xwl_window->surface_window;
RegionPtr region;
BoxPtr box;
struct wl_buffer *buffer;
@@ -1720,15 +1799,15 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window)
if (RegionNumRects(region) > 256) {
box = RegionExtents(region);
xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->toplevel->borderWidth,
- box->y1 + xwl_window->toplevel->borderWidth,
+ box->x1 + surface_window->borderWidth,
+ box->y1 + surface_window->borderWidth,
box->x2 - box->x1, box->y2 - box->y1);
} else {
box = RegionRects(region);
for (i = 0; i < RegionNumRects(region); i++, box++) {
xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->toplevel->borderWidth,
- box->y1 + xwl_window->toplevel->borderWidth,
+ box->x1 + surface_window->borderWidth,
+ box->y1 + surface_window->borderWidth,
box->x2 - box->x1, box->y2 - box->y1);
}
}
@@ -1745,7 +1824,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
return;
xwl_window_create_frame_callback(xwl_window);
- DamageEmpty(window_get_damage(xwl_window->toplevel));
+ DamageEmpty(window_get_damage(xwl_window->surface_window));
}
Bool
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index 7c75f9b80..fefb4969c 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -66,9 +66,23 @@ struct xwl_window {
/* Top-level window for the Wayland surface:
* - With rootful, the root window itself
* - With rootless, a direct child of the root window
+ * Mainly useful when the top-level window is needed, can also be used for
+ * the X dimensions of the Wayland surface though.
*/
WindowPtr toplevel;
+ /* The window associated with the Wayland surface:
+ * - If the top-level window has descendants which:
+ * - Cover it completely
+ * - Have no alpha channel
+ * - Use a different window pixmap than their parent for storage
+ * then the surface window is the lowest-level such descendant.
+ * - Otherwise it's the top-level window itself.
+ * Mainly useful for code dealing with (buffers for) the Wayland surface,
+ * can also be used for the X dimensions of the Wayland surface though.
+ */
+ WindowPtr surface_window;
+
struct xorg_list link_damage;
struct xorg_list link_window;
struct wl_callback *frame_callback;
@@ -114,6 +128,7 @@ int xwl_window_get_max_output_scale(struct xwl_window *xwl_window);
Bool xwl_realize_window(WindowPtr window);
Bool xwl_unrealize_window(WindowPtr window);
Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask);
+void xwl_clip_notify(WindowPtr window, int dx, int dy);
void xwl_resize_window(WindowPtr window,
int x, int y,
unsigned int width, unsigned int height,
commit db248682b3ff8a39eb29469589e35ecddf008c36
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Tue Apr 9 18:04:07 2024 +0200
xwayland: Pass xwl_window to xwl_glamor_dri3_syncobj_passthrough
Preparation for later changes, no functional change intended.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index b5b0c2a1c..1198ca16b 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -972,13 +972,12 @@ struct xwl_dri3_syncobj
};
void
-xwl_glamor_dri3_syncobj_passthrough(WindowPtr window,
+xwl_glamor_dri3_syncobj_passthrough(struct xwl_window *xwl_window,
struct dri3_syncobj *acquire_syncobj,
struct dri3_syncobj *release_syncobj,
uint64_t acquire_point,
uint64_t release_point)
{
- struct xwl_window *xwl_window = xwl_window_from_window(window);
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
struct xwl_dri3_syncobj *xwl_acquire_syncobj = (struct xwl_dri3_syncobj *)acquire_syncobj;
struct xwl_dri3_syncobj *xwl_release_syncobj = (struct xwl_dri3_syncobj *)release_syncobj;
diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h
index bbf930437..ef312a857 100644
--- a/hw/xwayland/xwayland-glamor.h
+++ b/hw/xwayland/xwayland-glamor.h
@@ -67,7 +67,7 @@ Bool xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen);
int xwl_glamor_get_fence(struct xwl_screen *screen);
void xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence);
struct dri3_syncobj *xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen);
-void xwl_glamor_dri3_syncobj_passthrough(WindowPtr window,
+void xwl_glamor_dri3_syncobj_passthrough(struct xwl_window *xwl_window,
struct dri3_syncobj *acquire_syncobj,
struct dri3_syncobj *release_syncobj,
uint64_t acquire_point,
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 2153ce6fb..1ac099da9 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -882,7 +882,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
#ifdef XWL_HAS_GLAMOR
if (vblank->acquire_syncobj && vblank->release_syncobj) {
if (xwl_window->xwl_screen->explicit_sync) {
- xwl_glamor_dri3_syncobj_passthrough(present_window,
+ xwl_glamor_dri3_syncobj_passthrough(xwl_window,
vblank->acquire_syncobj,
vblank->release_syncobj,
vblank->acquire_point,
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index f66f36169..bdae04945 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -393,7 +393,7 @@ xwl_window_buffers_set_syncpts(struct xwl_window_buffer *xwl_window_buffer)
else
goto fail;
- xwl_glamor_dri3_syncobj_passthrough(xwl_window->toplevel,
+ xwl_glamor_dri3_syncobj_passthrough(xwl_window,
xwl_window_buffer->syncobj,
xwl_window_buffer->syncobj,
acquire_point,
commit d3448f7aad076fb248014cbd59e2c7bb9dd990d3
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 8 18:18:06 2024 +0100
xwayland: Use xwl_window for damage closure
Preparation for later commits, no functional change intended.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index d4e8e81e2..e85827b82 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -192,15 +192,10 @@ xwl_window_update_property(struct xwl_window *xwl_window,
static void
damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
{
- WindowPtr window = data;
- struct xwl_window *xwl_window = xwl_window_get(window);
- struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window = data;
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
PixmapPtr window_pixmap;
- if (!xwl_window)
- return;
-
- xwl_screen = xwl_window->xwl_screen;
if (xwl_screen->ignore_damage)
return;
@@ -218,37 +213,38 @@ damage_destroy(DamagePtr pDamage, void *data)
}
static Bool
-register_damage(WindowPtr window)
+register_damage(struct xwl_window *xwl_window)
{
+ WindowPtr toplevel = xwl_window->toplevel;
DamagePtr damage;
damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
- FALSE, window->drawable.pScreen, window);
+ FALSE, toplevel->drawable.pScreen, xwl_window);
if (damage == NULL) {
ErrorF("Failed creating damage\n");
return FALSE;
}
- DamageRegister(&window->drawable, damage);
-
- dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
+ DamageRegister(&toplevel->drawable, damage);
+ dixSetPrivate(&toplevel->devPrivates, &xwl_damage_private_key, damage);
return TRUE;
}
static void
-unregister_damage(WindowPtr window)
+unregister_damage(struct xwl_window *xwl_window)
{
+ WindowPtr toplevel = xwl_window->toplevel;
DamagePtr damage;
- damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
+ damage = dixLookupPrivate(&toplevel->devPrivates, &xwl_damage_private_key);
if (!damage)
return;
DamageUnregister(damage);
DamageDestroy(damage);
- dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
+ dixSetPrivate(&toplevel->devPrivates, &xwl_damage_private_key, NULL);
}
static Bool
@@ -1366,7 +1362,7 @@ xwl_realize_window(WindowPtr window)
if (window == xwl_window->toplevel &&
!window_get_damage(window))
- return register_damage(window);
+ return register_damage(xwl_window);
return TRUE;
}
@@ -1503,7 +1499,7 @@ xwl_unrealize_window(WindowPtr window)
release_wl_surface_for_window(xwl_window);
xorg_list_del(&xwl_window->link_damage);
xorg_list_del(&xwl_window->link_window);
- unregister_damage(window);
+ unregister_damage(xwl_window);
xwl_window_buffers_dispose(xwl_window);
commit 07f603262700bfe2abcc28f6d7a8e38457d211cc
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 8 18:41:25 2024 +0100
xwayland: Call register_damage depending on ensure_surface_for_window
Preparation for next commit.
This might change behaviour for non-InputOutput top-level windows.
ensure_surface_for_window getting called and returning non-NULL for
those would seem like a pre-existing bug though.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index fdd4b287a..d4e8e81e2 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1360,18 +1360,14 @@ xwl_realize_window(WindowPtr window)
}
}
- if (xwl_screen->rootless ?
- (window->drawable.class == InputOutput &&
- window->parent == window->drawable.pScreen->root) :
- !window->parent) {
- if (!register_damage(window))
- return FALSE;
- }
-
xwl_window = ensure_surface_for_window(window);
if (!xwl_window)
return FALSE;
+ if (window == xwl_window->toplevel &&
+ !window_get_damage(window))
+ return register_damage(window);
+
return TRUE;
}
commit a562d01a184b2619adcf62b2283c8db04f2978a2
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Thu Feb 8 18:41:25 2024 +0100
xwayland: Return struct xwl_window * from ensure_surface_for_window
Preparation for later commits, no functional change intended.
v2:
* Leave register_damage call unchanged in this commit. (Olivier Fourdan)
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 51ea27243..fdd4b287a 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1225,7 +1225,7 @@ err_surf:
return FALSE;
}
-static Bool
+static struct xwl_window *
ensure_surface_for_window(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
@@ -1233,23 +1233,24 @@ ensure_surface_for_window(WindowPtr window)
struct xwl_window *xwl_window;
WindowPtr toplevel;
- if (xwl_window_from_window(window))
- return TRUE;
+ xwl_window = xwl_window_from_window(window);
+ if (xwl_window)
+ return xwl_window;
xwl_screen = xwl_screen_get(screen);
if (xwl_screen->rootless) {
if (window->redirectDraw != RedirectDrawManual)
- return TRUE;
+ return NULL;
}
else {
if (window->parent)
- return TRUE;
+ return NULL;
}
xwl_window = calloc(1, sizeof *xwl_window);
if (xwl_window == NULL)
- return FALSE;
+ return NULL;
xwl_window->xwl_screen = xwl_screen;
xwl_window->toplevel = window;
@@ -1312,11 +1313,11 @@ ensure_surface_for_window(WindowPtr window)
xwl_screen->tearing_control_manager, xwl_window->surface);
}
- return TRUE;
+ return xwl_window;
err:
free(xwl_window);
- return FALSE;
+ return NULL;
}
Bool
@@ -1325,6 +1326,7 @@ xwl_realize_window(WindowPtr window)
ScreenPtr screen = window->drawable.pScreen;
CompScreenPtr comp_screen = GetCompScreen(screen);
struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
Bool ret;
xwl_screen = xwl_screen_get(screen);
@@ -1366,7 +1368,11 @@ xwl_realize_window(WindowPtr window)
return FALSE;
}
- return ensure_surface_for_window(window);
+ xwl_window = ensure_surface_for_window(window);
+ if (!xwl_window)
+ return FALSE;
+
+ return TRUE;
}
static void
@@ -1539,15 +1545,14 @@ xwl_window_set_window_pixmap(WindowPtr window,
if (!RegionNotEmpty(&window->winSize))
return;
- ensure_surface_for_window(window);
+ xwl_window = ensure_surface_for_window(window);
- if (old_pixmap->drawable.width == pixmap->drawable.width &&
- old_pixmap->drawable.height == pixmap->drawable.height)
+ if (!xwl_window ||
+ (old_pixmap->drawable.width == pixmap->drawable.width &&
+ old_pixmap->drawable.height == pixmap->drawable.height))
return;
- xwl_window = xwl_window_get(window);
- if (xwl_window)
- xwl_window_buffers_dispose(xwl_window);
+ xwl_window_buffers_dispose(xwl_window);
}
Bool
commit 972d5af53785eea924aaddf91b1b2d479cbb4add
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Fri Dec 22 16:54:40 2023 +0100
xwayland: Rename xwl_window::window to ::toplevel
It's always the toplevel window, i.e. either the root window or a child
of it.
Preparation for later commits, no functional change.
v2: (Olivier Fourdan)
* Fix debug build.
* Add comment describing ::toplevel.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-dmabuf.c b/hw/xwayland/xwayland-dmabuf.c
index 4897c2708..97c501273 100644
--- a/hw/xwayland/xwayland-dmabuf.c
+++ b/hw/xwayland/xwayland-dmabuf.c
@@ -735,7 +735,7 @@ xwl_window_dmabuf_feedback_done(void *data,
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
{
struct xwl_window *xwl_window = data;
- uint32_t format = wl_drm_format_for_depth(xwl_window->window->drawable.depth);
+ uint32_t format = wl_drm_format_for_depth(xwl_window->toplevel->drawable.depth);
xwl_dmabuf_feedback_done(&xwl_window->feedback, dmabuf_feedback);
@@ -743,7 +743,7 @@ xwl_window_dmabuf_feedback_done(void *data,
xwl_feedback_is_modifier_supported(&xwl_window->feedback, format,
DRM_FORMAT_MOD_INVALID, TRUE);
DebugF("XWAYLAND: Window 0x%x can%s get implicit scanout support\n",
- xwl_window->window->drawable.id,
+ xwl_window->toplevel->drawable.id,
xwl_window->has_implicit_scanout_support ? "" : "not");
/* If the linux-dmabuf v4 per-surface feedback changed, make sure the
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
index 5bfbb3262..b5b0c2a1c 100644
--- a/hw/xwayland/xwayland-glamor-gbm.c
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -412,7 +412,7 @@ PixmapPtr
xwl_glamor_create_pixmap_for_window(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- WindowPtr window = xwl_window->window;
+ WindowPtr window = xwl_window->toplevel;
unsigned border_width = 2 * window->borderWidth;
if (!xwl_screen->glamor)
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 3b3337869..7447de102 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -543,8 +543,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
xwl_seat->pointer_enter_serial = serial;
xwl_seat->focus_window = wl_surface_get_user_data(surface);
- dx = xwl_seat->focus_window->window->drawable.x;
- dy = xwl_seat->focus_window->window->drawable.y;
+ dx = xwl_seat->focus_window->toplevel->drawable.x;
+ dy = xwl_seat->focus_window->toplevel->drawable.y;
/* We just entered a new xwindow, forget about the old last xwindow */
xwl_seat->last_focus_window = NULL;
@@ -660,8 +660,8 @@ dispatch_absolute_motion(struct xwl_seat *xwl_seat)
int flags;
int event_x = wl_fixed_to_int(xwl_seat->pending_pointer_event.x);
int event_y = wl_fixed_to_int(xwl_seat->pending_pointer_event.y);
- int drawable_x = xwl_seat->focus_window->window->drawable.x;
- int drawable_y = xwl_seat->focus_window->window->drawable.y;
+ int drawable_x = xwl_seat->focus_window->toplevel->drawable.x;
+ int drawable_y = xwl_seat->focus_window->toplevel->drawable.y;
int x;
int y;
@@ -1411,8 +1411,8 @@ xwl_touch_send_event(struct xwl_touch *xwl_touch,
double dx, dy, x, y;
ValuatorMask mask;
- dx = xwl_touch->window->window->drawable.x;
- dy = xwl_touch->window->window->drawable.y;
+ dx = xwl_touch->window->toplevel->drawable.x;
+ dy = xwl_touch->window->toplevel->drawable.y;
x = (dx + xwl_touch->x) * 0xFFFF / xwl_screen_get_width(xwl_seat->xwl_screen);
y = (dy + xwl_touch->y) * 0xFFFF / xwl_screen_get_height(xwl_seat->xwl_screen);
@@ -2202,8 +2202,8 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
sx *= xwl_seat->tablet_focus_window->viewport_scale_x;
sy *= xwl_seat->tablet_focus_window->viewport_scale_y;
- dx = xwl_seat->tablet_focus_window->window->drawable.x;
- dy = xwl_seat->tablet_focus_window->window->drawable.y;
+ dx = xwl_seat->tablet_focus_window->toplevel->drawable.x;
+ dy = xwl_seat->tablet_focus_window->toplevel->drawable.y;
xwl_tablet_tool->x = (double) dx + sx;
xwl_tablet_tool->y = (double) dy + sy;
@@ -3193,8 +3193,8 @@ sprite_check_lost_focus(SpritePtr sprite, WindowPtr window)
if (xwl_seat->focus_window == NULL &&
xwl_seat->last_focus_window != NULL &&
- (xwl_seat->last_focus_window->window == window ||
- IsParent(xwl_seat->last_focus_window->window, window)))
+ (xwl_seat->last_focus_window->toplevel == window ||
+ IsParent(xwl_seat->last_focus_window->toplevel, window)))
return TRUE;
return FALSE;
@@ -3257,7 +3257,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
if (!warp_emulator->xwl_seat->focus_window)
return;
- window = warp_emulator->xwl_seat->focus_window->window;
+ window = warp_emulator->xwl_seat->focus_window->toplevel;
if (x >= window->drawable.x ||
y >= window->drawable.y ||
x < (window->drawable.x + window->drawable.width) ||
@@ -3326,7 +3326,7 @@ xwl_pointer_warp_emulator_maybe_lock(struct xwl_pointer_warp_emulator *warp_emul
if (pointer_grab &&
!pointer_grab->ownerEvents &&
sprite &&
- XYToWindow(sprite, x, y) != xwl_seat->focus_window->window)
+ XYToWindow(sprite, x, y) != xwl_seat->focus_window->toplevel)
return;
xwl_pointer_warp_emulator_lock(warp_emulator);
@@ -3364,7 +3364,7 @@ xwl_pointer_warp_emulator_handle_motion(struct xwl_pointer_warp_emulator *warp_e
QueuePointerEvents(xwl_seat->relative_pointer, MotionNotify, 0,
POINTER_RELATIVE, &mask);
- window = xwl_seat->focus_window->window;
+ window = xwl_seat->focus_window->toplevel;
miPointerGetPosition(xwl_seat->pointer, &x, &y);
if (xwl_pointer_warp_emulator_is_locked(warp_emulator) &&
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 04c3033a5..2153ce6fb 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -785,7 +785,7 @@ xwl_present_check_flip(RRCrtcPtr crtc,
* window's, e.g. because a client redirected this window or one of its
* parents.
*/
- if (screen->GetWindowPixmap(xwl_window->window) != screen->GetWindowPixmap(present_window))
+ if (screen->GetWindowPixmap(xwl_window->toplevel) != screen->GetWindowPixmap(present_window))
return FALSE;
/*
@@ -793,7 +793,7 @@ xwl_present_check_flip(RRCrtcPtr crtc,
* dimensions as their xwl_window parent window. For the case of
* different sizes subsurfaces are presumably the way forward.
*/
- if (!RegionEqual(&xwl_window->window->winSize, &present_window->winSize))
+ if (!RegionEqual(&xwl_window->toplevel->winSize, &present_window->winSize))
return FALSE;
return TRUE;
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 42c9a0e20..701425c08 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -305,7 +305,7 @@ xwl_cursor_warped_to(DeviceIntPtr device,
xwl_window = xwl_window_from_window(window);
if (!xwl_window && xwl_seat->focus_window) {
- focus = xwl_seat->focus_window->window;
+ focus = xwl_seat->focus_window->toplevel;
/* Warps on non wl_surface backed Windows are only allowed
* as long as the pointer stays within the focus window.
@@ -339,15 +339,15 @@ find_matching_input_output_window(struct xwl_screen *xwl_screen,
/* When confining happens on InputOnly windows, work out the InputOutput
* window that would be covered by its geometry.
*/
- if (window->drawable.x < xwl_window->window->drawable.x ||
+ if (window->drawable.x < xwl_window->toplevel->drawable.x ||
window->drawable.x + window->drawable.width >
- xwl_window->window->drawable.x + xwl_window->window->drawable.width ||
- window->drawable.y < xwl_window->window->drawable.y ||
+ xwl_window->toplevel->drawable.x + xwl_window->toplevel->drawable.width ||
+ window->drawable.y < xwl_window->toplevel->drawable.y ||
window->drawable.y + window->drawable.height >
- xwl_window->window->drawable.y + xwl_window->window->drawable.height)
+ xwl_window->toplevel->drawable.y + xwl_window->toplevel->drawable.height)
continue;
- if (xwl_window->window->drawable.class == InputOnly)
+ if (xwl_window->toplevel->drawable.class == InputOnly)
continue;
return xwl_window;
diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 042a55fc0..f66f36169 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -339,7 +339,7 @@ xwl_window_allocate_pixmap(struct xwl_window *xwl_window)
return window_pixmap;
#endif /* XWL_HAS_GLAMOR */
- window_pixmap = screen->GetWindowPixmap(xwl_window->window);
+ window_pixmap = screen->GetWindowPixmap(xwl_window->toplevel);
return screen->CreatePixmap(screen,
window_pixmap->drawable.width,
window_pixmap->drawable.height,
@@ -358,7 +358,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
if (!new_window_pixmap)
return;
- window = xwl_window->window;
+ window = xwl_window->toplevel;
screen = window->drawable.pScreen;
window_pixmap = screen->GetWindowPixmap(window);
copy_pixmap_area(window_pixmap,
@@ -366,7 +366,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
0, 0,
window_pixmap->drawable.width,
window_pixmap->drawable.height);
- xwl_window_set_pixmap(xwl_window->window, new_window_pixmap);
+ xwl_window_set_pixmap(xwl_window->toplevel, new_window_pixmap);
screen->DestroyPixmap(window_pixmap);
}
@@ -393,7 +393,7 @@ xwl_window_buffers_set_syncpts(struct xwl_window_buffer *xwl_window_buffer)
else
goto fail;
- xwl_glamor_dri3_syncobj_passthrough(xwl_window->window,
+ xwl_glamor_dri3_syncobj_passthrough(xwl_window->toplevel,
xwl_window_buffer->syncobj,
xwl_window_buffer->syncobj,
acquire_point,
@@ -418,7 +418,7 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
PixmapPtr window_pixmap;
Bool implicit_sync = TRUE;
- window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
+ window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->toplevel);
xwl_window_buffer_add_damage_region(xwl_window);
@@ -441,8 +441,8 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
while (nBox--) {
copy_pixmap_area(window_pixmap,
xwl_window_buffer->pixmap,
- pBox->x1 + xwl_window->window->borderWidth,
- pBox->y1 + xwl_window->window->borderWidth,
+ pBox->x1 + xwl_window->toplevel->borderWidth,
+ pBox->y1 + xwl_window->toplevel->borderWidth,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
@@ -451,7 +451,7 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
RegionEmpty(xwl_window_buffer->damage_region);
xorg_list_del(&xwl_window_buffer->link_buffer);
- xwl_window_set_pixmap(xwl_window->window, xwl_window_buffer->pixmap);
+ xwl_window_set_pixmap(xwl_window->toplevel, xwl_window_buffer->pixmap);
/* Can't re-use client pixmap as a window buffer */
if (xwl_is_client_pixmap(window_pixmap)) {
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 2650e5cdd..51ea27243 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -87,7 +87,7 @@ window_get_damage(WindowPtr window)
RegionPtr
xwl_window_get_damage_region(struct xwl_window *xwl_window)
{
- return DamageRegion(window_get_damage(xwl_window->window));
+ return DamageRegion(window_get_damage(xwl_window->toplevel));
}
struct xwl_window *
@@ -133,9 +133,9 @@ xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
xwl_window->allow_commits = allow;
DebugF("XWAYLAND: win %d allow_commits = %d (%s)\n",
- xwl_window->window->drawable.id, allow, debug_msg);
+ xwl_window->toplevel->drawable.id, allow, debug_msg);
- damage = window_get_damage(xwl_window->window);
+ damage = window_get_damage(xwl_window->toplevel);
if (allow &&
xorg_list_is_empty(&xwl_window->link_damage) &&
damage &&
@@ -207,7 +207,7 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
if (xorg_list_is_empty(&xwl_window->link_damage))
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
- window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->window);
+ window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->toplevel);
if (xwl_is_client_pixmap(window_pixmap))
xwl_screen->screen->DestroyPixmap(xwl_window_swap_pixmap(xwl_window));
}
@@ -447,7 +447,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
if (!xwl_screen->rootless)
return FALSE;
- window = window_get_client_toplevel(xwl_window->window);
+ window = window_get_client_toplevel(xwl_window->toplevel);
if (!window)
return FALSE;
@@ -479,7 +479,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window,
*/
xwl_output = xwl_screen_get_first_output(xwl_screen);
emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner);
- if (xwl_output && xwl_window->window->overrideRedirect &&
+ if (xwl_output && xwl_window->toplevel->overrideRedirect &&
emulated_mode && emulated_mode->from_vidmode &&
drawable->x == 0 && drawable->y == 0 &&
drawable->width == xwl_screen_get_width(xwl_screen) &&
@@ -561,7 +561,7 @@ xwl_window_init_allow_commits(struct xwl_window *xwl_window)
PropertyPtr prop = NULL;
int ret;
- ret = dixLookupProperty(&prop, xwl_window->window,
+ ret = dixLookupProperty(&prop, xwl_window->toplevel,
xwl_window->xwl_screen->allow_commits_prop,
serverClient, DixReadAccess);
if (ret == Success && prop)
@@ -590,7 +590,7 @@ send_window_client_message(struct xwl_window *xwl_window, Atom type_atom, uint64
e.u.u.type = ClientMessage;
e.u.u.detail = 32;
- e.u.clientMessage.window = xwl_window->window->drawable.id;
+ e.u.clientMessage.window = xwl_window->toplevel->drawable.id;
e.u.clientMessage.u.l.type = type_atom;
e.u.clientMessage.u.l.longs0 = serial_lo(value);
e.u.clientMessage.u.l.longs1 = serial_hi(value);
@@ -685,7 +685,7 @@ xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window,
if (!xwl_screen->fullscreen)
return;
- if (xwl_window->window != xwl_screen->screen->root)
+ if (xwl_window->toplevel != xwl_screen->screen->root)
return;
if (xwl_window->wl_output_fullscreen != xwl_output->output)
@@ -1148,7 +1148,7 @@ static Bool
xwl_create_root_surface(struct xwl_window *xwl_window)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- WindowPtr window = xwl_window->window;
+ WindowPtr window = xwl_window->toplevel;
struct wl_region *region;
@@ -1252,7 +1252,7 @@ ensure_surface_for_window(WindowPtr window)
return FALSE;
xwl_window->xwl_screen = xwl_screen;
- xwl_window->window = window;
+ xwl_window->toplevel = window;
xwl_window->fractional_scale_numerator = FRACTIONAL_SCALE_DENOMINATOR;
xwl_window->viewport_scale_x = 1.0;
xwl_window->viewport_scale_y = 1.0;
@@ -1723,15 +1723,15 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window)
if (RegionNumRects(region) > 256) {
box = RegionExtents(region);
xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->window->borderWidth,
- box->y1 + xwl_window->window->borderWidth,
+ box->x1 + xwl_window->toplevel->borderWidth,
+ box->y1 + xwl_window->toplevel->borderWidth,
box->x2 - box->x1, box->y2 - box->y1);
} else {
box = RegionRects(region);
for (i = 0; i < RegionNumRects(region); i++, box++) {
xwl_surface_damage(xwl_screen, xwl_window->surface,
- box->x1 + xwl_window->window->borderWidth,
- box->y1 + xwl_window->window->borderWidth,
+ box->x1 + xwl_window->toplevel->borderWidth,
+ box->y1 + xwl_window->toplevel->borderWidth,
box->x2 - box->x1, box->y2 - box->y1);
}
}
@@ -1748,7 +1748,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
return;
xwl_window_create_frame_callback(xwl_window);
- DamageEmpty(window_get_damage(xwl_window->window));
+ DamageEmpty(window_get_damage(xwl_window->toplevel));
}
Bool
diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h
index a00284fde..7c75f9b80 100644
--- a/hw/xwayland/xwayland-window.h
+++ b/hw/xwayland/xwayland-window.h
@@ -62,7 +62,13 @@ struct xwl_window {
int surface_scale;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
- WindowPtr window;
+
+ /* Top-level window for the Wayland surface:
+ * - With rootful, the root window itself
+ * - With rootless, a direct child of the root window
+ */
+ WindowPtr toplevel;
+
struct xorg_list link_damage;
struct xorg_list link_window;
struct wl_callback *frame_callback;
commit 59a0259152a34801736548cb137b6264b283ea8a
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Tue Mar 12 10:51:25 2024 +0100
xwayland: Use xwl_window for tracking focus/touch
Slightly simpler, and might work better in some cases when X windows
get reparented.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 3c546057d..3b3337869 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -547,7 +547,7 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
dy = xwl_seat->focus_window->window->drawable.y;
/* We just entered a new xwindow, forget about the old last xwindow */
- xwl_seat->last_xwindow = NullWindow;
+ xwl_seat->last_focus_window = NULL;
master = GetMaster(dev, POINTER_OR_FLOAT);
(*pScreen->SetCursorPosition) (dev, pScreen, dx + sx, dy + sy, TRUE);
@@ -615,7 +615,7 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
* in sprite_check_lost_focus()
*/
if (xwl_seat->focus_window) {
- xwl_seat->last_xwindow = xwl_seat->focus_window->window;
+ xwl_seat->last_focus_window = xwl_seat->focus_window;
xwl_seat->focus_window = NULL;
focus_lost = TRUE;
}
@@ -3192,8 +3192,9 @@ sprite_check_lost_focus(SpritePtr sprite, WindowPtr window)
return TRUE;
if (xwl_seat->focus_window == NULL &&
- xwl_seat->last_xwindow != NullWindow &&
- (IsParent(xwl_seat->last_xwindow, window) || xwl_seat->last_xwindow == window))
+ xwl_seat->last_focus_window != NULL &&
+ (xwl_seat->last_focus_window->window == window ||
+ IsParent(xwl_seat->last_focus_window->window, window)))
return TRUE;
return FALSE;
@@ -3227,13 +3228,13 @@ xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
}
void
-xwl_seat_clear_touch(struct xwl_seat *xwl_seat, WindowPtr window)
+xwl_seat_clear_touch(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window)
{
struct xwl_touch *xwl_touch, *next_xwl_touch;
xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
&xwl_seat->touches, link_touch) {
- if (xwl_touch->window->window == window) {
+ if (xwl_touch->window == xwl_window) {
xorg_list_del(&xwl_touch->link_touch);
free(xwl_touch);
}
diff --git a/hw/xwayland/xwayland-input.h b/hw/xwayland/xwayland-input.h
index 2e686f945..d40bca08a 100644
--- a/hw/xwayland/xwayland-input.h
+++ b/hw/xwayland/xwayland-input.h
@@ -81,7 +81,7 @@ struct xwl_seat {
OsTimerPtr x_cursor_timer;
CursorPtr pending_x_cursor;
struct xwl_cursor cursor;
- WindowPtr last_xwindow;
+ struct xwl_window *last_focus_window;
uint32_t pointer_gesture_swipe_fingers;
uint32_t pointer_gesture_pinch_fingers;
@@ -195,7 +195,7 @@ void xwl_seat_leave_kbd(struct xwl_seat *xwl_seat);
void xwl_seat_destroy(struct xwl_seat *xwl_seat);
-void xwl_seat_clear_touch(struct xwl_seat *xwl_seat, WindowPtr window);
+void xwl_seat_clear_touch(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window);
void xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat,
struct xwl_window *xwl_window,
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index a8731f4dd..2650e5cdd 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1452,23 +1452,6 @@ xwl_unrealize_window(WindowPtr window)
xwl_screen = xwl_screen_get(screen);
- xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
- if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
- xwl_seat->focus_window = NULL;
- if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
- xwl_seat->tablet_focus_window = NULL;
- if (xwl_seat->last_xwindow == window)
- xwl_seat->last_xwindow = NullWindow;
- if (xwl_seat->cursor_confinement_window &&
- xwl_seat->cursor_confinement_window->window == window)
- xwl_seat_unconfine_pointer(xwl_seat);
- if (xwl_seat->pointer_warp_emulator &&
- xwl_seat->pointer_warp_emulator->locked_window &&
- xwl_seat->pointer_warp_emulator->locked_window->window == window)
- xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
- xwl_seat_clear_touch(xwl_seat, window);
- }
-
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
@@ -1480,6 +1463,21 @@ xwl_unrealize_window(WindowPtr window)
if (!xwl_window)
return ret;
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ if (xwl_seat->focus_window == xwl_window)
+ xwl_seat->focus_window = NULL;
+ if (xwl_seat->tablet_focus_window == xwl_window)
+ xwl_seat->tablet_focus_window = NULL;
+ if (xwl_seat->last_focus_window == xwl_window)
+ xwl_seat->last_focus_window = NULL;
+ if (xwl_seat->cursor_confinement_window == xwl_window)
+ xwl_seat_unconfine_pointer(xwl_seat);
+ if (xwl_seat->pointer_warp_emulator &&
+ xwl_seat->pointer_warp_emulator->locked_window == xwl_window)
+ xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
+ xwl_seat_clear_touch(xwl_seat, xwl_window);
+ }
+
if (xwl_window_has_viewport_enabled(xwl_window))
xwl_window_disable_viewport(xwl_window);
#ifdef XWL_HAS_GLAMOR
More information about the xorg-commit
mailing list