[PATCH 5/6] events: Make XYToWindow a screen function pointer

Kristian Høgsberg krh at bitplanet.net
Tue Mar 25 14:57:16 PDT 2014


This allows DDXen to override the window picking to account for
native windows not seen by the X server.  The bulk of the picking logic
is exposed as a new helper function, miSpriteTrace().  This function
completes the sprite trace filled out by the caller, and can be set up
to start the search from a given toplevel window.

Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
---
 dix/events.c         | 99 +++++-----------------------------------------------
 dix/touch.c          | 10 ++++--
 include/cursor.h     |  2 ++
 include/scrnintstr.h |  4 +++
 mi/mi.h              |  3 ++
 mi/miscrinit.c       | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 124 insertions(+), 93 deletions(-)

diff --git a/dix/events.c b/dix/events.c
index f05dada..601c1a4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -565,7 +565,7 @@ XineramaConstrainCursor(DeviceIntPtr pDev)
     (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
 }
 
-static Bool
+Bool
 XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
 {
     SpritePtr pSprite = pDev->spriteInfo->sprite;
@@ -1302,6 +1302,7 @@ static void
 ComputeFreezes(void)
 {
     DeviceIntPtr replayDev = syncEvents.replayDev;
+    ScreenPtr pScreen;
     WindowPtr w;
     GrabPtr grab;
     DeviceIntPtr dev;
@@ -1318,8 +1319,9 @@ ComputeFreezes(void)
 
         syncEvents.replayDev = (DeviceIntPtr) NULL;
 
-        w = XYToWindow(replayDev->spriteInfo->sprite,
-                       event->root_x, event->root_y);
+        pScreen = RootWindow(replayDev->spriteInfo->sprite)->drawable.pScreen;
+        w = (*pScreen->XYToWindow) (replayDev, replayDev->spriteInfo->sprite,
+                                    event->root_x, event->root_y);
         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
             if (IsTouchEvent((InternalEvent *) event)) {
                 TouchPointInfoPtr ti =
@@ -2835,92 +2837,6 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
     return deliveries;
 }
 
-static Bool
-PointInBorderSize(WindowPtr pWin, int x, int y)
-{
-    BoxRec box;
-
-    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
-        return TRUE;
-
-#ifdef PANORAMIX
-    if (!noPanoramiXExtension &&
-        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
-        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
-        int i;
-
-        FOR_NSCREENS_FORWARD_SKIP(i) {
-            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
-                                    x + screenInfo.screens[0]->x -
-                                    screenInfo.screens[i]->x,
-                                    y + screenInfo.screens[0]->y -
-                                    screenInfo.screens[i]->y, &box))
-                return TRUE;
-        }
-    }
-#endif
-    return FALSE;
-}
-
-/**
- * Traversed from the root window to the window at the position x/y. While
- * traversing, it sets up the traversal history in the spriteTrace array.
- * After completing, the spriteTrace history is set in the following way:
- *   spriteTrace[0] ... root window
- *   spriteTrace[1] ... top level window that encloses x/y
- *       ...
- *   spriteTrace[spriteTraceGood - 1] ... window at x/y
- *
- * @returns the window at the given coordinates.
- */
-WindowPtr
-XYToWindow(SpritePtr pSprite, int x, int y)
-{
-    WindowPtr pWin;
-    BoxRec box;
-
-    pSprite->spriteTraceGood = 1;       /* root window still there */
-    pWin = RootWindow(pSprite)->firstChild;
-    while (pWin) {
-        if ((pWin->mapped) &&
-            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
-            (x < pWin->drawable.x + (int) pWin->drawable.width +
-             wBorderWidth(pWin)) &&
-            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
-            (y < pWin->drawable.y + (int) pWin->drawable.height +
-             wBorderWidth(pWin))
-            /* When a window is shaped, a further check
-             * is made to see if the point is inside
-             * borderSize
-             */
-            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
-            && (!wInputShape(pWin) ||
-                RegionContainsPoint(wInputShape(pWin),
-                                    x - pWin->drawable.x,
-                                    y - pWin->drawable.y, &box))
-#ifdef ROOTLESS
-            /* In rootless mode windows may be offscreen, even when
-             * they're in X's stack. (E.g. if the native window system
-             * implements some form of virtual desktop system).
-             */
-            && !pWin->rootlessUnhittable
-#endif
-            ) {
-            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
-                pSprite->spriteTraceSize += 10;
-                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
-                                               pSprite->spriteTraceSize *
-                                               sizeof(WindowPtr));
-            }
-            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
-            pWin = pWin->firstChild;
-        }
-        else
-            pWin = pWin->nextSib;
-    }
-    return DeepestSpriteWin(pSprite);
-}
-
 /**
  * Ungrab a currently FocusIn grabbed device and grab the device on the
  * given window. If the win given is the NoneWin, the device is ungrabbed if
@@ -3017,6 +2933,7 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin, newSpriteWin;
     SpritePtr pSprite = pDev->spriteInfo->sprite;
+    ScreenPtr pScreen;
 
     verify_internal_event((InternalEvent *) ev);
 
@@ -3096,7 +3013,9 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
         ev->root_y = pSprite->hot.y;
     }
 
-    newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
+    pScreen = RootWindow(pSprite)->drawable.pScreen;
+    newSpriteWin =
+        (*pScreen->XYToWindow) (pDev, pSprite, pSprite->hot.x, pSprite->hot.y);
 
     if (newSpriteWin != prevSpriteWin) {
         int sourceid;
diff --git a/dix/touch.c b/dix/touch.c
index 1eeed78..d9131eb 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -573,13 +573,17 @@ TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
 {
     TouchClassPtr t = sourcedev->touch;
     SpritePtr sprite = &ti->sprite;
+    ScreenPtr screen;
+    WindowPtr root;
 
     if (t->mode == XIDirectTouch) {
         /* Focus immediately under the touchpoint in direct touch mode.
          * XXX: Do we need to handle crossing screens here? */
