Samuel Thibault, on jeu. 21 déc. 2017 17:50:54 +0100, wrote:
> One additionnal piece of information: it seems that what makes compiz
> have the issue (compared to my simple X root event listener) is the call
> to
>
> XSetInputFocus (s->dpy (), priv->id, RevertToPointerRoot, CurrentTime);
>
> on the window that after that acquires the grab.
Here are reproducers.
- First run focus-grab on a bare X server
- then run grab, which opens a window on the top left corner.
- Move the mouse to it.
-> in focus-grab the enter notify handler calls XSetInputFocus [*]
- press the g key
The result is this: On the ./grab side:
focus out 4194305 0
focus in 4194305 0
0: ||
1: |g|
0:1|g|
res 0
I.e. it got the 'g' keypress event, and successfully called XGrabKeyboard.
And on the ./focus-grab side:
started
create 4194305
enter 4194305 0
1
core focus out 4194305 0
core focus out 38 0
core focus out 38 0
core focus in 38 0
core focus in 4194305 0
focus out 6 0
key press 7 7 77 0
key press 7 7 42 0
key release 7 7 42 0
I.e. it saw the creation of the window, catched entering the window
and set XSetInputFocus, which generate focus events, then saw the 'g'
keypress (77 is my numlock) but didn't see any grab-related focus
events. That's my concern.
Samuel
[*] I know it's useless since that's the X server default, but calling
it that way avoids to put into the reproducer the machinery of catching
clicks etc. to call XSetInputFocus at the right point.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>
char hello[]="hello, World.";
char hi[]="Hi!";
int main (int argc, char **argv) {
Display *mydisplay;
Window mywindow;
XEvent myevent;
KeySym mykey;
XComposeStatus status;
memset(&status,0,sizeof(status));
int i;
char text[10];
int done;
mydisplay=XOpenDisplay("");
mywindow = DefaultRootWindow(mydisplay);
XSelectInput(mydisplay, DefaultRootWindow(mydisplay),
SubstructureNotifyMask |
StructureNotifyMask |
EnterWindowMask |
FocusChangeMask );
int xi_opcode = -1;
int first_event, first_error;
if (XQueryExtension(mydisplay, "XInputExtension", &xi_opcode, &first_event, &first_error))
{
int major = 2;
int minor = 1;
if (XIQueryVersion(mydisplay, &major, &minor) != BadRequest) {
XIEventMask eventmask;
unsigned char mask[XIMaskLen (XI_LASTEVENT)] = { 0 };
eventmask.deviceid = XIAllDevices;
eventmask.mask_len = sizeof(mask);
eventmask.mask = mask;
XISetMask (mask, XI_KeyPress);
XISetMask (mask, XI_KeyRelease);
XISetMask (mask, XI_ButtonPress);
XISetMask (mask, XI_ButtonRelease);
XISetMask (mask, XI_Motion);
XISetMask (mask, XI_FocusIn);
XISetMask (mask, XI_FocusOut);
XISelectEvents (mydisplay, mywindow, &eventmask, 1);
}
}
done=0;
fprintf(stderr,"started\n");
while(done==0) {
XNextEvent (mydisplay, &myevent);
switch(myevent.type) {
case KeyPress:
i = XLookupString(&myevent.xkey, text, 10, &mykey, &status);
fprintf(stderr,"%d: |%s|\n",i,text);
if (i == 1 /*len*/ && text[0] == 'q') done = 1;
char buf[128];
int foo;
if (XkbTranslateKeySym(mydisplay, &mykey, 0, buf, sizeof(buf), &foo))
fprintf(stderr,"%d:%ld|%s|\n", foo, strlen(buf), buf);
break;
case KeyRelease:
break;
case FocusIn:
fprintf(stderr, "core focus in %ld %d\n", myevent.xfocus.window, myevent.xfocus.mode);
break;
case FocusOut:
fprintf(stderr, "core focus out %ld %d\n", myevent.xfocus.window, myevent.xfocus.mode);
break;
case EnterNotify:
fprintf(stderr, "enter %ld %d\n", myevent.xcrossing.window, myevent.xcrossing.mode);
printf("%d\n", XSetInputFocus (mydisplay, myevent.xcrossing.window, RevertToPointerRoot, CurrentTime));
break;
case LeaveNotify:
fprintf(stderr, "leave %ld %d\n", myevent.xcrossing.window, myevent.xcrossing.mode);
break;
case GenericEvent:
if (myevent.xcookie.extension == xi_opcode) {
XGetEventData(mydisplay, &myevent.xcookie);
XIRawEvent *xiRawEv = (XIRawEvent *) myevent.xcookie.data;
XIDeviceEvent *xiDevEv = (XIDeviceEvent *) myevent.xcookie.data;
XIEnterEvent *xiEntEv = (XIEnterEvent *) myevent.xcookie.data;
switch (myevent.xcookie.evtype) {
case XI_KeyPress:
fprintf(stderr,"key press %d %d %d %x\n", xiRawEv->deviceid, xiRawEv->sourceid, xiRawEv->detail, xiDevEv->flags);
break;
case XI_KeyRelease:
fprintf(stderr,"key release %d %d %d %x\n", xiRawEv->deviceid, xiRawEv->sourceid, xiRawEv->detail, xiDevEv->flags);
break;
case XI_FocusIn:
fprintf(stderr, "focus in %d %d\n", xiEntEv->detail, xiEntEv->mode);
break;
case XI_FocusOut:
fprintf(stderr, "focus out %d %d\n", xiEntEv->detail, xiEntEv->mode);
break;
}
XFreeEventData(mydisplay, &myevent.xcookie);
} else {
fprintf(stderr,"generic mesg %d %d\n", myevent.xcookie.extension, xi_opcode);
}
break;
case CreateNotify:
{
Window win = myevent.xcreatewindow.window;
fprintf(stderr, "create %ld\n", win);
XSelectInput(mydisplay, win, FocusChangeMask | SubstructureNotifyMask |EnterWindowMask );
break;
}
case MapRequest:
XMapWindow(mydisplay, myevent.xmaprequest.window);
break;
}
}
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>
int main (int argc, char **argv) {
Display *mydisplay, *mydisplay2;
Window mywindow;
XEvent myevent;
KeySym mykey;
XSizeHints myhint;
XComposeStatus status;
memset(&status,0,sizeof(status));
int myscreen;
unsigned long myforeground, mybackground, valuemask;
XSetWindowAttributes xswa;
int i;
char text[10];
int done;
mydisplay=XOpenDisplay("");
myscreen=DefaultScreen(mydisplay);
mybackground=WhitePixel(mydisplay, myscreen);
myforeground=BlackPixel(mydisplay, myscreen);
myhint.x=0; myhint.y=0;
myhint.width=400; myhint.height=400;
myhint.flags=PPosition|PSize;
mywindow=XCreateSimpleWindow(mydisplay, DefaultRootWindow (mydisplay), myhint.x, myhint.y, myhint.width, myhint.height, 5 /*border*/, myforeground, mybackground);
XSetWindowBackgroundPixmap(mydisplay, mywindow, None);
XMapRaised(mydisplay, mywindow);
XSelectInput(mydisplay, mywindow, FocusChangeMask | KeyPressMask);
while(1) {
XNextEvent (mydisplay, &myevent);
switch(myevent.type) {
case MappingNotify:
XRefreshKeyboardMapping(&myevent.xmapping);
break;
case ButtonPress:
fprintf(stderr,"button press\n");
break;
case KeyPress:
i = XLookupString(&myevent.xkey, text, 10, &mykey, &status);
fprintf(stderr,"%d: |%s|\n",i,text);
if (i == 1 /*len*/ && text[0] == 'q') done = 1;
char buf[128];
int foo;
if (XkbTranslateKeySym(mydisplay, &mykey, 0, buf, sizeof(buf), &foo))
fprintf(stderr,"%d:%d|%s|\n", foo, strlen(buf), buf);
if (myevent.xkey.keycode == 42)
{
int res;
res = XGrabKeyboard (mydisplay, mywindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
fprintf(stderr,"res %d\n", res);
}
else if (myevent.xkey.keycode == 43)
{
fprintf(stderr,"got h\n");
} else if (myevent.xkey.keycode == 38)
exit(1);
break;
case KeyRelease:
break;
case FocusIn:
fprintf(stderr, "focus in %d %d\n", myevent.xfocus.window, myevent.xfocus.mode);
break;
case FocusOut:
fprintf(stderr, "focus out %d %d\n", myevent.xfocus.window, myevent.xfocus.mode);
break;
default:
fprintf(stderr,"mesg %d\n", myevent.type);
}
}
}
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel