Recently, I've found that in order to obey _NET_WM_SYNC_REQUEST events
use presentation at the same time in a reasonable fashion, one must be
able to determine whether or not the compositing manager has actually
redirected the window.  Polling with an error trap and
XCompositeRedirectWindow is horribly inefficient, and there is no other
way for a client to be notified when redirection has changed.

These additions to the Composite extension constitute a minor revision
of that extension, and provide a mechanism for clients to listen to
redirection changes on a given window.  The patches consist of additions
to xorgproto defining the new version of the extension, an
implementation in the X.Org server, and stubs in libXcomposite.

Since I've totally lost track of how X server development works today,
I've copied in the maintainer of libXcomposite, as this list does not
seem to get much attention.  I hope that isn't a problem.

If these changes look good, I'd like for them to be installed.  If
they're not, please tell me why, and I will try my best to fix them.

Thanks in advance.

>From 8c72d0297c1993cb2f8f121cd5bc2f5d7702bfd9 Mon Sep 17 00:00:00 2001
From: Po Lu <luang...@yahoo.com>
Date: Wed, 19 Oct 2022 15:43:38 +0800
Subject: [PATCH xorgproto] Add composite redirection notification events

Applications may want to monitor whether or not their windows are
redirected, in order to decide whether or not to wait for protocols
such as _NET_WM_FRAME_DRAWN when the compositor can choose to
unredirect them.  This update to the Composite protocol allows
applications to select for events that are emitted upon changes to the
redirection state of arbitrary windows, and to query their state.
---
 compositeproto.pc.in                    |   2 +-
 compositeproto.txt                      | 145 ++++++++++++++++++++++++
 configure.ac                            |   2 +-
 include/X11/extensions/composite.h      |  25 +++-
 include/X11/extensions/compositeproto.h |  77 +++++++++++++
 meson.build                             |   2 +-
 6 files changed, 247 insertions(+), 6 deletions(-)

diff --git a/compositeproto.pc.in b/compositeproto.pc.in
index 91f2422..f053a3a 100644
--- a/compositeproto.pc.in
+++ b/compositeproto.pc.in
@@ -3,5 +3,5 @@ includedir=@includedir@
 
 Name: CompositeExt
 Description: Composite extension headers
-Version: 0.4.2
+Version: 0.5.0
 Cflags: -I${includedir}
diff --git a/compositeproto.txt b/compositeproto.txt
index c1a7878..febdde3 100644
--- a/compositeproto.txt
+++ b/compositeproto.txt
@@ -303,3 +303,148 @@ operations other than QueryVersion.
     Composite Overlay Window on the screen specified by the 
     argument 'window'. A screen's Composite Overlay Window is 
     unmapped when there are no longer any clients using it.
+
+12. Composite Input (0.5)
+
+Applications may wish to monitor whether or not their windows are redirected.
+The CompositeSelectInput request paried with the RedirectNotify event allows
+monitoring whether or not a window is redirected, and why it was redirected or
+unredirected.
+
+12.1 Types
+
+     COMPOSITEEVENT			{ RedirectNotify,
+     					  RedirectStateNotify, }
+     REDIRECTREASON			{ WindowRedirected,
+     					  ParentRedirected,
+					  ChildCreated,
+					  ChildReparented, }
+
+12.2 Events
+
+RedirectNotify
+
+	reason:				REDIRECTREASON
+	update:				SETofUPDATETYPE or Unredirected
+	window:				Window
+	timestamp:			Timestamp
+
+	This event is emitted when a client has selected for RedirectNotify
+	events on a window through the CompositeSelectInput request, and the
+	storage for its contents may have changed.
+
+        If 'type' is Unredirected, then the window contents are no longer
+	directed to off-screen storage.
+
+	Otherwise, 'type' is a mask containing the update modes given to all
+	RedirectWindow or RedirectSubwindows requests that are currently causing
+	the window contents to be redirected.  'reason' specifies why the event
+	was sent, and has the following meanings:
+
+		WindowRedirected
+
+			The window may have been redirected or unredirected as
+			the result of being specified as the 'window' argument
+			to a RedirectWindow, UnredirectWindow,
+			UnredirectSubwindows, or RedirectSubwindows request, or
+			its equivalent, such as client destruction.
+
+		ParentRedirected
+
+			The window may have been redirected or unredirected as
+			the result of being a child of the 'window' argument to
+			a RedirectSubwindows or UnredirectSubwindows request at
+			the time the request was made, or its equivalent, such
+			as client destruction.
+
+		ChildCreated
+
+			The window was redirected as the result of being created
+			as a child of the 'window' argument to a
+			RedirectSubwindows request, after that request was made.
+
+		ChildReparented
+
+			The window was redirected or unredirected as a result of
+			being reparented to or away from the 'window' argument
+			of a RedirectSubwindows request, either by a
+			ReparentWindow request or save-set processing.
+
+	No event is emitted if the window was unredirected as a result of being
+	destroyed.  If 'reason' is ChildCreated or ChildReparented, this event
+	is emitted after any CreateNotify or ReparentNotify events generated as
+	a result of the window creation or reparenting that caused the window to
+	be redirected.
+
+	If a window is reparented from one window that has been passed to a
+	CompositeRedirectSubwindows request to another, then two events will be
+	generated: one event will be generated as if the window may have been
+	unredirected as a result of the reparent, and another as if the window
+	may have been redirected as a result of the reparent.  Both events will
+	be emitted after any ReparentNotify event generated as a result of the
+	reparenting.
+
+	'timestamp' is the server time at which the event was generated.
+
+RedirectStateNotify
+
+	update:			SETofUPDATETYPE or Unredirected
+	window:			Window
+	timestamp:		Timestamp
+
+	This event is emitted in response to a CompositeGetRedirectedEvent
+	request.  'window' is the window argument to the request, 'timestamp' is
+	the current server time, and 'update' is a mask of all update modes that
+	have been specified in prior RedirectWindow and RedirectSubwindows
+	request that are currently causing the 'window' to be redirected, or
+	Unredirected if the window is not currently redirected.
+
+12.3 Requests
+
+    CompositeSelectInput
+
+		window:				Window
+		events:				SETofCOMPOSITEEVENT
+
+		errors: Window, Value, Match
+
+	Select for events to be delivered to the window when the window is
+	redirected or un-redirected.  
+
+	If the given window is not valid, a Window error is generated.  If
+	'events' contains events that are not listed in the definition of
+	COMPOSITEEVENT, a Value error is generated.  If 'window' is the root
+	window of a screen, a Match error is generated.
+
+    CompositeQueryRedirected
+
+		id:				Window
+
+		->
+
+		redirected:			SETofUPDATETYPE or Unredirected
+
+		errors: Window, Match
+
+	Obtain whether or not the given window is redirected.  The reply is a
+	mask of all update modes that have been specified in prior
+	RedirectWindow and RedirectSubwindows request that are currently causing
+	the 'window' to be redirected, or Unredirected if the window is not
+	currently redirected.
+
+	If the given window is not valid, a Window error is generated.  If it is
+	the root window of a screen, a Match error is generated.
+
+    CompositeGetRedirectedEvent
+
+		id:				Window
+
+		errors: Window, Match
+
+	Request the delivery of a RedirectStateNotify event to the current
+	client for the given window.  The client need not select for the
+	generated event with the CompositeSelectInput request, but if it does,
+	it will receive events requested by other clients as well.
+
+	If the given window is not valid, a Window error is generated.  If it is
+	the root window of a screen, a Match error is generated.
diff --git a/configure.ac b/configure.ac
index 87334ad..aba9ba9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@ dnl Process this file with autoconf to create configure.
 
 AC_PREREQ([2.60])
 # keep version in sync with meson.build
