I'm working on a window manager, mainly as an exercise, and I'm facing a problem. I would like to be able to raise the clicked window to the top of the stack. Currently, I am using XGrabButton on Button1 and ControlMask to allow for moving of windows, and when I Ctrl+click the window, the desired effect is achieved. However, if I use XGrabButton on Button1 with AnyModifier, while the effect I am looking for is achieved, I can no longer interact with the client window (highlighting text, etc.) through the mouse button. I have tried Grabbing the button on EnterNotify, then ungrabbing the button as soon as the window is raised, but this appears to have no effect and the window manager acts as though I never grabbed the button at all.
My program is still relatively small, so here is the code:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "window_manager.h"
ewm_instance wm;
void
ewm_init()
{
wm._display = XOpenDisplay(NULL);
if (!wm._display) {
printf("Could not open display %s\n", XDisplayName(NULL));
}
wm._root = DefaultRootWindow(wm._display);
}
void
ewm_run()
{
XSelectInput(wm._display,
wm._root,
SubstructureRedirectMask | SubstructureNotifyMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask);
XSync(wm._display, 0);
XGrabServer(wm._display);
Window returned_root, returned_parent;
Window *top_level_windows;
unsigned int num_top_level_windows;
XQueryTree(wm._display,
wm._root,
&returned_root,
&returned_parent,
&top_level_windows,
&num_top_level_windows);
XFree(top_level_windows);
XUngrabServer(wm._display);
XGrabButton(
wm._display,
Button1,
ControlMask,
wm._root,
0,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync,
GrabModeAsync,
None,
None);
XGrabButton(
wm._display,
Button1,
ControlMask,
wm._root,
0,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync,
GrabModeAsync,
None,
None);
for (;;) {
XEvent e;
XNextEvent(wm._display, &e);
switch (e.type) {
case CreateNotify:
printf("CreateNotify\n");
break;
case DestroyNotify:
printf("DestroyNotify\n");
break;
case ReparentNotify:
printf("ReparentNotify\n");
break;
case MapNotify:
printf("Mapping Window\n");
break;
case UnmapNotify:
printf("UnmapNotify\n");
break;
case ConfigureNotify:
printf("ConfigureNotify\n");
break;
case MapRequest:
printf("MapRequest\n");
ewm_on_map_request(&e.xmaprequest);
break;
case ConfigureRequest:
printf("ConfigureRequest\n");
break;
case ButtonPress:
printf("ButtonPress\n");
ewm_on_button_press(&e.xbutton);
break;
case ButtonRelease:
printf("ButtonRelease\n");
break;
case MotionNotify:
ewm_on_motion_notify(&e.xmotion);
break;
case KeyPress:
printf("KeyPress\n");
ewm_on_key_press(&e.xkey);
break;
case KeyRelease:
printf("KeyRelease\n");
break;
case EnterNotify:
ewm_on_enter_notify(&e.xcrossing);
break;
default:
printf("Something else\n");
}
}
}
void
ewm_on_map_request(const XMapRequestEvent *e)
{
XSelectInput(
wm._display,
e->window,
KeyPressMask | KeyReleaseMask |
EnterWindowMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
XMapWindow(wm._display, e->window);
XSetInputFocus(wm._display, e->window, RevertToPointerRoot, CurrentTime);
}
void
ewm_on_enter_notify(const XEnterWindowEvent *e)
{
printf("Entered window: %lu\n", e->window);
XSetInputFocus(wm._display, e->window, RevertToParent, CurrentTime);
}
void
ewm_on_key_press(const XKeyEvent *e)
{
if ((e->state & ControlMask) &&
e->keycode == XKeysymToKeycode(wm._display, XK_q)) {
printf("Destroying window\n");
XDestroyWindow(wm._display, e->window);
}
if ((e->state & ControlMask) &&
e->keycode == XKeysymToKeycode(wm._display, XK_Return)) {
printf("Enter Works\n");
system("urxvt &");
}
}
void
ewm_on_button_press(const XButtonEvent *e)
{
if (e->subwindow != 0) {
// Save initial cursor position;
wm._cursor_start_position = (Vector){e->x_root, e->y_root};
// Save initial window info
Window returned_root;
int x, y;
unsigned int width, height, depth, border_width;
XGetGeometry(wm._display,
e->subwindow,
&returned_root,
&x, &y,
&width, &height,
&border_width,
&depth);
wm._window_start_position = (Vector){x, y};
wm._window_start_size = (Size){width, height};
XRaiseWindow(wm._display, e->subwindow);
XSetInputFocus(wm._display, e->subwindow, RevertToParent, CurrentTime);
printf("Raising window %lu\n", e->subwindow);
printf("root id: %lu\n", wm._root);
XUngrabButton(wm._display, Button1, AnyModifier, e->subwindow);
}
}
void
ewm_on_motion_notify(const XMotionEvent *e)
{
const Vector drag_pos = {e->x_root, e->y_root};
const Vector delta = {
(drag_pos.x - wm._cursor_start_position.x),
(drag_pos.y - wm._cursor_start_position.y)
};
if ((e->state & Button1Mask) && (e->state & ControlMask)) {
const Vector dest_window_pos = {
(wm._window_start_position.x + delta.x),
(wm._window_start_position.y + delta.y)
};
if (e->subwindow != 0) {
XMoveWindow(wm._display,
e->subwindow,
dest_window_pos.x,
dest_window_pos.y);
}
}
}
void
ewm_cleanup()
{
XCloseDisplay(wm._display);
}
I have also tried to use XSendEvent, but based on the results I have gotten from it I don't think I understand what it is supposed to do very well. I am very new to Xlib programming so any help is greatly appreciated.
Thank you!
I had exactly the same problem. The comments in the original question helped, but they're not quite there yet, they're missing an important detail (point 1 ahead). Ultimately I found the hint here solved it.
Grab the event synchronously (notice GrabModeSync given as pointer_mode)
XGrabButton(dis, FOCUS_BUTTON, AnyModifier, root, False, BUTTONMASK, GrabModeSync, GrabModeAsync, None, None);
Use XAllowEvents and Xsync for the pass-through effect
XAllowEvents(display, ReplayPointer, ev->xbutton.time);
XSync(display, 0);
Related
I need to be notified when mouse enters or leaves a window (any window, that's why I'm grabbing on the root window). I have a solution using xcb_input_xi_grab_device() but it works only half way. When I run the app, I do get enter/leave events but the mouse pointer disappears and it consumes all mouse events and other windows stop (children of the root window) reacting to clicks.
Using XCB_INPUT_GRAB_OWNER_OWNER should allow passing-through the events but it doesn't work.
app.c:
#include <stdio.h>
#include <xcb/xcb.h>
#include <xcb/xinput.h>
xcb_input_device_id_t find_device(xcb_connection_t *conn)
{
xcb_input_xi_query_device_reply_t *reply = xcb_input_xi_query_device_reply(
conn, xcb_input_xi_query_device(conn, XCB_INPUT_DEVICE_ALL), NULL);
xcb_input_xi_device_info_iterator_t iter =
xcb_input_xi_query_device_infos_iterator(reply);
xcb_input_device_id_t device_id;
int found = 0;
while (iter.rem) {
xcb_input_xi_device_info_t *device = iter.data;
switch (device->type) {
case XCB_INPUT_DEVICE_TYPE_MASTER_POINTER:
case XCB_INPUT_DEVICE_TYPE_SLAVE_POINTER:
case XCB_INPUT_DEVICE_TYPE_FLOATING_SLAVE:
device_id = device->deviceid;
found = 1;
break;
}
if (found) {
break;
}
xcb_input_xi_device_info_next(&iter);
}
free(reply);
return device_id;
}
int main()
{
xcb_connection_t *conn = xcb_connect(NULL, NULL);
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
uint32_t mask =
XCB_INPUT_XI_EVENT_MASK_ENTER | XCB_INPUT_XI_EVENT_MASK_LEAVE;
xcb_generic_error_t *error;
xcb_input_xi_grab_device_reply_t *reply = xcb_input_xi_grab_device_reply(
conn,
xcb_input_xi_grab_device(conn, screen->root, XCB_CURRENT_TIME,
XCB_CURSOR_NONE, find_device(conn),
XCB_INPUT_GRAB_MODE_22_ASYNC,
XCB_INPUT_GRAB_MODE_22_ASYNC,
XCB_INPUT_GRAB_OWNER_OWNER, 1, &mask),
&error);
free(reply);
if (error) {
printf("failed to grab device\n");
free(error);
return -1;
}
xcb_flush(conn);
xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(conn))) {
xcb_ge_event_t *generic_event = event;
switch (generic_event->event_type) {
case XCB_INPUT_ENTER:
printf("enter\n");
break;
case XCB_INPUT_LEAVE:
printf("leave\n");
break;
}
free(event);
}
return -1; // never reached
}
cc -O2 app.c -o app `pkg-config --cflags --libs xcb xcb-xinput`
I also tried to achieve it with xcb_grab_button(), xcb_input_xi_select_events(), xcb_input_xi_passive_grab_device() or xcb_grab_pointer() but then the problem is the same. Either the mouse events are not passed-through or I don't receive enter/leave events at all.
Sorry for the poor title, it wasn't easy to describe it better. I am learning C and as a toy project I am building a simple status bar for my window manager. Basically it just outputs text to the root X11 window name, which gets picked up by the wm (DWM).
Now I wanted to add simple click detected, so that I can do something when a specific area is clicked. The polling of the mouse happens in a while loop; and the update of the status bar also lives in the while loop, but with a different (less frequent) interval. Everything works, except that no other X11 applications are receiving the mouse clicks I listen to in my while loop.
I used XNextEvent first but found out that was blocking the while loop if the mouse was idle. Then I learned about XCheckWindowEvent which returns a boolean if the event I want to poll matches, then I can handle it. But the loop will not pause when the mouse is idle (which is most of the time).
However since doing so, whenever I move the mouse, I cannot click on any other window anymore. The cursor moves just fine, but clicks do not seem to work.
Am I making any sense?
This is the listing of my program (slightly simplified as for the status setting part, since that probably will distract).
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#include <unistd.h>
#include <fcntl.h>
#include <X11/Xlib.h>
#define EVTMASK (ButtonPressMask | PointerMotionMask)
void set_status(Display *display, Window window, char *str);
void process_mouse(Display *display, Window window, XEvent xevent);
char *key_name[] = {
"first",
"second (or middle)",
"third"
};
int
main(void)
{
const int MSIZE = 1024;
Display *display;
XEvent xevent;
Window window;
char *status;
char *bg_color = "#000000";
char *clr_yellow = "#ecbe7b";
time_t previousTime = time(NULL);
time_t interval_status = 1;
time_t currentTime;
if (!(display = XOpenDisplay(NULL))) {
fprintf(stderr, "Cannot open display.\n");
return EXIT_FAILURE;
}
// Setup X11 for mouse grabbing
window = DefaultRootWindow(display);
XAllowEvents(display, AsyncBoth, CurrentTime);
XGrabPointer(display,
window,
1,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask ,
GrabModeAsync,
GrabModeAsync,
None,
None,
CurrentTime);
status = (char*) malloc(sizeof(char)*MSIZE);
if(!status)
return EXIT_FAILURE;
while(1)
{
process_mouse(display, window, xevent);
if((time(¤tTime) - previousTime) >= interval_status)
{
int ret = snprintf(status, MSIZE, "^b%s^^c%s^%s Status me!", bg_color, clr_yellow);
set_status(display, window, status);
previousTime += interval_status;
}
}
return 0;
}
void
set_status(Display *display, Window window, char *str)
{
XStoreName(display, window, str);
XSync(display, False);
}
void
process_mouse(Display *display, Window window, XEvent xevent)
{
if(XCheckWindowEvent(display, window, EVTMASK, &xevent)) {
switch (xevent.type) {
case MotionNotify:
printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
break;
case ButtonPress:
printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]);
break;
case ButtonRelease:
printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
break;
}
XPutBackEvent(display, &xevent);
}
}
Open question: should I go back to the NextEvent method and listen to the mouse on a different thread?
I am trying to be notified about any pointer motion. Since I don't want to run as the window manager, I need to set XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION on all windows which I do both on startup and when I get a create notify event.
This seems to work fine in general and I receive motion notify events on all windows. However, somehow, this isn't true for Google Chrome windows. I checked the event mask by explicitly querying it afterwards and it is correctly set. I also don't see anything unusual in the propagation mask.
What could cause Google Chrome to not report motion notify events? AFAIK, the X protocol doesn't allow that except for active pointer grabs which Chrome surely doesn't have.
Here is how I register myself on all existing windows. I call register_events on the root window and whenever I receive a create notify event as well:
static void register_events(xcb_window_t window) {
xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(connection,
window, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_LEAVE_WINDOW });
xcb_generic_error_t *error = xcb_request_check(connection, cookie);
if (error != NULL) {
xcb_disconnect(connection);
errx(EXIT_FAILURE, "could not subscribe to events on a window, bailing out");
}
}
static void register_existing_windows(void) {
xcb_query_tree_reply_t *reply;
if ((reply = xcb_query_tree_reply(connection, xcb_query_tree(connection, root), 0)) == NULL) {
return;
}
int len = xcb_query_tree_children_length(reply);
xcb_window_t *children = xcb_query_tree_children(reply);
for (int i = 0; i < len; i++) {
register_events(children[i]);
}
xcb_flush(connection);
free(reply);
}
The Chrome windows appear to be comprised of quite the tree of nested child windows. It appears you'll need to walk the tree of windows and monitor them all. This code picks up pointer motion events across the entirety of my Chrome windows:
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <X11/Xlib.h>
static void register_events(xcb_connection_t *conn,
xcb_window_t window) {
xcb_void_cookie_t cookie =
xcb_change_window_attributes_checked(conn,
window, XCB_CW_EVENT_MASK,
(uint32_t[]) {
XCB_EVENT_MASK_POINTER_MOTION });
xcb_generic_error_t *error = xcb_request_check(conn, cookie);
if (error != NULL) {
xcb_disconnect(conn);
exit(-1);
}
}
static void register_existing_windows(xcb_connection_t *conn,
xcb_window_t root) {
int i, len;
xcb_window_t *children;
xcb_query_tree_reply_t *reply;
if ((reply = xcb_query_tree_reply(conn,
xcb_query_tree(conn, root), 0))
== NULL)
{
return;
}
len = xcb_query_tree_children_length(reply);
children = xcb_query_tree_children(reply);
for (i = 0; i < len; i++) {
register_events(conn, children[i]);
register_existing_windows(conn, children[i]);
}
xcb_flush(conn);
}
void main(void) {
int i=0;
/* Open the connection to the X server */
xcb_connection_t *conn = xcb_connect (NULL, NULL);
/* Get the first screen */
xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (conn)).data;
register_existing_windows(conn, screen->root);
while(1) {
xcb_generic_event_t *evt;
evt = xcb_wait_for_event(conn);
printf("%i\n", i++);
}
}
(That's just intended as proof of concept, and not very nice.)
While #Jay Kominek's answer was helpful and valid, I've come to realize now that using the Xinput extension provides a much better approach as it won't interfere with applications whatsoever.
Simply selecting on the entire tree causes all kinds of issues, e.g., hover doesn't work in Chrome anymore.
xcb provides xcb_grab_pointer to capture pointer event without registe on specific window.
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
void
print_modifiers (uint32_t mask)
{
const char **mod, *mods[] = {
"Shift", "Lock", "Ctrl", "Alt",
"Mod2", "Mod3", "Mod4", "Mod5",
"Button1", "Button2", "Button3", "Button4", "Button5"
};
printf ("Modifier mask: ");
for (mod = mods ; mask; mask >>= 1, mod++)
if (mask & 1)
printf(*mod);
putchar ('\n');
}
int
main ()
{
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t win;
xcb_generic_event_t *e;
uint32_t mask = 0;
/* Open the connection to the X server */
c = xcb_connect (NULL, NULL);
/* Get the first screen */
screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
mask = XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION;
xcb_grab_pointer(c, false, screen->root, mask, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);
xcb_flush (c);
while ((e = xcb_wait_for_event (c))) {
switch (e->response_type & ~0x80) {
case XCB_BUTTON_PRESS: {
xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
print_modifiers(ev->state);
switch (ev->detail) {
case 4:
printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n",
ev->event, ev->event_x, ev->event_y);
break;
case 5:
printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n",
ev->event, ev->event_x, ev->event_y);
break;
default:
printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n",
ev->detail, ev->event, ev->event_x, ev->event_y);
}
break;
}
case XCB_BUTTON_RELEASE: {
xcb_button_release_event_t *ev = (xcb_button_release_event_t *)e;
print_modifiers(ev->state);
printf ("Button %d released in window %ld, at coordinates (%d,%d)\n",
ev->detail, ev->event, ev->event_x, ev->event_y);
break;
}
case XCB_MOTION_NOTIFY: {
xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e;
printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n",
ev->event, ev->event_x, ev->event_y);
break;
}
default:
/* Unknown event type, ignore it */
printf("Unknown event: %d\n", e->response_type);
break;
}
/* Free the Generic Event */
free (e);
}
return 0;
}
I am designing an app that having the ID of an X11 window to draw a rectangle.
The problem I have is that I can not draw nothing in the window.
Code
One obvious error is that you did not select ExposureMask in call to XSelectInput, so you will not receive Expose event you are waiting for.
Other possible problem is not setting foreground drawing color of the GC by XSetForegroundColor, default is black. And using default gc of screen may fail if the window has different color depth or different visual. Other important GC attributes issubwindow_mode (whether to draw over child windows).
Still, after I did those changes, the program only works for me (draws a rectangle) on root window and xev, but not for xterm, no expose events.
This is my fixed version:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[]){
Window win;
Display *display;
XEvent e;
display = XOpenDisplay(NULL);
if(display==NULL){
fprintf(stderr,"Cannot open Display\n");
exit(1);
}
int s = DefaultScreen(display);
//unsigned long *id = (unsigned long*)(argv[1]);
sscanf(argv[1], "0x%x", &win);
if(!XSelectInput(display,win,StructureNotifyMask | ExposureMask)){
fprintf(stderr,"Cannot select Display\n");
return -1;
}
if(!XMapWindow(display,win)){
fprintf(stderr,"Cannot map Display\n");
return -1;
}
XGCValues gcv;
gcv.subwindow_mode = IncludeInferiors;
GC gc = XCreateGC(display, win, GCSubwindowMode,
&gcv);
XSetForeground(display, gc, 0xff00ff00);
XSetPlaneMask(display, gc, 0xffffffff);
while (1) {
puts("waiting for event\n");
XNextEvent(display, &e);
puts("got event\n");
if (e.type == Expose) {
printf("drawing\n");
XFillRectangle(display, win, gc, 20, 20, 100, 100);
}
if (e.type == KeyPress)
break;
}
return 0;
}
I am currently writing an application which requires to monitor mouse pointer movement on all the existing windows in Linux. I am using Ubuntu 11.10 with gnome.
What I need is to get the information on mouse pointer movement anywhere on the screen.
Here is the existing code for doing the same :
void *MonitorOffline(void *threaddata)
{
time_t sTime, cTime;
DISPLAY *dsp = NULL;
int iError = 0;
sTime = time(NULL);
XSetErrorHandler(_invalid_window_handler);
while (1) {
XEvent event;
cTime = time(NULL);
if ((cTime - sTime) > OFFLINETIME) {
log_msg("User %s is offline", cuserid(NULL));
sTime = cTime;
}
iError = RegisterWinEvents(&dsp);
if (iError) {
log_quit("%s:%d : Error in RegisterWinEvents", __FUNCTION__,
__LINE__);
break;
}
XNextEvent(dsp, &event);
switch(event.type) {
case KeyPress:
printf("KeyPress Encountered\n");
break;
printf("KeyRelease Encountered\n");
break;
case ButtonPress:
printf("ButtonPress Encountered\n");
break;
case ButtonRelease:
printf("ButtonRelease Encountered\n");
break;
case MotionNotify:
printf("MotionNotify Encountered\n");
break;
case EnterNotify:
printf("EnterNotify Encountered\n");
break;
case LeaveNotify:
printf("LeaveNotify Encountered\n");
break;
}
XCloseDisplay (dsp);
fflush(stdout);
}
}
int RegisterWinEvents(DISPLAY **dsp)
{
Window window_id;
char *win_name;
int iError = 0;
XSetWindowAttributes attr;
XWindowAttributes wattr;
Window root_return, parent_return;
Window root;
Window client;
Window *children_return = NULL;
unsigned int num_children = 0;
Status status;
int i;
time_t t;
iError = WDGetRoot(&root, dsp);
if (iError == -1) {
return -1;
}
status = XQueryTree (*dsp, root, &root_return,
&parent_return, &children_return,
&num_children);
for(i = 0; i < num_children; i++)
{
attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | EnterWindowMask |
LeaveWindowMask | PointerMotionMask |
Button1MotionMask |
Button2MotionMask | Button3MotionMask |
Button4MotionMask | Button5MotionMask |
ButtonMotionMask | KeymapStateMask |
ExposureMask | VisibilityChangeMask |
StructureNotifyMask | /* ResizeRedirectMask | */
SubstructureNotifyMask | SubstructureRedirectMask |
FocusChangeMask | PropertyChangeMask |
ColormapChangeMask;// | OwnerGrabButtonMask;
status = XGetWindowAttributes(*dsp, children_return[i], &wattr);
if (wattr.all_event_masks & ButtonPressMask)
attr.event_mask &= ~ButtonPressMask;
attr.event_mask &= ~SubstructureRedirectMask;
XSelectInput(*dsp, children_return[i], attr.event_mask);
}
XFree(children_return);
return 0;
}
WINDOW WDGetRootWindow(DISPLAY* pDisplay, INT iScreen)
{
return RootWindow(pDisplay,iScreen);
}
int WDGetRoot(Window *root, DISPLAY **pDisplay)
{
INT iScreen = 0;
setlocale(LC_CTYPE, "");
//Initialize the Display
if((*pDisplay = WDOpenDisplay(NULL))) {
//Get the sceen associated with Display
iScreen = WDGetScreenOfDisplay(*pDisplay);
//Once we have the screen , we need to get the rootwindow associated
//with the screen so that we can traverse the window tree and get the
//window with current focus (the active window)
*root = WDGetRootWindow(*pDisplay, iScreen);
} else {
return -1;
}
return 0;
}
With the above code I am able to capture the mouse pointer movement on the title bar of all windows but am unable to capture any movement when the mouse pointer is inside the window (eg text part of an office writer etc) .
What more I have to add to the code for it to work to capture mouse movement across the entire window ?
XQueiryPointer claims to be able to return coordinates in the window.
The XQueryPointer function returns ... the pointer coordinates
relative to the root window's origin.
Try that combined with your call to XQueryTree