How can I listen to the root events?
Closed this issue · 20 comments
I see the examples show how to listen to a specific window's events but is there a way to listen to the root window's events?
I need to manage global events.
You need to set root window event mask to your events set using ChangeWindowAttributes:
var x11 = require('x11');
x11.createClient(function(err, display) {
var X = display.client;
var root = display.screen[0].root;
X.ChangeWindowAttributes(wid, { eventMask: x11.eventMask.PointerMotion|x11.eventMask.KeyPress });
X.on('event', function(ev) {
console.log(ev);
});
});
Each window keeps separate copy of events mask per client, so here you are not changing global root event mask, but telling it "this is set of events this client is after". In xlib this is usually done with XSelectInput call (wich internally does ChangeWindowAttributes request).
The code you posted does not work. Where is wid
coming from? Did you mean to put root
?
It does not work for me with root
as the first parameter to ChangeWindowAttributes
.
Ok. So what is the environment you ran the code in? I am running i3 window manager, could that possibly cause a conflict? The code "works" as in I do not get any errors but I do not get the constant stream of events you got. I have only seen one event's output displayed while running the code. I also tried in Gnome 3 but I got the same result. I'm a little confused because it works as expected when I create a window and listen for it's events.
Edit: Ok so since I was running it in i3 the windows are maximized by default. I placed my windows in floating mode which allowed me to drag my mouse around the desktop. When I dragged my mouse around the desktop I got the constant stream of MotionNotify
events but no key press events.
That's probably because root window is covered by another window. Try to do "xwininfo", click on desktop and compare output with "xwininfo -root". In gnome, there is full screen "nautilus" window. Also composite manager might prevent events from bubbling ( it usually opens overlay window on top ).
Try to run it inside Xnest or Xephyr server - my example gif captured in Xephyr on mac/xorg
Yes I just came to the same conclusion. So is there a way I can get a stream of the events for all the windows?
I need to process all events.
Which events are you interested in? I don't think there is an easy way ( the only one comes to me is very hardcore: monitor x11 socket / port 6000 for all packets and extract information you need )
I most importantly interested in KeyPress and KeyRelease events. I'm was looking at this as an alternative to reading straight from /dev/input/* which requires root
You can do "GrabKeyboard" (but don't forget to post key events manually to a focused window) - read http://tronche.com/gui/x/xlib/input/XGrabKeyboard.html
Does this lib provide GrabModeAsync
or GrabModeSync
? How would I specify the pointer and keyboard modes?
Yes. https://github.com/sidorares/node-x11/blob/master/lib/corereqs.js#L512
According to http://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.txt
GrabModeAsync is 1 and GrabModeSync is 0 for both pointer mode and keyboard mode
I see XGrabKeyboard being used with XNextEvent. Is this available?
Yes. client.on('event', handler)
XGrabKeyboard is not going to work for me because it is still specific to a window. I need to process global key events for all windows.
I believe XQueryKeymap is the right approach.
Something similar to this python implementation here.
Does this lib support it?
No, not yet (feel free to add: https://github.com/sidorares/node-x11/blob/master/lib/corereqs.js , format is
QueryKeymap
1 44 opcode
1 unused
2 1 request length
▶
1 1 Reply
1 unused
2 CARD16 sequence number
4 2 reply length
32 LISTofCARD8 keys
)
Note that you need to poll keyboard with QueryKeymap request and might miss some keypresses if they happen to be between polls
I want to track the mouse.
I'm using Gnome, but i believe we can get a generic and simple way.
Why events don't bubble? Or... node-x11
can't force composite wms to bubble events to be listen at root?
can you see them with xev(1) ?
node-x11 only can see what network protocol allows. If events ton't reach root window you won't see them. Does it work for you without wm? (or without composite manager?)
I could not find how to get this information with xev
, but i can do with xdotool getmouselocation
.
So, what dark magic is xdotool using? :-)
Looks like all xdotool does is use XQueryPointer: https://github.com/jordansissel/xdotool/blob/f5309ecea01463b3bddb4964978631cd201fb7c6/xdo.c#L866
Nice... https://tronche.com/gui/x/xlib/window-information/XQueryPointer.html I believe that is it. :-)