-AC_INIT([xorgproto], [2022.2],
+AC_INIT([xorgproto], [2022.10],
         [https://gitlab.freedesktop.org/xorg/proto/xorgproto/issues])
 AM_INIT_AUTOMAKE([foreign dist-xz])
 
diff --git a/include/X11/extensions/composite.h b/include/X11/extensions/composite.h
index e460118..39121a3 100644
--- a/include/X11/extensions/composite.h
+++ b/include/X11/extensions/composite.h
@@ -49,11 +49,17 @@
 
 #define COMPOSITE_NAME				"Composite"
 #define COMPOSITE_MAJOR				0
-#define COMPOSITE_MINOR				4
+#define COMPOSITE_MINOR				5
 
 #define CompositeRedirectAutomatic		0
 #define CompositeRedirectManual			1
 
+#define CompositeRedirectAutomaticMask		1
+#define CompositeRedirectManualMask		2
+#define CompositeUnredirected                   0
+
+#define CompositeUpdateTypeToMask(update_type)  (1 << (update_type))
+
 #define X_CompositeQueryVersion			0
 #define X_CompositeRedirectWindow		1
 #define X_CompositeRedirectSubwindows		2
@@ -63,9 +69,22 @@
 #define X_CompositeNameWindowPixmap		6
 #define X_CompositeGetOverlayWindow             7
 #define X_CompositeReleaseOverlayWindow         8
+#define X_CompositeSelectInput                  9
+#define X_CompositeQueryRedirected              10
+#define X_CompositeGetRedirectedEvent           11
+
+#define CompositeNumberRequests	    (X_CompositeGetRedirectedEvent + 1)
+
+#define CompositeRedirectNotify               0
+#define CompositeRedirectStateNotify          1
+#define CompositeRedirectNotifyMask           1
+#define CompositeRedirectStateNotifyMask      2
 
-#define CompositeNumberRequests	    (X_CompositeReleaseOverlayWindow + 1)
+#define CompositeNumberEvents	    (CompositeRedirectStateNotify + 1)
 
-#define CompositeNumberEvents			0
+#define CompositeWindowRedirected               0
+#define CompositeParentRedirected               1
+#define CompositeChildCreated                   2
+#define CompositeChildReparented                3
 
 #endif /* _COMPOSITE_H_ */
diff --git a/include/X11/extensions/compositeproto.h b/include/X11/extensions/compositeproto.h
index b63f9cc..3435ead 100644
--- a/include/X11/extensions/compositeproto.h
+++ b/include/X11/extensions/compositeproto.h
@@ -51,6 +51,7 @@
 #define Window CARD32
 #define Region CARD32
 #define Pixmap CARD32
+#define Time CARD32
 
 /*
  * requests and replies
@@ -185,8 +186,84 @@ typedef struct {
 
 #define sz_xCompositeReleaseOverlayWindowReq sizeof(xCompositeReleaseOverlayWindowReq)
 
+/* Version 0.5 additions.  */
+
+typedef struct {
+    CARD8   type;
+    BYTE    pad;
+    CARD16  sequenceNumber;
+    CARD32  reason;
+    CARD32  update;
+    Window  window;
+    Time    timestamp;
+    CARD32  pad1;
+    CARD32  pad2;
+    CARD32  pad3;
+} xCompositeRedirectNotifyEvent;
+
+#define sz_xCompositeRedirectNotifyEvent sizeof(xCompositeRedirectNotifyEvent)
+
+typedef struct {
+    CARD8  type;
+    BYTE   pad;
+    CARD16 sequenceNumber;
+    Window window;
+    Time   timestamp;
+    CARD32 update;
+    CARD32 pad1;
+    CARD32 pad2;
+    CARD32 pad3;
+    CARD32 pad4;
+} xCompositeRedirectStateNotifyEvent;
+
+#define sz_xCompositeRedirectStateNotifyEvent sizeof(xCompositeRedirectStateNotifyEvent)
+
+typedef struct {
+    CARD8   reqType;
+    CARD8   compositeReqType;
+    CARD16  length;
+    Window  window;
+    CARD32  events;
+} xCompositeSelectInputReq;
+
+#define sz_xCompositeSelectInputReq sizeof(xCompositeSelectInputReq)
+
+typedef struct {
+    CARD8   reqType;
+    CARD8   compositeReqType;
+    CARD16  length;
+    Window  id;
+} xCompositeQueryRedirectedReq;
+
+#define sz_xCompositeQueryRedirectedReq sizeof(xCompositeQueryRedirectedReq)
+
+typedef struct {
+    BYTE    type;   /* X_Reply */
+    BYTE    pad;
+    CARD16  sequenceNumber;
+    CARD32  length;
+    CARD32  update;
+    CARD32  pad1;
+    CARD32  pad2;
+    CARD32  pad3;
+    CARD32  pad4;
+    CARD32  pad5;
+} xCompositeQueryRedirectedReply;
+
+#define sz_xCompsiteQueryRedirectedReply sizeof(xCompositeQueryRedirectedReply)
+
+typedef struct {
+    CARD8   reqType;
+    CARD8   compositeReqType;
+    CARD16  length;
+    Window  id;
+} xCompositeGetRedirectedEventReq;
+
+#define sz_xCompositeGetRedirectedEventReq sizeof(xCompositeGetRedirectedEventReq)
+
 #undef Window
 #undef Region
 #undef Pixmap
+#undef Time
 
 #endif /* _COMPOSITEPROTO_H_ */
diff --git a/meson.build b/meson.build
index 6bd7110..09dbeda 100644
--- a/meson.build
+++ b/meson.build
@@ -19,7 +19,7 @@
 # SOFTWARE.
 
 # keep version in sync with configure.ac
-project('xorgproto', 'c', license : 'MIT', version : '2022.2')
+project('xorgproto', 'c', license : 'MIT', version : '2022.10')
 cc = meson.get_compiler('c')
 
 pcs = [
-- 
2.37.3

>From 5c2c8ada35ed843d527f492d1bba64f3af1c0e0d Mon Sep 17 00:00:00 2001
From: Po Lu <luang...@yahoo.com>
Date: Wed, 19 Oct 2022 15:46:05 +0800
Subject: [PATCH libXcomposite] Implement wrappers for version 0.5 of the
 Composite extension

---
 configure.ac                         |   2 +-
 include/X11/extensions/Xcomposite.h  |  32 ++++-
 man/Makefile.am                      |   5 +-
 man/XCompositeGetRedirectedEvent.man |   1 +
 man/XCompositeQueryRedirected.man    |   1 +
 man/XCompositeSelectInput.man        |   1 +
 man/Xcomposite.xml                   |  29 +++++
 src/Xcomposite.c                     | 175 +++++++++++++++++++++++++++
 8 files changed, 243 insertions(+), 3 deletions(-)
 create mode 100644 man/XCompositeGetRedirectedEvent.man
 create mode 100644 man/XCompositeQueryRedirected.man
 create mode 100644 man/XCompositeSelectInput.man

diff --git a/configure.ac b/configure.ac
index d62be07..99f3e40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@ AC_PREREQ([2.60])
 # that 'revision' number appears in Xcomposite.h and has to be manually
 # synchronized.
 #
-AC_INIT(libXcomposite, [0.4.5],
+AC_INIT(libXcomposite, [0.5.0],
 	[https://gitlab.freedesktop.org/xorg/lib/libXcomposite/issues], [libXcomposite])
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_HEADERS([config.h])
diff --git a/include/X11/extensions/Xcomposite.h b/include/X11/extensions/Xcomposite.h
index 9e4fcb1..53447fb 100644
--- a/include/X11/extensions/Xcomposite.h
+++ b/include/X11/extensions/Xcomposite.h
@@ -55,9 +55,30 @@
  */
 #define XCOMPOSITE_MAJOR	COMPOSITE_MAJOR
 #define XCOMPOSITE_MINOR	COMPOSITE_MINOR
-#define XCOMPOSITE_REVISION	2
+#define XCOMPOSITE_REVISION	0
 #define XCOMPOSITE_VERSION	((XCOMPOSITE_MAJOR * 10000) + (XCOMPOSITE_MINOR * 100) + (XCOMPOSITE_REVISION))
 
+typedef struct {
+    int type;
+    unsigned long serial;
+    Bool send_event;
+    Display *display;
+    Window window;
+    Time timestamp;
+    int reason;
+    int update;
+} XCompositeRedirectNotifyEvent;
+
+typedef struct {
+    int type;
+    unsigned long serial;
+    Bool send_event;
+    Display *display;
+    Window window;
+    Time timestamp;
+    int update;
+} XCompositeRedirectStateNotifyEvent;
+
 _XFUNCPROTOBEGIN
 
 Bool XCompositeQueryExtension (Display *dpy,
@@ -94,6 +115,15 @@ XCompositeGetOverlayWindow (Display *dpy, Window window);
 void
 XCompositeReleaseOverlayWindow (Display *dpy, Window window);
 
+void
+XCompositeSelectInput (Display *dpy, Window window, long events);
+
+Status
+XCompositeQueryRedirected (Display *display, Window window, long *);
+
+void
+XCompositeGetRedirectedEvent (Display *display, Window window);
+
 _XFUNCPROTOEND
 
 #endif /* _XCOMPOSITE_H_ */
diff --git a/man/Makefile.am b/man/Makefile.am
index cbed2eb..942b09d 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -16,7 +16,10 @@ Xcomposite_shadows =	 			\
 	XCompositeCreateRegionFromBorderClip	\
 	XCompositeNameWindowPixmap		\
 	XCompositeGetOverlayWindow		\
-	XCompositeReleaseOverlayWindow
+	XCompositeReleaseOverlayWindow		\
+	XCompositeSelectInput			\
+	XCompositeQueryRedirected		\
+	XCompositeGetRedirectedEvent
 
 if INSTALL_MANPAGES
 libman_DATA = $(libman_PRE:man=@LIB_MAN_SUFFIX@)
diff --git a/man/XCompositeGetRedirectedEvent.man b/man/XCompositeGetRedirectedEvent.man
new file mode 100644
index 0000000..3d50287
--- /dev/null
+++ b/man/XCompositeGetRedirectedEvent.man
@@ -0,0 +1 @@
+.so man3/Xcomposite.3
diff --git a/man/XCompositeQueryRedirected.man b/man/XCompositeQueryRedirected.man
new file mode 100644
index 0000000..3d50287
--- /dev/null
+++ b/man/XCompositeQueryRedirected.man
@@ -0,0 +1 @@
+.so man3/Xcomposite.3
diff --git a/man/XCompositeSelectInput.man b/man/XCompositeSelectInput.man
new file mode 100644
index 0000000..3d50287
--- /dev/null
+++ b/man/XCompositeSelectInput.man
@@ -0,0 +1 @@
+.so man3/Xcomposite.3
diff --git a/man/Xcomposite.xml b/man/Xcomposite.xml
index 9ba9ec5..cc46a00 100644
--- a/man/Xcomposite.xml
+++ b/man/Xcomposite.xml
@@ -117,6 +117,23 @@
    <paramdef>Display *<parameter>dpy</parameter></paramdef>
    <paramdef>Window <parameter>window</parameter></paramdef>
   </funcprototype>
+  <funcprototype>
+    <funcdef>void <function>XCompositeSelectInput</function></funcdef>
+    <paramdef>Display *<parameter>dpy</parameter></paramdef>
+    <paramdef>Window <parameter>window</parameter></paramdef>
+    <paramdef>long <parameter>events</parameter></paramdef>
+  </funcprototype>
+  <funcprototype>
+    <funcdef>Status <function>XCompositeQueryRedirected</function></funcdef>
+    <paramdef>Display *<parameter>dpy</parameter></paramdef>
+    <paramdef>Window <parameter>window</parameter></paramdef>
+    <paramdef>long *<parameter>update</parameter></paramdef>
+  </funcprototype>
+  <funcprototype>
+    <funcdef>void <function>XCompositeGetRedirectEvent</function></funcdef>
+    <paramdef>Display *<parameter>dpy</parameter></paramdef>
+    <paramdef>Window <parameter>window</parameter></paramdef>
+  </funcprototype>
  </funcsynopsis></refsynopsisdiv>
 
 <refsect1><title>Description</title>
@@ -394,6 +411,18 @@ contents of all descendants.
     Extension for <function>XCompositeReleaseOverlayWindow</function>.
    </para></listitem>
   </varlistentry>
+  <varlistentry>
+    <term><function>XCompositeSelectInput</function></term>
+    <listitem><para>
+      This request selects for some kinds of events to be delivered to
+      the window specified in the <parameter>window</parameter>
+      window when it is redirected or un-redirected.
+    </para>
+    <para>
+      The X server must support at least version 0.5 of the Composite
+      Extension for <function>XCompositeSelectInput</function>.
+    </para></listitem>
+  </varlistentry>
  </variablelist>
 </para>
 </refsect1>
diff --git a/src/Xcomposite.c b/src/Xcomposite.c
index b107475..48c0220 100644
--- a/src/Xcomposite.c
+++ b/src/Xcomposite.c
@@ -93,6 +93,105 @@ XCompositeCloseDisplay (Display *dpy, XExtCodes *codes)
     return XCompositeExtRemoveDisplay (&XCompositeExtensionInfo, dpy);
 }
 
+
+static Bool
+XCompositeWireToEvent (Display *dpy, XEvent *event, xEvent *wire)
+{
+    XCompositeExtDisplayInfo		*info;
+    XCompositeRedirectNotifyEvent	*event_out;
+    xCompositeRedirectNotifyEvent	*wire_in;
+    XCompositeRedirectStateNotifyEvent	*event_out_1;
+    xCompositeRedirectStateNotifyEvent	*wire_in_1;
+
+    info = XCompositeFindDisplay (dpy);
+    XCompositeCheckExtension (dpy, info, False);
+
+    switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
+    {
+    case CompositeRedirectNotify:
+	event_out = (XCompositeRedirectNotifyEvent *) event;
+	wire_in = (xCompositeRedirectNotifyEvent *) wire;
+
+	event_out->type = wire_in->type & 0x7F;
+	event_out->serial = _XSetLastRequestRead (dpy,
+						  (xGenericReply *) wire);
+	event_out->send_event = (wire_in->type & 0x80) != 0;
+	event_out->display = dpy;
+	event_out->window = wire_in->window;
+	event_out->timestamp = wire_in->timestamp;
+	event_out->reason = wire_in->reason;
+	event_out->update = wire_in->update;
+
+	return True;
+
+    case CompositeRedirectStateNotify:
+	event_out_1 = (XCompositeRedirectStateNotifyEvent *) event;
+	wire_in_1 = (xCompositeRedirectStateNotifyEvent *) wire;
+
+	event_out_1->type = wire_in_1->type & 0x7F;
+	event_out_1->serial = _XSetLastRequestRead (dpy,
+						    (xGenericReply *) wire);
+	event_out_1->send_event = (wire_in_1->type & 0x80) != 0;
+	event_out_1->display = dpy;
+	event_out_1->window = wire_in_1->window;
+	event_out_1->timestamp = wire_in_1->timestamp;
+	event_out_1->update = wire_in_1->update;
+
+	return True;
+    }
+
+    return False;
+}
+
+static Status
+XCompositeEventToWire (Display *dpy, XEvent *event, xEvent *wire)
+{
+    XCompositeExtDisplayInfo		*info;
+    XCompositeRedirectNotifyEvent	*event_in;
+    xCompositeRedirectNotifyEvent	*wire_out;
+    XCompositeRedirectStateNotifyEvent	*event_in_1;
+    xCompositeRedirectStateNotifyEvent	*wire_out_1;
+
+    info = XCompositeFindDisplay (dpy);
+    XCompositeCheckExtension (dpyinfo, info, 0);
+
+    switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
+    {
+    case CompositeRedirectNotify:
+	event_in = (XCompositeRedirectNotifyEvent *) event;
+	wire_out = (xCompositeRedirectNotifyEvent *) wire;
+
+	wire_out->type = event_in->type;
+
+	if (event_in->send_event)
+	    wire_out->type |= 0x80;
+
+	wire_out->window = event_in->window;
+	wire_out->timestamp = event_in->timestamp;
+	wire_out->reason = event_in->reason;
+	wire_out->update = event_in->update;
+
+	return 1;
+
+    case CompositeRedirectStateNotify:
+	event_in_1 = (XCompositeRedirectStateNotifyEvent *) event;
+	wire_out_1 = (xCompositeRedirectStateNotifyEvent *) wire;
+
+	wire_out_1->type = event_in_1->type;
+
+	if (event_in_1->send_event)
+	    wire_out_1->type |= 0x80;
+
+	wire_out_1->window = event_in_1->window;
+	wire_out_1->timestamp = event_in_1->timestamp;
+	wire_out_1->update = event_in_1->update;
+
+	return 1;
+    }
+
+    return 0;
+}
+
 /*
  * XCompositeExtAddDisplay - add a display to this extension. (Replaces
  * XextAddDisplay)
@@ -103,6 +202,7 @@ XCompositeExtAddDisplay (XCompositeExtInfo	*extinfo,
 			 const char		*ext_name)
 {
     XCompositeExtDisplayInfo    *info;
+    int				 event_number;
 
     info = (XCompositeExtDisplayInfo *) Xmalloc (sizeof (XCompositeExtDisplayInfo));
     if (!info) return NULL;
@@ -119,6 +219,16 @@ XCompositeExtAddDisplay (XCompositeExtInfo	*extinfo,
 	xCompositeQueryVersionReq	*req;
         XESetCloseDisplay (dpy, info->codes->extension,
                            XCompositeCloseDisplay);
+	/*
+	 * Install event conversion functions.
+	 */
+	for (event_number = info->codes->first_event;
+	     event_number < info->codes->first_event + CompositeNumberEvents;
+	     event_number++)
+	{
+	    XESetWireToEvent (dpy, event_number, XCompositeWireToEvent);
+	    XESetEventToWire (dpy, event_number, XCompositeEventToWire);
+	}
 	/*
 	 * Get the version info
 	 */
@@ -394,3 +504,68 @@ XCompositeReleaseOverlayWindow (Display *dpy, Window window)
     UnlockDisplay (dpy);
     SyncHandle ();
 }
+
+void
+XCompositeSelectInput (Display *dpy, Window window, long events)
+{
+    XCompositeExtDisplayInfo *info;
+    xCompositeSelectInputReq *req;
+
+    info = XCompositeFindDisplay (dpy);
+    XCompositeSimpleCheckExtension (dpy, info);
+    LockDisplay (dpy);
+    GetReq (CompositeSelectInput, req);
+    req->reqType = info->codes->major_opcode;
+    req->compositeReqType = X_CompositeSelectInput;
+    req->window = window;
+    req->events = events;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+}
+
+Status
+XCompositeQueryRedirected (Display *dpy, Window window, long *update)
+{
+    XCompositeExtDisplayInfo		*info;
+    xCompositeQueryRedirectedReq	*req;
+    xCompositeQueryRedirectedReply	reply;
+
+    *update = CompositeUnredirected;
+
+    info = XCompositeFindDisplay (dpy);
+    XCompositeCheckExtension (dpy, info, 0);
+    LockDisplay (dpy);
+    GetReq (CompositeQueryRedirected, req);
+    req->reqType = info->codes->major_opcode;
+    req->compositeReqType = X_CompositeQueryRedirected;
+    req->id = window;
+    if (!_XReply (dpy, (xReply *) &reply, 0, xFalse))
+    {
+	UnlockDisplay (dpy);
+	SyncHandle ();
+	return 0;
+    }
+    UnlockDisplay (dpy);
+    SyncHandle ();
+
+    *update = reply.update;
+    return 1;
+}
+
+void
+XCompositeGetRedirectedEvent (Display *dpy, Window window)
+{
+    XCompositeExtDisplayInfo		*info;
+    xCompositeGetRedirectedEventReq	*req;
+
+    info = XCompositeFindDisplay (dpy);
+    XCompositeSimpleCheckExtension (dpy, info);
+    LockDisplay (dpy);
+    GetReq (CompositeGetRedirectedEvent, req);
+    req->reqType = info->codes->major_opcode;
+    req->compositeReqType = X_CompositeGetRedirectedEvent;
+    req->id = window;
+    UnlockDisplay (dpy);
+    SyncHandle ();
+}
+
-- 
2.37.3

>From 3631d5158e67d557d0602966e296105fa489df1d Mon Sep 17 00:00:00 2001
From: Po Lu <luang...@yahoo.com>
Date: Wed, 19 Oct 2022 15:44:23 +0800
Subject: [PATCH] Implement version 0.5 of the Composite extension

---
 composite/compalloc.c       |  49 ++++-
 composite/compext.c         | 399 +++++++++++++++++++++++++++++++++++-
 composite/compint.h         |  10 +
 composite/compwindow.c      |  10 +-
 include/protocol-versions.h |   2 +-
 meson.build                 |   2 +-
 6 files changed, 459 insertions(+), 13 deletions(-)

diff --git a/composite/compalloc.c b/composite/compalloc.c
index eaabf0d91..f960ee72b 100644
--- a/composite/compalloc.c
+++ b/composite/compalloc.c
@@ -47,6 +47,29 @@
 
 #include "compint.h"
 
+int
+compGetUpdateMask(WindowPtr pWindow)
+{
+    CompWindowPtr pCompWindow;
+    CompClientWindowPtr pCompClientWindow;
+    int mask;
+
+    pCompWindow = GetCompWindow(pWindow);
+
+    if (!pCompWindow)
+        return CompositeUnredirected;
+
+    mask = CompositeUnredirected;
+    for (pCompClientWindow = pCompWindow->clients;
+         pCompClientWindow;
+         pCompClientWindow = pCompClientWindow->next) {
+        if (CLIENT_ID (pCompClientWindow->id) != serverClient->index)
+            mask |= CompositeUpdateTypeToMask(pCompClientWindow->update);
+    }
+
+    return mask;
+}
+
 static Bool
 compScreenUpdate(ClientPtr pClient, void *closure)
 {
@@ -409,6 +432,9 @@ compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
         DamageExtSetCritical(pClient, TRUE);
         pWin->inhibitBGPaint = TRUE;
     }
+    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+        CompositeSendRedirectNotify(pChild, CompositeParentRedirected,
+                                    compGetUpdateMask(pChild));
     return Success;
 }
 
@@ -446,8 +472,11 @@ compFreeClientSubwindows(WindowPtr pWin, XID id)
             /*
              * Unredirect all existing subwindows
              */
-            for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+            for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) {
                 (void) compUnredirectWindow(pClient, pChild, ccw->update);
+                CompositeSendRedirectNotify(pChild, CompositeParentRedirected,
+                                            compGetUpdateMask(pChild));
+            }
 
             free(ccw);
             break;
@@ -499,9 +528,16 @@ compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
         int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)],
                                      pWin, ccw->update);
 
-        if (ret != Success)
+        if (ret != Success) {
+            /* Some windows may still have been redirected, so send
+               the event anyway.  */
+            CompositeSendRedirectNotify(pWin, CompositeChildReparented,
+                                        compGetUpdateMask(pWin));
             return ret;
+        }
     }
