X11: Detect general Mouse and Keyboard events - c

Is there a way to detect if the mouse has been moved ANYWHERE on the X Server or a keyboard event occured? I need to react on the user doing anything with the X11 input devices.
I only managed to detect events on my own window using GTK.
I am thankful for every information (it does not have to be full code, an entry point would be good enough!)

Yes, you can do this using the Xinput2 extension. A complete, but rather small, tool which does this for cursor events can be found here (unclutter-xfixes). As a disclaimer, I am the author of that tool.
Another good resource in tutorial form can be found here.
Using XInput2 has multiple benefits:
No need to constantly poll the position (resource efficient)
Does not interfere with / break applications like selecting mouse events on all windows would.
What you don't get easily using Xinput2 is the exact position (but you can query it when you need it), but my understanding is that you don't need it anyway.
Once you loaded the extension, which I won't show here, you can select all events like this:
XIEventMask masks[1];
unsigned char mask[(XI_LASTEVENT + 7)/8];
memset(mask, 0, sizeof(mask));
XISetMask(mask, XI_RawMotion);
XISetMask(mask, XI_RawButtonPress);
XISetMask(mask, XI_RawKeyPress);
masks[0].deviceid = XIAllMasterDevices;
masks[0].mask_len = sizeof(mask);
masks[0].mask = mask;
XISelectEvents(display, DefaultRootWindow(display), masks, 1);
XFlush(display);
In your event queue, you can now look for the corresponding events.

For modern X11 implementations, xinput --test-xi2 --root will display great detail about all X11 input events available on your root window. I use this in a shell script that needs to wait on any input event:
echo "DEBUG $(date) waiting on X event"
xinput --test-xi2 --root | head -n 15 >/dev/null
echo "DEBUG $(date) got X event"

Related

X11/Xlib: virtual keyboard input and keyboard mapping synchronization issue

For an automated test application I have to simulate large amount of unicode keyboard input into an old X11 application (of which I don't have any source access).
My program takes the input from an UCS-2 LE encoded input stream via stdin and the basic operation is as follows:
Save current keyboard layout and lock modifiers (XDisplayKeycodes, XGetKeyboardMapping, XkbGetState)
Unlock active modifiers (XkbLockModifiers)
Disable all X11 slave keyboard devices via Xinput2 extension
Read input into a key press queue until n unique symbols are encountered, where n is the number of possible keycodes as returned by XDisplayKeycodes.
Map these n unique X11 KeySyms via XChangeKeyboardMapping on the n available KeyCodes
Type the correct KeyCodes for all enqueued KeySyms via XTestFakeKeyEvent
Clear the queue and continue at 4.) until no input is available
Reactivate keyboards and restore initial modifiers and mappings
Basically this system works better and much more performant than any virtual X11 key input tool I've seen so far.
However, there is an issue I can currently only fix using ugly delays:
As any other X11 application, the target application receives a MappingNotify (request==Keyboard) event from the X server after my application succeeded in changing the keyboard mapping table.
The usual response of a X11 client is to call XRefreshKeyboardMapping to update Xlib's knowledge of the new keyboard layout.
Now if the the client has some lag processing its X11 event queue, the XRefreshKeyboardMapping call might return a too recent mapping that is already some generations too far in the future.
E.g. my input generator has already done the fourth XChangeKeyboardMapping when the target application just arrived at handling the second MappingNotify event in its XEvent queue handler.
Actually it should get the second generation of the map, which isn't available at the X server anymore at that time.
Unfortunately there is no map id or version of any kind in the keyboard MappingNotify event so that XRefreshKeyboardMapping could refer to a specific map ... and the X server does not seem to keep a history either.
The result is that the X11 application's KeyCode to KeySym conversion operates with an invalid layout and generates wrong KeySyms.
So basically I have to wait until all clients (or at least the one with the input focus) have requested and received my last XChangeKeyboardMapping map before I am allowed to do the next XChangeKeyboardMapping.
I can fix 99.9% of the errors using a delay before XChangeKeyboardMapping and that delay is calculated by some ugly witchcraft (amount of key strokes etc.) and is way to high if 100% accuracy has to be achieved.
So my question is if there is any way to programmatically be notified or to check if a X11 client has completed XRefreshKeyboardMapping or if its map is in sync with the server map?
If not, is there a way to get another X11 client's current mapping via xlib (to check if the map is current)?
Thanks for any hints!
I've done something similar on Windows in the past. I had the luxury of being able to use the SendInput function which accepts a KEYBDINPUT structure with KEYEVENTF_UNICODE flag. Unfortunately X11 does not support direct keystroke synthesizing of Unicode characters.
Since I cannot comment yet I'm forced to give a suggestion as answer:
Have you considered using the clipboard instead in order to transfer your "unicode input" into this X11 application's input field ?
You also might consider using direct Unicode input if that application uses a toolkit that supports this:
E.g. programs based on GTK+ (that includes all GNOME applications) support Unicode input.
Hold Ctrl + Shift and type u followed by the Unicode hex digits and release Ctrl and Shift again.
I guess it should be easy to synthesize these sequences using the Xtest extension.

