[PATCH v2 2/6] XKB: Add debug key actions for grabs & window tree

Daniel Stone daniel at fooishbar.org
Wed Jun 22 02:17:28 PDT 2011


Add four new private XKB actions for debugging:
    * PrGrbs: print active grabs to the log file
    * Ungrab: ungrab all currently active grabs
    * ClsGrb: kill clients with active grabs
    * PrWins: dump the current window tree to the log file

To use these, you need to modify your XKB maps, e.g. the following to
have Ctrl+Alt+(F9-F12) mapped to the above:
 - compat/xfree86:
    interpret XF86LogGrabInfo {
        action = Private(type=0x86, data="PrGrbs");
    };
    interpret XF86Ungrab {
        action = Private(type=0x86, data="Ungrab");
    }
    interpret XF86ClearGrab {
        action = Private(type=0x86, data="ClsGrb");
    }
    interpret XF86LogWindowTree {
        action = Private(type=0x86, data="PrWins");
    }

 - symbols/pc:
    key <FK09> {        type="CTRL+ALT", [ Return, XF86LogGrabInfo      ]   };
    key <FK10> {        type="CTRL+ALT", [ Return, XF86Ungrab           ]   };
    key <FK11> {        type="CTRL+ALT", [ Return, XF86ClearGrab        ]   };
    key <FK12> {        type="CTRL+ALT", [ Return, XF86LogWindowTree    ]   };

These patches have been submitted to xkeyboard-config, but due to a
long-standing and catastrophic bug, shouldn't be used with xkbcomp
below version 1.2.3.

At the moment, this only works if the grabbing client continues to call
AllowEvents, as the server does no event processing at all when a device
is frozen.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 dix/grabs.c                     |  112 +++++++++++++++++++++++++++++++++++++++
 hw/xfree86/dixmods/xkbPrivate.c |   15 +++++
 include/dixgrabs.h              |    3 +
 3 files changed, 130 insertions(+), 0 deletions(-)

v2: Fixed event mask printing for core vs. XI 1.x grabs.
    Use ErrorF everywhere instead of DebugF.
    Use local variables for dev->deviceGrab and dev->deviceGrab.grab.
    Fix format strings for int vs. long.
    Always print prefix/postfix log messages so it's clear if there were
    no grabs printed.
    Change DeaGrab/DeactivateGrabs to Ungrab.
    Merge deactivate grab & kill grabbing client functions, as they were
    basically identical.


diff --git a/dix/grabs.c b/dix/grabs.c
index 69c58df..02cc12c 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -68,6 +68,118 @@ SOFTWARE.
 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
 