-        sprite->spriteTrace[0] =
-            sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
-        XYToWindow(sprite, ev->device_event.root_x, ev->device_event.root_y);
+        root = sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
+        sprite->spriteTrace[0] = root;
+        screen = root->drawable.pScreen;
+        (*screen->XYToWindow) (sourcedev, sprite, ev->device_event.root_x,
+                               ev->device_event.root_y);
     }
     else if (!TouchBuildDependentSpriteTrace(sourcedev, sprite))
         return FALSE;
diff --git a/include/cursor.h b/include/cursor.h
index 9da08af..d1467dd 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -131,6 +131,8 @@ extern _X_EXPORT void GetSpritePosition(struct _DeviceIntRec * /* pDev */ ,
 
 #ifdef PANORAMIX
 extern _X_EXPORT int XineramaGetCursorScreen(struct _DeviceIntRec *pDev);
+extern _X_EXPORT Bool XineramaSetWindowPntrs(DeviceIntPtr pDev,
+                                             WindowPtr pWin);
 #endif                          /* PANORAMIX */
 
 #endif                          /* CURSOR_H */
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 86da789..412617b 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -353,6 +353,9 @@ typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
 
 typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
 
+typedef WindowPtr (*XYToWindowProcPtr)(DeviceIntPtr pDev,
+                                       SpritePtr pSprite, int x, int y);
+
 typedef struct _Screen {
     int myNum;                  /* index of this instance in Screens[] */
     ATOM id;
@@ -513,6 +516,7 @@ typedef struct _Screen {
     struct xorg_list offload_head;
 
     ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
+    XYToWindowProcPtr XYToWindow;
 } ScreenRec;
 
 static inline RegionPtr
diff --git a/mi/mi.h b/mi/mi.h
index 950ee38..192f708 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -537,4 +537,7 @@ extern _X_EXPORT void miPolyFillArc(DrawablePtr /*pDraw */ ,
                                     xArc *      /*parcs */
     );
 
+extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y
+    );
+
 #endif                          /* MI_H */
diff --git a/mi/miscrinit.c b/mi/miscrinit.c
index 6aed52f..edf5cae 100644
--- a/mi/miscrinit.c
+++ b/mi/miscrinit.c
@@ -38,6 +38,12 @@ from The Open Group.
 #include "pixmapstr.h"
 #include "dix.h"
 #include "miline.h"
+#include "inputstr.h"
+#include "windowstr.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
 #ifdef MITSHM
 #include <X11/extensions/shm.h>
 #include "shmint.h"
@@ -202,6 +208,98 @@ miSetScreenPixmap(PixmapPtr pPix)
         pPix->drawable.pScreen->devPrivate = (void *) pPix;
 }
 