+    CompositeSendRedirectNotify(pWin, CompositeChildReparented,
+                                compGetUpdateMask(pWin));
     return Success;
 }
 
@@ -521,9 +557,16 @@ compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
         int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)],
                                        pWin, ccw->update);
 
-        if (ret != Success)
+        if (ret != Success) {
+            /* Some windows may still have been unredirected, so send
+               the event anyway.  */
+            CompositeSendRedirectNotify(pWin, CompositeChildReparented,
+                                        compGetUpdateMask(pWin));
             return ret;
+        }
     }
+    CompositeSendRedirectNotify(pWin, CompositeChildReparented,
+                                compGetUpdateMask(pWin));
     return Success;
 }
 
diff --git a/composite/compext.c b/composite/compext.c
index 34a2a5363..af53328d9 100644
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -51,6 +51,7 @@
 #include "extinit.h"
 
 static CARD8 CompositeReqCode;
+static int CompositeEventBase;
 static DevPrivateKeyRec CompositeClientPrivateKeyRec;
 
 #define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec)
@@ -63,6 +64,88 @@ typedef struct _CompositeClient {
     int minor_version;
 } CompositeClientRec, *CompositeClientPtr;
 
+static RESTYPE CompositeEventType;
+static RESTYPE CompositeClientType;
+
+typedef struct _CompositeEvent *CompositeEventPtr;
+
+typedef struct _CompositeEvent {
+    CompositeEventPtr next, last;
+    CARD32 eventMask;
+    ClientPtr pClient;
+    WindowPtr pWindow;
+    XID clientResource;
+} CompositeEventRec;
+
+#define ALLCOMPOSITEEVENT                                               \
+    (CompositeRedirectNotifyMask | CompositeRedirectStateNotifyMask)
+
+void
+CompositeSendRedirectNotify(WindowPtr pWin, int reason, int update)
+{
+    CompositeEventPtr *pHead, pEvent;
+    int rc;
+    xCompositeRedirectNotifyEvent wire;
+
+    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
+                                 CompositeEventType, serverClient,
+                                 DixReadAccess);
+    if (rc != Success)
+        return;
+
+    UpdateCurrentTimeIf();
+
+    for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+        if (!(pEvent->eventMask & CompositeRedirectNotifyMask))
+            continue;
+
+        memset(&wire, 0, sizeof (xCompositeRedirectNotifyEvent));
+        wire.type = CompositeRedirectNotify + CompositeEventBase;
+        wire.reason = reason;
+        wire.update = update;
+        wire.window = pWin->drawable.id;
+        wire.timestamp = currentTime.milliseconds;
+        WriteEventsToClient(pEvent->pClient, 1, (xEvent *) &wire);
+    }
+}
+
+static void
+CompositeSendRedirectStateNotify(ClientPtr pClient, WindowPtr pWin,
+                                 int update)
+{
+    CompositeEventPtr *pHead, pEvent;
+    int rc;
+    xCompositeRedirectStateNotifyEvent wire;
+
+    UpdateCurrentTimeIf();
+
+    memset(&wire, 0, sizeof (wire));
+    wire.type = CompositeRedirectStateNotify + CompositeEventBase;
+    wire.window = pWin->drawable.id;
+    wire.update = update;
+    wire.timestamp = currentTime.milliseconds;
+    WriteEventsToClient(pClient, 1, (xEvent *) &wire);
+
+    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
+                                 CompositeEventType, serverClient,
+                                 DixReadAccess);
+    if (rc != Success)
+        return;
+
+    for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+        if (!(pEvent->eventMask & CompositeRedirectStateNotifyMask)
+            || pEvent->pClient == pClient)
+            continue;
+
+        memset(&wire, 0, sizeof (wire));
+        wire.type = CompositeRedirectStateNotify + CompositeEventBase;
+        wire.window = pWin->drawable.id;
+        wire.update = update;
+        wire.timestamp = currentTime.milliseconds;
+        WriteEventsToClient(pEvent->pClient, 1, (xEvent *) &wire);
+    }
+}
+
 #define GetCompositeClient(pClient) ((CompositeClientPtr) \
     dixLookupPrivate(&(pClient)->devPrivates, CompositeClientPrivateKey))
 
@@ -141,6 +224,7 @@ static int
 ProcCompositeRedirectWindow(ClientPtr client)
 {
     WindowPtr pWin;
+    int rc;
 
     REQUEST(xCompositeRedirectWindowReq);
 
@@ -148,7 +232,13 @@ ProcCompositeRedirectWindow(ClientPtr client)
     VERIFY_WINDOW(pWin, stuff->window, client,
                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
 
-    return compRedirectWindow(client, pWin, stuff->update);
+    rc = compRedirectWindow(client, pWin, stuff->update);
+
+    if (rc == Success)
+        CompositeSendRedirectNotify(pWin, CompositeWindowRedirected,
+                                    compGetUpdateMask(pWin));
+
+    return rc;
 }
 
 static int
@@ -169,6 +259,7 @@ static int
 ProcCompositeUnredirectWindow(ClientPtr client)
 {
     WindowPtr pWin;
+    int rc;
 
     REQUEST(xCompositeUnredirectWindowReq);
 
@@ -176,7 +267,13 @@ ProcCompositeUnredirectWindow(ClientPtr client)
     VERIFY_WINDOW(pWin, stuff->window, client,
                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
 
-    return compUnredirectWindow(client, pWin, stuff->update);
+    rc = compUnredirectWindow(client, pWin, stuff->update);
+
+    if (rc == Success)
+        CompositeSendRedirectNotify(pWin, CompositeWindowRedirected,
+                                    compGetUpdateMask(pWin));
+
+    return rc;
 }
 
 static int
@@ -354,15 +451,131 @@ ProcCompositeReleaseOverlayWindow(ClientPtr client)
     return Success;
 }
 
+static int
+ProcCompositeSelectInput(ClientPtr client)
+{
+    REQUEST(xCompositeSelectInputReq);
+    WindowPtr pWin;
+    CompositeEventPtr pEvent, pNewEvent, *pHead;
+    XID clientResource;
+    int rc;
+
+    REQUEST_SIZE_MATCH(xCompositeSelectInputReq);
+    VERIFY_WINDOW(pWin, stuff->window, client, DixReceiveAccess);
+
+    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
+                                 CompositeEventType, client, DixWriteAccess);
+    if (rc != Success && rc != BadValue)
+        return rc;
+
+    if (!stuff->events) {
+        /* Delete the existing entry.  */
+        if (pHead) {
+            pNewEvent = NULL;
+            for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+                if (pEvent->pClient == client)
+                    break;
+                pNewEvent = pEvent;
+            }
+            if (pEvent) {
+                FreeResource(pEvent->clientResource, CompositeClientType);
+                if (pNewEvent)
+                    pNewEvent->next = pEvent->next;
+                else
+                    *pHead = pEvent->next;
+                free(pEvent);
+            }
+        }
+    }
+    else {
+        if (stuff->events & ~ALLCOMPOSITEEVENT) {
+            client->errorValue = stuff->events;
+            return BadValue;
+        }
+        if (pHead) {
+            /* Check for existing entry.  */
+            for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+                if (pEvent->pClient == client) {
+                    pEvent->eventMask = stuff->events;
+                    return Success;
+                }
+            }
+        }
+        pNewEvent = malloc(sizeof (CompositeEventRec));
+        if (!pNewEvent)
+            return BadAlloc;
+        pNewEvent->next = NULL;
+        pNewEvent->pClient = client;
+        pNewEvent->pWindow = pWin;
+        clientResource = FakeClientID(client->index);
+        pNewEvent->clientResource = clientResource;
+        if (!AddResource(clientResource, CompositeClientType,
+                         (void *) pNewEvent))
+            return BadAlloc;
+        pNewEvent->eventMask = stuff->events;
+        if (!pHead) {
+            pHead = calloc(1, sizeof(CompositeEventPtr));
+            if (!pHead ||
+                !AddResource (pWin->drawable.id, CompositeEventType,
+                              (void *) pHead)) {
+                FreeResource (clientResource, RT_NONE);
+                return BadAlloc;
+            }
+        }
+        pNewEvent->next = *pHead;
+        *pHead = pNewEvent;
+    }
+
+    return Success;
+}
+
+static int
+ProcCompositeQueryRedirected(ClientPtr client)
+{
+    REQUEST(xCompositeQueryRedirectedReq);
+    WindowPtr pWin;
+    xCompositeQueryRedirectedReply rep;
+
+    REQUEST_SIZE_MATCH(xCompositeQueryRedirectedReq);
+    VERIFY_WINDOW(pWin, stuff->id, client, DixGetAttrAccess);
+
+    memset(&rep, 0, sizeof(rep));
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.update = compGetUpdateMask(pWin);
+    WriteToClient(client, sizeof(rep), &rep);
+    return Success;
+}
+
+static int
+ProcCompositeGetRedirectedEvent(ClientPtr client)
+{
+    REQUEST(xCompositeGetRedirectedEventReq);
+    WindowPtr pWin;
+
+    REQUEST_SIZE_MATCH(xCompositeGetRedirectedEventReq);
+    VERIFY_WINDOW(pWin, stuff->id, client, DixGetAttrAccess);
+
+    CompositeSendRedirectStateNotify(client, pWin,
+                                     compGetUpdateMask(pWin));
+    return Success;
+}
+
 static int (*ProcCompositeVector[CompositeNumberRequests]) (ClientPtr) = {
-ProcCompositeQueryVersion,
+        ProcCompositeQueryVersion,
         ProcCompositeRedirectWindow,
         ProcCompositeRedirectSubwindows,
         ProcCompositeUnredirectWindow,
         ProcCompositeUnredirectSubwindows,
         ProcCompositeCreateRegionFromBorderClip,
         ProcCompositeNameWindowPixmap,
-        ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow,};
+        ProcCompositeGetOverlayWindow,
+        ProcCompositeReleaseOverlayWindow,
+        ProcCompositeSelectInput,
+        ProcCompositeQueryRedirected,
+        ProcCompositeGetRedirectedEvent,
+};
 
 static int
 ProcCompositeDispatch(ClientPtr client)