Simulate a mouse click with IOKit

Backstory:
I want to write a C program to automate clicks in a program running in OSx (in a desktop setting).
I first tried Using Quartz Event Services to simulate input events. But then I had this problem: Simulating mouse clicks on Mac OS X does not work for some applications, and the answers didn't help in my case.
CGEventRef click1_down = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, CGPointMake(posx, posy), kCGMouseButtonLeft);
CGEventSetIntegerValueField(click1_down, kCGMouseEventClickState, 0);
// This down click works about 5% of the time.
CGEventPost(kCGHIDEventTap, click1_down);
usleep(30000);
CGEventRef click1_up = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, CGPointMake(posx, posy), kCGMouseButtonLeft);
CGEventSetIntegerValueField(click1_up, kCGMouseEventClickState, 1);
CGEventPost(kCGHIDEventTap, click1_up);
// I've tried every combination of CGEventSetIntegerValueField, usleep and CFRelease, nothing seems to help
// The only thing helping is repeating the line: "CGEventPost(kCGHIDEventTap, click1_down);" 100s of times,
// then the down click works about 80% of the time, still not acceptable
I'm now turning to solution #3 suggested here: How can Mac OS X games receive low-level keyboard input events?
(this might also help How can I simulate the touch events by IOHIDEvent?)
I tried with Karabiner by sending a mouse click on key press:
<item>
<name>Right Mousebutton</name>
<identifier>rightMouseButton</identifier>
<autogen>__KeyToKey__ KeyCode::H, PointingButton::LEFT</autogen>
</item>
And this sends the click 100% of the time, but I want to send the click with by writing C code (to have greater control). Tough I'm not sure, Karabiner seems to use IOKit to send events, so I think this should work in my case, if I'm able to send mouse events with IOKit.
So my question is basically: how do I write a C program to simulate a mouse left click with IOKit ? The documentation is very sparse and I didn't manage to do it.
I tried getting inspiration from some projects:
https://github.com/tekezo/Karabiner
https://github.com/NoobsArePeople2/manymouse

How do I gracefully exit an X11 event loop?

Almost every tutorial I find tells me to do this for my event loop:
XEvent event;
while (true)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
printf("Expose\n");
break;
default:
break;
}
}
However, clicking the X to close the program results in this message.
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 10 requests (10 known processed) with 0 events remaining.
It is indeed strange to me that the examples suggest using an infinite loop. That doesn't sound natural, and my other X11 programs don't do that. So I searched around. I found out how to capture the window close event.
Atom wmDeleteMessage = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1);
XEvent event;
bool running = true;
while (running)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
printf("Expose\n");
break;
case ClientMessage:
if (event.xclient.data.l[0] == wmDeleteMessage)
running = false;
break;
default:
break;
}
}
That works. It exits without errors. ... But I refuse to believe this is the normal way to do things. I mean, is this the only way to properly exit an X11 app? It seems like a lot of work just to capture the close event. How do I make a 'proper' event loop? Why is the close event so deeply buried? What am I missing?
The problem lays in the communication between X Server and the Window Manager.
When you call XCreateWindow or XCreateSimpleWindow, the X Server creates your window (not showing it until you explicitly map it on the screen by calling XMapWindow), and then the Window Manager is responsible for attaching all the decorations and buttons and system menu around your window.
You can call XDestroyWindow on your own to remove the window, and this usually means it just disappears from the screen, but your program is still running and the connection to the X Server is still open, so you can send it some more requests.
The problem begins when the user clicks that little X button attached to your window by the Window Manager, because it is not created by the X Server and it is not his business to decide what to do then. Now it's all in hands of Window Manager.
If the Window Manager simply called XDestroyWindow on your window, it would cause a problem if your application wanted to capture the closing event to do something before the window gets destroyed. So the convention has been established between the X Server and the Window Managers to handle this process.
The default behavior of most Window Managers is to destroy the window and close the connection with the X server, because this is what most users of Window Managers would expect: that when they close the window, the program will end (and the connection to the X Server will close with the closed window). And then, when you try to call XCloseDisplay(display), it will cause the IO error you've mentioned, because the connection to the server is already closed and the display structure is invalid.
Here's an excerpt from the Xlib documentation which explains this:
Clients that choose not to include WM_DELETE_WINDOW in the WM_PROTOCOLS property may be disconnected from the server if the user asks for one of the client's top-level windows to be deleted.
Yeah, it would be great if they didn't hide it so deep in their docs, though :-P
But when you already find it, fortunately it also hints for the solution.
If you want a different behavior (that is, to capture the closing event from the Window Manager), you need to use the WM_DESTROY_WINDOW protocol.
Another excerpt from the docs:
Clients, usually those with multiple top-level windows, whose server connection must survive the deletion of some of their top-level windows, should include the atom WM_DELETE_WINDOW in the WM_PROTOCOLS property on each such window. They will receive a ClientMessage event as described above whose data[0] field is WM_DELETE_WINDOW.
I had the same error and I wanted to know exactly what causes it and why. It took me some time to figure it out and find the proper explanation in the doc, so I put my explanation here to save the time of others uninformed.
There are no such things as "exit button" or "application" or "close event" in X11. This is by design.
Window decorations, exit buttons and many the other things we depend upon are not built into X11. They are implemented on top of the core X11 instead. The name of the particular set of conventions responsible for wmDeleteMessage is ICCCM, look it up.
Xlib only deals with the core X11 protocol. No built-in close event there.
There are toolkits that make dealing with ICCCM and all other things that are not built into X11 easier (GTK, wxWindows, Qt, ...) You probably want to use one of those.