+static Bool
+PointInBorderSize(WindowPtr pWin, int x, int y)
+{
+    BoxRec box;
+
+    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
+        return TRUE;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension &&
+        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
+        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
+        int i;
+
+        FOR_NSCREENS_FORWARD_SKIP(i) {
+            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
+                                    x + screenInfo.screens[0]->x -
+                                    screenInfo.screens[i]->x,
+                                    y + screenInfo.screens[0]->y -
+                                    screenInfo.screens[i]->y, &box))
+                return TRUE;
+        }
+    }
+#endif
+    return FALSE;
+}
+
+WindowPtr
+miSpriteTrace(SpritePtr pSprite, int x, int y)
+{
+    WindowPtr pWin;
+    BoxRec box;
+
+    pWin = DeepestSpriteWin(pSprite);
+    while (pWin) {
+        if ((pWin->mapped) &&
+            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
+            (x < pWin->drawable.x + (int) pWin->drawable.width +
+             wBorderWidth(pWin)) &&
+            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
+            (y < pWin->drawable.y + (int) pWin->drawable.height +
+             wBorderWidth(pWin))
+            /* When a window is shaped, a further check
+             * is made to see if the point is inside
+             * borderSize
+             */
+            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+            && (!wInputShape(pWin) ||
+                RegionContainsPoint(wInputShape(pWin),
+                                    x - pWin->drawable.x,
+                                    y - pWin->drawable.y, &box))
+#ifdef ROOTLESS
+            /* In rootless mode windows may be offscreen, even when
+             * they're in X's stack. (E.g. if the native window system
+             * implements some form of virtual desktop system).
+             */
+            && !pWin->rootlessUnhittable
+#endif
+            ) {
+            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
+                pSprite->spriteTraceSize += 10;
+                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+                                               pSprite->spriteTraceSize *
+                                               sizeof(WindowPtr));
+            }
+            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+            pWin = pWin->firstChild;
+        }
+        else
+            pWin = pWin->nextSib;
+    }
+    return DeepestSpriteWin(pSprite);
+}
+
+/**
+ * Traversed from the root window to the window at the position x/y. While
+ * traversing, it sets up the traversal history in the spriteTrace array.
+ * After completing, the spriteTrace history is set in the following way:
+ *   spriteTrace[0] ... root window
+ *   spriteTrace[1] ... top level window that encloses x/y
+ *       ...
+ *   spriteTrace[spriteTraceGood - 1] ... window at x/y
+ *
+ * @returns the window at the given coordinates.
+ */
+static WindowPtr
+miXYToWindow(DeviceIntPtr master, SpritePtr pSprite, int x, int y)
+{
+    pSprite->spriteTraceGood = 1;       /* root window still there */
+    return miSpriteTrace(pSprite, x, y);
+}
+
 Bool
 miScreenInit(ScreenPtr pScreen, void *pbits,  /* pointer to screen bits */
              int xsize, int ysize,      /* in pixels */
@@ -272,6 +370,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits,  /* pointer to screen bits */
     pScreen->ChangeBorderWidth = miChangeBorderWidth;
     pScreen->SetShape = miSetShape;
     pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
+    pScreen->XYToWindow = miXYToWindow;
 
     miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
 
-- 
1.9.0



More information about the xorg-devel mailing list