Hi,

I'm interested in selecting a window and being able to grab buttonpress events of the mouse. The problem is that when I try to apply the ButtonPressMask via the XSelectInput function, I get the following error while running the program:

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: 26
Current serial number in output stream: 28
I think that XSelectInput uses XChangeWindowAttributes in order to change the event masks of the selected window. Here's what I found about XChangeWindowAttributes in the Xlib Programming manual :

Multiple clients can select input on the same window. Their event masks are maintained separately. When an event is generated, it is reported to all interested clients. However, only one client at a time can select for SubstructureRedirectMask ResizeRedirectMask and ButtonPressMask If a client attempts to select any of these event masks and some other client has already selected one, a BadAccess error results. There is only one do-not-propagate-mask for a window, not one per client.
So it means that another client has selected the ButtonPressMask, so is the ButtonPressMask already selected. So it means I shoul be able to catch ButtonPress events.. In fact not really, I can't catch those events while not putting the ButtonPressMask with XSelectInput. So what do I need to do?

Here's the code for the Select_Window I use, it's part of the dsimple.c file available in the xorg community:
Code:
Window Select_Window(dpy)
     Display *dpy;
{
  int status;
  Cursor cursor;
  XEvent event;
  Window target_win = None, root = RootWindow(dpy,screen);
  int buttons = 0;

  /* Make the target cursor */
  cursor = XCreateFontCursor(dpy, XC_crosshair);

  /* Grab the pointer using target cursor, letting it room all over */
  status = XGrabPointer(dpy, root, False,
			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
			GrabModeAsync, root, cursor, CurrentTime);
  if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");

  /* Let the user select a window... */
  while ((target_win == None) || (buttons != 0)) {
    /* allow one more event */
    XAllowEvents(dpy, SyncPointer, CurrentTime);
    XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
    switch (event.type) {
    case ButtonPress:
      if (target_win == None) {
	target_win = event.xbutton.subwindow; /* window selected */
	if (target_win == None) target_win = root;
      }
      buttons++;
      break;
    case ButtonRelease:
      if (buttons > 0) /* there may have been some down before we started */
	buttons--;
       break;
    }
  }

  XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */

  return(target_win);
}
... And here's the really basic and not optimized code I use in order to manage events. It works as long as I create my own window, but when commenting XCreateSimpleWindow and uncommenting Select_Window, it crashes with the usual error as mentioned earlier in this post.

Code:
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>

extern "C"{
	#include "dsimple.h"
}

#include <iostream>
using namespace std;

static Window selectWindow(Display* dpy);

GC      gc;
Display *display;
int     screen;
Window  win, root;
unsigned long white_pixel, black_pixel;

int x, y, bidon, i = 0;

int main() {
	if ((display = XOpenDisplay ("")) == NULL) {
		fprintf (stderr, "Can't open Display\n");
		exit (1);
	}
	gc = DefaultGC (display, screen);
	screen = DefaultScreen (display);
	root = RootWindow (display, screen);
	white_pixel = WhitePixel (display, screen);
	black_pixel = BlackPixel (display, screen);
	win = XCreateSimpleWindow (display, root,
			     0, 0, 200, 100, 5, black_pixel, white_pixel);
//	win = Select_Window(display);

	  XSelectInput (display, win, PointerMotionMask |
			ExposureMask | SubstructureNotifyMask | ExposureMask | StructureNotifyMask | PropertyChangeMask
			| ButtonPressMask);
	  XStoreName (display, win, "Example");
	  XMapWindow (display, win);

	  for (;;) {
		  XEvent ev;
		  char buf[40];
		  XNextEvent (display, &ev);
		  switch (ev.type) {
		  case Expose :
			  XDrawString (display, win, gc, 10, 30, "This is a window example.", 24);
			  break ;
		  case MapNotify:
			  cout << "Window has been mapped !" << endl;
		  case MotionNotify :
			  cout << "MotionNotify event" << endl;
			  break ;
		  case ButtonPress  :
			  cout << "ButtonPress event" << endl;
			  break;
		default :
			break;
		}
	  }
	  return 0;
}
If anyone has any idea I could manage to get ButtonPress events while still being able to select a window like I do, I would really appreciate.

Thank you,

Jerome