+void
+PrintDeviceGrabInfo(DeviceIntPtr dev)
+{
+    ClientPtr client;
+    LocalClientCredRec *lcc;
+    int i, j;
+    GrabInfoPtr devGrab = &dev->deviceGrab;
+    GrabPtr grab = devGrab->grab;
+
+    ErrorF("Active grab 0x%lx (%s) on device '%s' (%d):",
+           (unsigned long) grab->resource,
+           (grab->grabtype == GRABTYPE_XI2) ? "xi2" :
+            ((grab->grabtype == GRABTYPE_CORE) ? "core" : "xi1"),
+           dev->name, dev->id);
+
+    client = clients[CLIENT_ID(grab->resource)];
+    if (client && GetLocalClientCreds(client, &lcc) != -1)
+    {
+        ErrorF("      client pid %ld uid %ld gid %ld\n",
+               (lcc->fieldsSet & LCC_PID_SET) ? (long) lcc->pid : 0,
+               (lcc->fieldsSet & LCC_UID_SET) ? (long) lcc->euid : 0,
+               (lcc->fieldsSet & LCC_GID_SET) ? (long) lcc->egid : 0);
+        FreeLocalClientCreds(lcc);
+    }
+    else
+    {
+        ErrorF("      (no client information available)\n");
+    }
+
+    /* XXX is this even correct? */
+    if (devGrab->sync.other)
+        ErrorF("      grab ID 0x%lx from paired device\n",
+               (unsigned long) devGrab->sync.other->resource);
+
+    ErrorF("      at %ld (from %s grab)%s (device %s, state %d)\n",
+           (unsigned long) devGrab->grabTime.milliseconds,
+           devGrab->fromPassiveGrab ? "passive" : "active",
+           devGrab->implicitGrab ? " (implicit)" : "",
+           devGrab->sync.frozen ? "frozen" : "thawed",
+           devGrab->sync.state);
+
+    if (grab->grabtype == GRABTYPE_CORE)
+    {
+        ErrorF("        core event mask 0x%lx\n",
+               (unsigned long) grab->eventMask);
+    }
+    else if (grab->grabtype == GRABTYPE_XI)
+    {
+        ErrorF("      xi1 event mask 0x%lx\n",
+               devGrab->implicitGrab ? (unsigned long) grab->deviceMask :
+                                       (unsigned long) grab->eventMask);
+    }
+    else if (grab->grabtype == GRABTYPE_XI2)
+    {
+        for (i = 0; i < EMASKSIZE; i++)
+        {
+            int print;
+            print = 0;
+            for (j = 0; j < XI2MASKSIZE; j++)
+            {
+                if (grab->xi2mask[i][j])
+                {
+                    print = 1;
+                    break;
+                }
+            }
+            if (!print)
+                continue;
+            ErrorF("      xi2 event mask for device %d: 0x", dev->id);
+            for (j = 0; j < XI2MASKSIZE; j++)
+                ErrorF("%x", grab->xi2mask[i][j]);
+            ErrorF("\n");
+        }
+    }
+
+    if (devGrab->fromPassiveGrab)
+    {
+        ErrorF("      passive grab type %d, detail 0x%x, "
+               "activating key %d\n", grab->type, grab->detail.exact,
+               devGrab->activatingKey);
+    }
+
+    ErrorF("      owner-events %s, kb %d ptr %d, confine %lx, cursor 0x%lx\n",
+           grab->ownerEvents ? "true" : "false",
+           grab->keyboardMode, grab->pointerMode,
+           grab->confineTo ? (unsigned long) grab->confineTo->drawable.id : 0,
+           grab->cursor ? (unsigned long) grab->cursor->id : 0);
+}
+
+void
+UngrabAllDevices(Bool kill_client)
+{
+    DeviceIntPtr dev;
+    ClientPtr client;
+
+    ErrorF("Ungrabbing all devices%s; grabs listed below:\n",
+           kill_client ? " and killing their owners" : "");
+
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+        if (!dev->deviceGrab.grab)
+            continue;
+        PrintDeviceGrabInfo(dev);
+        client = clients[CLIENT_ID(dev->deviceGrab.grab->resource)];
+        if (!client || client->clientGone)
+            dev->deviceGrab.DeactivateGrab(dev);
+        CloseDownClient(client);
+    }
+
+    ErrorF("End list of ungrabbed devices\n");
+}
+
 GrabPtr
 CreateGrab(
     int client,
diff --git a/hw/xfree86/dixmods/xkbPrivate.c b/hw/xfree86/dixmods/xkbPrivate.c
index 9742eaf..06d1c2b 100644
--- a/hw/xfree86/dixmods/xkbPrivate.c
+++ b/hw/xfree86/dixmods/xkbPrivate.c
@@ -13,6 +13,7 @@
 #define XKBSRV_NEED_FILE_FUNCS
 #include <xkbsrv.h>
 
+#include "dixgrabs.h"
 #include "os.h"
 #include "xf86.h"
 
@@ -29,6 +30,20 @@ XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act)
             xf86ProcessActionEvent(ACTION_PREV_MODE, NULL);
         else if (strcasecmp(msgbuf, "+vmode")==0)
             xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL);
+        else if (strcasecmp(msgbuf, "prgrbs")==0) {
+            DeviceIntPtr tmp;
+            xf86Msg(X_INFO, "Printing all currently active device grabs:\n");
+            for (tmp = inputInfo.devices; tmp; tmp = tmp->next)
+                if (tmp->deviceGrab.grab)
+                    PrintDeviceGrabInfo(tmp);
+            xf86Msg(X_INFO, "End list of active device grabs\n");
+        }
+        else if (strcasecmp(msgbuf, "ungrab")==0)
+            UngrabAllDevices(FALSE);
+        else if (strcasecmp(msgbuf, "clsgrb")==0)
+            UngrabAllDevices(TRUE);
+        else if (strcasecmp(msgbuf, "prwins")==0)
+            PrintWindowTree();
     }
 
     return 0;
diff --git a/include/dixgrabs.h b/include/dixgrabs.h
index 3b2a46d..229c8bb 100644
--- a/include/dixgrabs.h
+++ b/include/dixgrabs.h
@@ -28,6 +28,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 struct _GrabParameters;
 
+extern void PrintDeviceGrabInfo(DeviceIntPtr dev);
+extern void UngrabAllDevices(Bool kill_client);
+
 extern GrabPtr CreateGrab(
 	int /* client */,
 	DeviceIntPtr /* device */,
-- 
1.7.5.4



More information about the xorg-devel mailing list