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

Peter Hutterer peter.hutterer at who-t.net
Wed Jun 15 18:01:58 PDT 2011


On Tue, Jun 14, 2011 at 07:30:49PM +0100, Daniel Stone wrote:
> Add four new private XKB actions for debugging:
>     * PrGrbs: print active grabs to the log file
>     * DeaGrb: deactivate active grabs

compat/xfree86 still has the stuff for "Ungrab" and "ClsGrab".

#define XF86XK_Ungrab           0x1008FE20   /* force ungrab */
#define XF86XK_ClearGrab        0x1008FE21   /* kill application with grab */

we should keep using them if possible.

Also, everywhere in the protocol and man pages we use "Ungrab" instead of
"deactivate", it'd be better to use that terminology here too anyway.

>     * KilGrb: 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+Enter print all currently active grabs:
>  - compat/xfree86:
>     interpret XF86DOS {
>         action = Private(type=0x86, data="PrGrbs");
>     };
> 
>  - symbols/pc:
>     key <RTRN> {        type="CTRL+ALT", [ Return, XF86DOS      ]       };
> 
> (Or any other unused keysym in place of XFDOS.)
> 
> 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                     |  132 +++++++++++++++++++++++++++++++++++++++
>  hw/xfree86/dixmods/xkbPrivate.c |    9 +++
>  include/dixgrabs.h              |    4 +
>  3 files changed, 145 insertions(+), 0 deletions(-)
> 
> diff --git a/dix/grabs.c b/dix/grabs.c
> index 69c58df..d65c76f 100644
> --- a/dix/grabs.c
> +++ b/dix/grabs.c
> @@ -68,6 +68,138 @@ SOFTWARE.
>  #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
>  #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
>  
> +void
> +PrintGrabInfo(void)
> +{
> +    DeviceIntPtr dev;
> +    ClientPtr client;
> +    LocalClientCredRec *lcc;
> +    int i, j;

A "Printing active grabs" here would be nice. It would tell us whether there
simply are no grabs or whether this function isn't actually called.

> +
> +    for (dev = inputInfo.devices; dev; dev = dev->next)
> +    {
> +        if (!dev->deviceGrab.grab)
> +            continue;

using a tmp variable for dev->deviceGrab would be good here
> +
> +        DebugF("[dix] Active grab 0x%lx (%s) on device '%s' (%d):",

any reason you use DebugF here but ErrorF in the print window tree patch?
it's unlikely that users reporting stuck grabs will have debugging enabled.

> +               (unsigned long) dev->deviceGrab.grab->resource,
> +               (dev->deviceGrab.grab->grabtype == GRABTYPE_XI2) ? "xi2" :
> +                ((dev->deviceGrab.grab->grabtype == GRABTYPE_CORE) ? "core" :
> +                  "xi1"),
> +               dev->name,
> +               dev->id);
> +
> +        client = clients[CLIENT_ID(dev->deviceGrab.grab->resource)];
> +        if (client && GetLocalClientCreds(client, &lcc) != -1)
> +        {
> +            DebugF("      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
> +        {
> +            DebugF("      (no client information available)\n");
> +        }
> +
> +        /* XXX is this even correct? */
> +        if (dev->deviceGrab.sync.other)
> +            DebugF("      grab ID 0x%lx from paired device\n",
> +                   (unsigned long) dev->deviceGrab.sync.other->resource);
> +
> +        DebugF("      at %ld (from %s grab)%s (device %s, state %d)\n",
> +               dev->deviceGrab.grabTime,
> +               dev->deviceGrab.fromPassiveGrab ? "passive" : "active",
> +               dev->deviceGrab.implicitGrab ? " (implicit)" : "",
> +               dev->deviceGrab.sync.frozen ? "frozen" : "thawed",
> +               dev->deviceGrab.sync.state);
> +        DebugF("        grab type %s\n",
> +               ((dev->deviceGrab.grab->grabtype == GRABTYPE_CORE) ? "core" :
> +                 (dev->deviceGrab.grab->grabtype == GRABTYPE_XI) ? "xi1" :
> +                  "xi2"));
> +        DebugF("        core event mask 0x%lx\n",
> +               dev->deviceGrab.grab->eventMask);
> +        if (dev->deviceGrab.grab->deviceMask)
> +            DebugF("      xi1 event mask 0x%lx\n",
> +                   dev->deviceGrab.grab->deviceMask);

only for implicit passive grabs, otherwise eventMask is the device's grab
mask see the massive comment above struct _GrabRec in inputstr.h

> +        for (i = 0; i < EMASKSIZE; i++)
> +        {
> +            int print;
> +            print = 0;
> +            for (j = 0; j < XI2MASKSIZE; j++)
> +            {
> +                if (dev->deviceGrab.grab->xi2mask[i][j])
> +                {
> +                    print = 1;
> +                    break;
> +                }
> +            }
> +            if (!print)
> +                continue;
> +            DebugF("      xi2 event mask for device %d: 0x", dev->id);
> +            for (j = 0; j < XI2MASKSIZE; j++)
> +                DebugF("%x", dev->deviceGrab.grab->xi2mask[i][j]);
> +            DebugF("\n");
> +        }
> +
> +        if (dev->deviceGrab.fromPassiveGrab)
> +        {
> +            DebugF("      passive grab type %d, detail 0x%lx, "
> +                   "activating key %d\n",
> +               dev->deviceGrab.grab->type,
> +               dev->deviceGrab.grab->detail.exact,
> +               dev->deviceGrab.activatingKey);
> +        }
> +
> +        DebugF("      owner-events %s, kb %d ptr %d, confine %x, cursor 0x%x\n",
> +               dev->deviceGrab.grab->ownerEvents ? "true" : "false",
> +               dev->deviceGrab.grab->keyboardMode,
> +               dev->deviceGrab.grab->pointerMode,
> +               dev->deviceGrab.grab->confineTo ?
> +                dev->deviceGrab.grab->confineTo->drawable.id :
> +                0,
> +               dev->deviceGrab.grab->cursor ?
> +                dev->deviceGrab.grab->cursor->id :
> +                0);

using a tmp variable for dev->deviceGrab.grab would be nice.

> +    }
> +}
> +
> +void
> +DeactivateAllGrabs(void)
> +{
> +    DeviceIntPtr dev;
> +
> +    DebugF("[dix] Deactivating all active grabs, listed below:\n");
> +    PrintGrabInfo();
> +
> +    for (dev = inputInfo.devices; dev; dev = dev->next)
> +    {
> +        if (dev->deviceGrab.grab)
> +            dev->deviceGrab.DeactivateGrab(dev);
> +    }
> +}
> +
> +void
> +KillGrabbingClients(void)
> +{
> +    DeviceIntPtr dev;
> +    ClientPtr client;
> +
> +    DebugF("[dix] Killing all clients with active grabs, listed below:\n");

these really needs to be ErrorF. same with the one above. both
cause weird behaviour in applications so a little warning is always nice to
have.

> +    PrintGrabInfo();
> +
> +    for (dev = inputInfo.devices; dev; dev = dev->next)
> +    {
> +        if (!dev->deviceGrab.grab)
> +            continue;
> +        client = clients[CLIENT_ID(dev->deviceGrab.grab->resource)];
> +        if (!client || client->clientGone)
> +            continue;
> +        CloseDownClient(client);
> +    }
> +}
> +
>  GrabPtr
>  CreateGrab(
>      int client,
> diff --git a/hw/xfree86/dixmods/xkbPrivate.c b/hw/xfree86/dixmods/xkbPrivate.c
> index 9742eaf..381044f 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,14 @@ 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)
> +            PrintGrabInfo();
> +        else if (strcasecmp(msgbuf, "deagrb")==0)

s/deagrb/ungrab/

> +            DeactivateAllGrabs();
> +        else if (strcasecmp(msgbuf, "kilgrb")==0)

s/kilgrb/clsgrb/

so we can re-use the existing ones

Cheers,
  Peter


> +            KillGrabbingClients();
> +        else if (strcasecmp(msgbuf, "prwins")==0)
> +            PrintWindowTree();

>      }
>  
>      return 0;
> diff --git a/include/dixgrabs.h b/include/dixgrabs.h
> index 3b2a46d..3f031a5 100644
> --- a/include/dixgrabs.h
> +++ b/include/dixgrabs.h
> @@ -28,6 +28,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>  
>  struct _GrabParameters;
>  
> +extern void PrintGrabInfo(void);
> +extern void DeactivateAllGrabs(void);
> +extern void KillGrabbingClients(void);
> +
>  extern GrabPtr CreateGrab(
>  	int /* client */,
>  	DeviceIntPtr /* device */,
> -- 
> 1.7.5.3
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 


More information about the xorg-devel mailing list