Skip to content

Instantly share code, notes, and snippets.

@CyberShadow
Created March 30, 2016 17:55
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save CyberShadow/6412d11aea64144f8905cc0b8196f38e to your computer and use it in GitHub Desktop.
#!/bin/env rdmd
module xorg_show_grabs;
import std.algorithm;
import std.conv;
import std.exception;
import std.getopt;
import std.stdio;
import std.string;
void main(string[] args)
{
const defaultLogFileName = "/var/log/Xorg.0.log";
string logFileName = defaultLogFileName;
auto help = getopt(args,
"xorg-log", "Path to the Xorg log file, by default: " ~ defaultLogFileName, &logFileName,
);
if (help.helpWanted)
return defaultGetoptPrinter("xorg-show-grabs - Extract and display key grabs from Xorg log in a human-readable way.
Usage:
1. Run:
xdotool key XF86LogGrabInfo
2. Run this program.
Options:
",
help.options);
bool[string][string] results;
string currentClient;
bool currentGrab;
int currentKey, currentMod;
foreach (l; File(logFileName).byLine())
{
auto line = l.findSplit("] ")[2];
if (!line.length)
continue;
if (line == "Printing all currently registered grabs")
results = null;
else
if (line.skipOver(" Printing all registered grabs of client pid "))
currentClient = line.idup.strip();
else
if (line.skipOver(" grab "))
{
currentGrab = false;
line.skipUntil(' ');
if (!line.startsWith("(core), type 'KeyPress' on window "))
continue;
currentGrab = true;
}
else
if (line.skipOver(" device "))
{
if (!line.startsWith("'Virtual core keyboard' ("))
currentGrab = false;
}
else
if (line.skipOver(" detail "))
{
currentKey = line.skipUntil(' ').to!int;
if (!line.skipOver("(mask 0), modifiersDetail "))
continue;
currentMod = line.skipUntil(' ').to!int;
}
else
if (line.skipOver(" owner-events "))
{
if (currentGrab)
{
auto key = xModToString(currentMod)~xKeyToString(currentKey);
results[currentClient][key] = true;
currentGrab = false;
}
}
}
foreach (client; results.keys.sort())
{
writefln("%s:", client);
foreach (key; results[client].keys.sort())
writefln(" %s", key);
}
}
auto skipUntil(T)(ref T[] s, T c)
{
auto i = s.indexOf(c);
if (i < 0)
{
s = null;
return null;
}
auto result = s[0..i];
s = s[i+1..$];
return result;
}
pragma(lib, "X11");
import core.stdc.config;
struct Display;
alias KeyCode = ubyte;
alias KeySym = c_ulong;
extern(C) Display* XOpenDisplay(const(char)*);
extern(C) KeySym XkbKeycodeToKeysym(Display *dpy, KeyCode kc, uint group, uint level);
extern(C) char* XKeysymToString(KeySym);
string xKeyToString(int key)
{
static Display *dpy = null;
if (!dpy)
dpy = enforce(XOpenDisplay(":0"), "Can't open display!");
KeySym ks = XkbKeycodeToKeysym(dpy, cast(ubyte)key, 0, 0);
return XKeysymToString(ks).to!string();
}
string xModToString(int mod)
{
// 1 2 4 8 0x10 0x20 0x40 0x80
//const string[] names = [ "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"];
//const string[] names = [ "Shift", "Lock", "Control", "Alt" , "Mod2", "Mod3", "Win" , "Mod5"];
const string[] names = [ "Shift", "Lock", "Control", "Mod1(Alt)" , "Mod2", "Mod3", "Mod4(Win)" ,"Mod5"];
string result;
foreach (i, name; names)
if ((1<<i) & mod)
result ~= name ~ " + ";
return result;
}
@fidergo-stephane-gourichon

This is programmed in language D. To get an executable file, one can install packages gdc (GNU D compiler) and libx11-dev then run gdc -o xorg-show-grabs xorg-show-grabs.d -lX11.

@cpbotha
Copy link

cpbotha commented Jul 30, 2019

On Arch / Manjaro, gdc unfortunately does not build anymore:

$ gdc -o xorg-show-grabs xorg-show-grabs.d -lX11 -llto_plugin
gdc: fatal error: -fuse-linker-plugin, but liblto_plugin.so not found

Fortunately, dmd (the D reference compiler) is even easier:

$ dmd xorg-show-grabs.d

The binary is called xorg-show-grabs

@MikuChan03
Copy link

Marry me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment