Access to events from the root window ? (~ mouse / keyboard hook)
Hello,
I need to know on Linux when a user press a key or use a button of his
mouse even when my app is not in focus (it's for a small "podcasting"
software which also grabs/synchronize screenshot(slides) when the user
do something).
On windows I've used the PyHook module (Python). Since I didn't find
anything equivalent on Linux I thought it was a good idea to use the
Xlib since it's obvious that the X server centralise all the events and
pass them to clients which request them.
The problem is that I can have these events only if I make a client
window which have the focus on it [I use these maks
XSelectInput(display, win, KeyPressMask |ButtonPressMask); ]
If I ask directly for the main root window events
[XSelectInput(display, root_window, KeyPressMask |ButtonPressMask);] I
have this message:
---
X Error of failed request: BadAccess (attempt to access private
resource denied)
Major opcode of failed request: 2 (X_ChangeWindowAttributes)
Serial number of failed request: 7
Current serial number in output stream: 7
---
I paste below the little test snippet.
Is what I'm trying to do feasible with Xlib ?
If so can you give me a hint ?
If not what would you advise (I don't necessarily need to know which
particular button or key is pressed)
Thanks in advance !
Test snippet:
------
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void
main()
{
Display* display;
int screen_num;
Window win;
Window root_window; //should be the main Window Manager window ?
unsigned int display_width, display_height,width, height,win_x,
win_y,win_border_width;
char *display_name = getenv("DISPLAY");
display = XOpenDisplay(display_name);
screen_num = DefaultScreen(display);
width = 200;
height = 100;
win_x = 0;
win_y = 0;
win_border_width = 2;
win = XCreateSimpleWindow(display, RootWindow(display, screen_num),
win_x, win_y, width, height,
win_border_width,
BlackPixel(display, screen_num),
WhitePixel(display, screen_num));*/
root_window= RootWindow(display,screen_num);
/* make the window actually appear on the screen. */
XMapWindow(display, win);
/* subscribe to the given set of event types. */
//XSelectInput(display, win, KeyPressMask |ButtonPressMask); //works
fine with win
XSelectInput(display, root_window, KeyPressMask |ButtonPressMask);
/* perform an events loop */
{
int done = 0;
XEvent an_event;
while (!done) {
XNextEvent(display, &an_event);
switch (an_event.type) {
case ButtonPress:
printf("Button pressed !\n");
break;
case KeyPress:
printf("Key pressed !!!\n");
break;
} /* end switch on event type */
} /* end while events handling */
}
Re: Access to events from the root window ? (~ mouse / keyboard hook)
<francois.schnell@gmail.com> wrote in message
news:1152698867.110435.151570@i42g2000cwa.googlegroups.com...[color=blue]
> Hello,
>
> I need to know on Linux when a user press a key or use a button of his
> mouse even when my app is not in focus (it's for a small "podcasting"
> software which also grabs/synchronize screenshot(slides) when the user
> do something).
>
> On windows I've used the PyHook module (Python). Since I didn't find
> anything equivalent on Linux I thought it was a good idea to use the
> Xlib since it's obvious that the X server centralise all the events and
> pass them to clients which request them.
>
> The problem is that I can have these events only if I make a client
> window which have the focus on it [I use these maks
> XSelectInput(display, win, KeyPressMask |ButtonPressMask); ]
>
> If I ask directly for the main root window events
> [XSelectInput(display, root_window, KeyPressMask |ButtonPressMask);] I
> have this message:
> ---
> X Error of failed request: BadAccess (attempt to access private
> resource denied)
> Major opcode of failed request: 2 (X_ChangeWindowAttributes)
> Serial number of failed request: 7
> Current serial number in output stream: 7
> ---
>
> I paste below the little test snippet.
>
> Is what I'm trying to do feasible with Xlib ?
> If so can you give me a hint ?
> If not what would you advise (I don't necessarily need to know which
> particular button or key is pressed)
>
> Thanks in advance !
>
> Test snippet:
>
> ------
> #include <X11/Xlib.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> void
> main()
> {
> Display* display;
> int screen_num;
> Window win;
> Window root_window; //should be the main Window Manager window ?
>
> unsigned int display_width, display_height,width, height,win_x,
> win_y,win_border_width;
> char *display_name = getenv("DISPLAY");
>
> display = XOpenDisplay(display_name);
> screen_num = DefaultScreen(display);
>
> width = 200;
> height = 100;
> win_x = 0;
> win_y = 0;
> win_border_width = 2;
>
> win = XCreateSimpleWindow(display, RootWindow(display, screen_num),
> win_x, win_y, width, height,
> win_border_width,
> BlackPixel(display, screen_num),
> WhitePixel(display, screen_num));*/
> root_window= RootWindow(display,screen_num);
>
> /* make the window actually appear on the screen. */
> XMapWindow(display, win);
>
> /* subscribe to the given set of event types. */
> //XSelectInput(display, win, KeyPressMask |ButtonPressMask); //works
> fine with win
> XSelectInput(display, root_window, KeyPressMask |ButtonPressMask);
>
> /* perform an events loop */
> {
> int done = 0;
> XEvent an_event;
> while (!done) {
> XNextEvent(display, &an_event);
> switch (an_event.type) {
> case ButtonPress:
> printf("Button pressed !\n");
> break;
> case KeyPress:
> printf("Key pressed !!!\n");
> break;
> } /* end switch on event type */
> } /* end while events handling */
> }
>[/color]
You would have to call XSelectInput on all windows, not just the root
window.
Note that even then you might not get the input, if that window's
application has
implemented a keyboard grab (Otherwise it is easy to write a keystroke
listener and steal passwords as they are typed in).
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project