How to circumvent the "foreground lock timeout" to activate my window?

I'm trying to make an application like Launchy/Enso/etc., which pops up when the user presses the Caps Lock key.
To do this, I have needed to install a low-level keyboard hook (WH_KEYBOARD_LL), from which I subsequently spawn a thread to display the dialog to present to the user.
The trouble is, when I somehow steal focus (e.g. by clicking on another window) and subsequently press Caps Lock with a short delay, my window doesn't get the keyboard input: the input goes to the background window, even though my window is "active" (from looking at the title bar).
Of course, this gets pretty annoying, since I then end up typing something like "visu" (for "Visual Studio") inside a text processor (or a chat box...) and pressing Enter, withotu realizing that it didn't do what I intended.
(Funny thing is, after a 3-second (or so) pause, my window's title bar suddenly becomes "inactive", even though it was never active in the first place!)
How can I bypass this "protection" mechanism to actually activate my window?
Okay, I finally figured out a hack. (Microsoft employers: please look away...)
I intercept Caps Lock with a low-level keyboard hook, then when I detect VK_CAPITAL, I call
keybd_event(
VK_OEM_8,
(BYTE)MapVirtualKey(pKBDLLHook->vkCode, MAPVK_VK_TO_VSC),
(wParam == WM_KEYUP || wParam == WM_SYSKEYUP) ? KEYEVENTF_KEYUP : 0,
0
);
from within the handler.
Essentially, I just change the request to VK_OEM_8.
However, Notice that the virtual-key code does not correspond to the scan code. This is intentional -- VK_OEM_8 doesn't have a scan code (as far as I could tell, anyway) so I didn't have much of an option.
Then I just program based on VK_OEM_8 instead -- which is easy to intercept/handle/etc.
Hope this helps out other people.

Intercept WM_DELETE_WINDOW on X11?

I'd like to intercept the WM_DELETE_WINDOW message that is posted to a certain selection of windows that an application I'm writing (AllTray), so that I can act on it instead of the application receiving it. I'm currently looking at trying this at the GDK level via gdk_display_add_client_message_filter if possible, but I'd be happy with an Xlib solution if there is one as well; it seems to be possible, but I just don't seem to be understanding how I am to do it successfully.
Currently, I have two programs (written in C) that I am trying to use to get this figured out, the first one does nothing but create a window and register that it knows about WM_DELETE_WINDOW, and the second one attempts to catch that message, but seems to fail in doing so; it appears to do precisely nothing. Am I understanding the documentation wrong on this, or is there something additional that I need to be doing (or do I need to avoid using GDK entirely for this)?
The background is this: Prior to my re-write of AllTray, the way it would do things appears to be to try to intercept a mouse-click on the X button itself. For some window managers, this worked properly, for others it didn't work at all, and for others, the user had to configure it manually and instruct AllTray where the button for closing the window was. What I am looking for is a solution that doesn't involve a LD_LIBRARY_PRELOAD and will work for any window manager/application combination that conforms to the current standards and sends a WM_DELETE_WINDOW ClientMessage when the window is closed.
UPDATE: I'm still looking for an answer. The route that I am taking at the moment is to try to reparent the window and manage it myself, but I just cannot make it work. Upon reparenting, I don't seem to be able to get it back in any way. I may be missing something very fundamental, but I can't figure out how to actually make it appear it my own window again, to bring it back on the screen.
UPDATE 2: Alright, so I've hit another brick wall. The X server documentation says to set the StructureNotifyMask on the window's event mask to receive both MapNotify and ReparentNotify events. I'd be interested in receiving either. My current thinking was to create a window that served just as an event receiver, and then when I get events for interesting things, act on them by creating and reparenting. However, this simply doesn't seem to be working. The only events I actually receive are PropertyNotify events. So, this route doesn't seem to be doing very much good, either.
I don't know X11, but I googled using "Intercept WM_DELETE_WINDOW X11" as keywords. Found 17k - MarkMail and Mplayer-commits r154 - trunk/libvo. In both cases they are doing the same thing.
/* This is used to intercept window closing requests. */
static Atom wm_delete_window;
within static void x11_init(),
XMapWindow(display, win);
wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, win, &wm_delete_window, 1);
then, within static int x11_check_events(),
XEvent Event;
while (XPending(display)) {
XNextEvent(display, &Event);
if (Event.type == ClientMessage) {
if ((Atom)Event.xclient.data.l[0] == wm_delete_window) {
/* your code here */
}
}
}
See XInternAtom, XSetWMProtocols and XNextEvent.
After I wrote the above, I found Handling window close in an X11 app:
When a user clicks the close button
[x] on our X11 application we want it
to pop a a dialog asking “do you
really want to quit?”. This is a plain
X app. No fancy GTK or QT widgets
here. So how to catch the “window is
being closed” message?
The answer is to tell the Window
Manager we are interested in these
event by calling XSetWMProtocols and
registering a WM_DELETE_WINDOW message
with it. Then we’ll get a client
message from the Window Manager if
someone tries to close the window, and
it won’t close it, it’ll leave that us
up to us. Here’s an example….
// example.cpp
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
int main()
{
Display* display = XOpenDisplay(NULL);
Window window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0,
500, 400,
0,
0, 0);
// register interest in the delete window message
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1);
std::cout << "Starting up..." << std::endl;
XMapWindow(display, window);
while (true) {
XEvent event;
XNextEvent(display, &event);
if (event.type == ClientMessage &&
event.xclient.data.l[0] == wmDeleteMessage) {
std::cout << "Shutting down now!!!" << std::endl;
break;
}
}
XCloseDisplay(display);
return 0;
}
Unfortunately, the best answer to this question is a series of non-answers; there are technically ways to accomplish it, but they all have downfalls that make them extremely impractical:
Create an X11 proxy for an application, passing all X11 protocol messages back and forth between the application and the X server. The proxy would then filter out any interesting messages. The downside to this is that this is an awful lot of overhead for a single little tiny feature, and the X11 protocol is complex. There could also be unintended consequences, which makes this an even more unattractive option.
Launch as a standard application that acts as an intermediary between the window manager and “interesting” client applications. This breaks some things, such as XDnD. In effect, it is not unlike the first option, except that the proxy is at the Window level as opposed to the X11 protocol level.
Use the non-portable LD_PRELOAD library trick. This has several downsides:
It is non-portable across dynamic linkers: not all dynamic linkers support LD_PRELOAD, even among UNIX-like systems.
It is non-portable across operating systems: not all operating systems support featureful dynamic linkers.
It breaks network-transparency: the shared object/dynamic link library must reside on the host as the child process that is being executed.
Not all X11 applications use Xlib; it would be necessary to write one LD_PRELOAD module for each of the libraries that an application might use to talk with X11.
In addition to the last point, not all applications would be susceptible to LD_PRELOAD even if they ran under a linker that supported it, because they may not use a shared object or DLL in order to communicate with X; consider, for example, a Java application which uses an X11 protocol library written in Java itself.
On some UNIX-like operating systems, LD_PRELOAD libraries must be setuid/setgid if they are to be used with setuid/setgid programs. This is, of course, a potential security vulnerability.
I am quite sure that are more downsides that I cannot think of.
Implement an extension to the X Window system. Non-portable among X11 implementations, complex and convoluted as all get out, and absolutely out of the question.
Implement extensions or plug-ins to window managers. There are as many window managers as there are opinions on window managers, and therefore this is utterly infeasible.
Ultimately, I was able to finally accomplish my goal by using a completely separate mechanism; anyone who is interested, please see the Close-to-Tray support in AllTray 0.7.5.1dev and later, including the git master branch available on github.
Ok, to elaborate on my earlier suggestion, you might want to investigate XEmbed. At the least, that might give you some ideas to try.
Failing that, I'd have a look at how other similar software might be working (e.g. wmdock, or how GtkPlug/GtkSocket is implemented), though I believe in both those cases explicit support is required in the applications.
Hope that is more helpful.
You should read ICCCM that tells you how window manager communicates with client. Most of WM will create a frame window to contain your top-level window via reparenting. Thus, if your reparent may break the relationship known by WM and your client window.

Resources