@@ -477,6 +690,39 @@ SProcCompositeReleaseOverlayWindow(ClientPtr client)
     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
 }
 
+static int _X_COLD
+SProcCompositeSelectInput(ClientPtr client)
+{
+    REQUEST(xCompositeSelectInputReq);
+
+    swaps(&stuff->length);
+    REQUEST_SIZE_MATCH(xCompositeSelectInputReq);
+    swapl(&stuff->window);
+    return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int _X_COLD
+SProcCompositeQueryRedirected(ClientPtr client)
+{
+    REQUEST(xCompositeQueryRedirectedReq);
+
+    swaps(&stuff->length);
+    REQUEST_SIZE_MATCH(xCompositeSelectInputReq);
+    swapl(&stuff->id);
+    return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int _X_COLD
+SProcCompositeGetRedirectedEvent(ClientPtr client)
+{
+    REQUEST(xCompositeGetRedirectedEventReq);
+
+    swaps(&stuff->length);
+    REQUEST_SIZE_MATCH(xCompositeGetRedirectedEventReq);
+    swapl(&stuff->id);
+    return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
 static int
 (*SProcCompositeVector[CompositeNumberRequests]) (ClientPtr) = {
     SProcCompositeQueryVersion,
@@ -488,6 +734,9 @@ static int
     SProcCompositeNameWindowPixmap,
     SProcCompositeGetOverlayWindow,
     SProcCompositeReleaseOverlayWindow,
+    SProcCompositeSelectInput,
+    SProcCompositeQueryRedirected,
+    SProcCompositeGetRedirectedEvent,
 };
 
 static int _X_COLD
@@ -524,6 +773,51 @@ GetCompositeWindowBytes(void *value, XID id, ResourceSizePtr size)
     }
 }
 
+static int
+CompositeFreeClient(void *data, XID id)
+{
+    CompositeEventPtr pEvent;
+    WindowPtr pWin;
+    CompositeEventPtr *pHead, pCur, pPrev;
+    int rc;
+
+    pEvent = (CompositeEventPtr) data;
+    pWin = pEvent->pWindow;
+    rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
+                                 CompositeEventType, serverClient,
+                                 DixReadAccess);
+    if (rc == Success) {
+        pPrev = NULL;
+
+        for (pCur = *pHead; pCur && pCur != pEvent; pCur = pCur->next)
+            pPrev = pCur;
+        if (pCur) {
+            if (pPrev)
+                pPrev->next = pEvent->next;
+            else
+                *pHead = pEvent->next;
+        }
+    }
+
+    free(pEvent);
+    return 1;
+}
+
+static int
+CompositeFreeEvents(void *data, XID id)
+{
+    CompositeEventPtr *pHead, pCur, pNext;
+
+    pHead = (CompositeEventPtr *) data;
+    for (pCur = *pHead; pCur; pCur = pNext) {
+        pNext = pCur->next;
+        FreeResource(pCur->clientResource, CompositeClientType);
+        free(pCur);
+    }
+    free(pHead);
+    return 1;
+}
+
 void
 CompositeExtensionInit(void)
 {
@@ -569,6 +863,16 @@ CompositeExtensionInit(void)
     if (!CompositeClientOverlayType)
         return;
 
+    CompositeClientType = CreateNewResourceType
+        (CompositeFreeClient, "CompositeClient");
+    if (!CompositeClientType)
+        return;
+
+    CompositeEventType = CreateNewResourceType
+        (CompositeFreeEvents, "CompositeEvent");
+    if (!CompositeEventType)
+        return;
+
     if (!dixRegisterPrivateKey(&CompositeClientPrivateKeyRec, PRIVATE_CLIENT,
                                sizeof(CompositeClientRec)))
         return;
@@ -577,12 +881,13 @@ CompositeExtensionInit(void)
         if (!compScreenInit(screenInfo.screens[s]))
             return;
 
-    extEntry = AddExtension(COMPOSITE_NAME, 0, 0,
+    extEntry = AddExtension(COMPOSITE_NAME, CompositeNumberEvents, 0,
                             ProcCompositeDispatch, SProcCompositeDispatch,
                             NULL, StandardMinorOpcode);
     if (!extEntry)
         return;
     CompositeReqCode = (CARD8) extEntry->base;
+    CompositeEventBase = extEntry->eventBase;
 
     /* Initialization succeeded */
     noCompositeExtension = FALSE;
@@ -904,6 +1209,84 @@ PanoramiXCompositeReleaseOverlayWindow(ClientPtr client)
     return Success;
 }
 
+static int
+PanoramiXCompositeSelectInput (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc, j;
+
+    REQUEST(xCompositeSelectInputReq);
+    REQUEST_SIZE_MATCH(xCompositeSelectInputReq);
+
+    if ((rc = dixLookupResourceByType((void **) &win, stuff->window,
+                                      XRT_WINDOW, client,
+                                      DixUnknownAccess))) {
+        client->errorValue = stuff->window;
+        return rc;
+    }
+
+    FOR_NSCREENS_FORWARD(j) {
+        stuff->window = win->info[j].id;
+        rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+        if (rc != Success)
+            break;
+    }
+
+    return rc;
+}
+
+static int
+PanoramiXCompositeQueryRedirected (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc, j;
+
+    REQUEST(xCompositeQueryRedirectedReq);
+    REQUEST_SIZE_MATCH(xCompositeQueryRedirectedReq);
+
+    if ((rc = dixLookupResourceByType((void **) &win, stuff->id,
+                                      XRT_WINDOW, client,
+                                      DixUnknownAccess))) {
+        client->errorValue = stuff->id;
+        return rc;
+    }
+
+    FOR_NSCREENS_FORWARD(j) {
+        /* Just do the first screen.  */
+        stuff->id = win->info[j].id;
+        return (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+    }
+
+    /* Xinerama with 0 screens!  */
+    return BadImplementation;
+}
+
+static int
+PanoramiXCompositeGetRedirectedEvent (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc, j;
+
+    REQUEST(xCompositeQueryRedirectedReq);
+    REQUEST_SIZE_MATCH(xCompositeQueryRedirectedReq);
+
+    if ((rc = dixLookupResourceByType((void **) &win, stuff->id,
+                                      XRT_WINDOW, client,
+                                      DixUnknownAccess))) {
+        client->errorValue = stuff->id;
+        return rc;
+    }
+
+    FOR_NSCREENS_FORWARD(j) {
+        /* Just do the first screen.  */
+        stuff->id = win->info[j].id;
+        return (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+    }
+
+    /* Xinerama with 0 screens!  */
+    return BadImplementation;
+}
+
 void
 PanoramiXCompositeInit(void)
 {
@@ -928,6 +1311,12 @@ PanoramiXCompositeInit(void)
         PanoramiXCompositeGetOverlayWindow;
     ProcCompositeVector[X_CompositeReleaseOverlayWindow] =
         PanoramiXCompositeReleaseOverlayWindow;
+    ProcCompositeVector[X_CompositeSelectInput] =
+        PanoramiXCompositeSelectInput;
+    ProcCompositeVector[X_CompositeQueryRedirected] =
+        PanoramiXCompositeQueryRedirected;
+    ProcCompositeVector[X_CompositeGetRedirectedEvent] =
+        PanoramiXCompositeGetRedirectedEvent;
 }
 
 void
diff --git a/composite/compint.h b/composite/compint.h
index 423b641ff..df6ca8198 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -197,6 +197,9 @@ extern RESTYPE CompositeClientOverlayType;
  * compalloc.c
  */
 
+int
+  compGetUpdateMask(WindowPtr pWin);
+
 Bool
  compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update);
 
@@ -335,6 +338,13 @@ int
 compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
                  int bw, WindowPtr pSib);
 
+/*
+ * compext.c
+ */
+
+void
+ CompositeSendRedirectNotify(WindowPtr pWin, int reason, int update);
+
 void PanoramiXCompositeInit(void);
 void PanoramiXCompositeReset(void);
 
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 73a1871a0..6e8142912 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -584,9 +584,13 @@ compCreateWindow(WindowPtr pWin)
         if (window_pixmap != parent_pixmap)
             (*pScreen->SetWindowPixmap) (pWin, parent_pixmap);
         if (csw)
-            for (ccw = csw->clients; ccw; ccw = ccw->next)
-                compRedirectWindow(clients[CLIENT_ID(ccw->id)],
-                                   pWin, ccw->update);
+            {
+                for (ccw = csw->clients; ccw; ccw = ccw->next)
+                    compRedirectWindow(clients[CLIENT_ID(ccw->id)],
+                                       pWin, ccw->update);
+                CompositeSendRedirectNotify(pWin, CompositeChildCreated,
+                                            compGetUpdateMask(pWin));
+            }
         if (compImplicitRedirect(pWin, pWin->parent))
             compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
     }
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index d7bfc6dca..6da5eb6b5 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -40,7 +40,7 @@
 
 /* Composite */
 #define SERVER_COMPOSITE_MAJOR_VERSION		0
-#define SERVER_COMPOSITE_MINOR_VERSION		4
+#define SERVER_COMPOSITE_MINOR_VERSION		5
 
 /* Damage */
 #define SERVER_DAMAGE_MAJOR_VERSION		1
diff --git a/meson.build b/meson.build
index 47ecb06c9..7b70b50fb 100644
--- a/meson.build
+++ b/meson.build
@@ -82,7 +82,7 @@ bigreqsproto_dep = dependency('bigreqsproto', version: '>= 1.1.0', fallback: ['x
 xtrans_dep = dependency('xtrans', version: '>= 1.3.5')
 
 videoproto_dep = dependency('videoproto', fallback: ['xorgproto', 'ext_xorgproto'])
-compositeproto_dep = dependency('compositeproto', version: '>= 0.4', fallback: ['xorgproto', 'ext_xorgproto'])
+compositeproto_dep = dependency('compositeproto', version: '>= 0.5', fallback: ['xorgproto', 'ext_xorgproto'])
 recordproto_dep = dependency('recordproto', version: '>= 1.13.99.1', fallback: ['xorgproto', 'ext_xorgproto'])
 scrnsaverproto_dep = dependency('scrnsaverproto', version: '>= 1.1', fallback: ['xorgproto', 'ext_xorgproto'])
 resourceproto_dep = dependency('resourceproto', version: '>= 1.2.0', fallback: ['xorgproto', 'ext_xorgproto'])
-- 
2.37.3

Reply via email to