mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 22:01:46 +00:00
[client] x11: switch to using XInput2 for all events and warp
On platforms like KDE, mixing X core events with XInput2 events causes issues, so just switch entirely over to XInput2.
This commit is contained in:
parent
da65c47245
commit
ac3333c0d2
2 changed files with 202 additions and 86 deletions
|
@ -38,6 +38,9 @@ struct X11DSState
|
|||
Window window;
|
||||
int xinputOp;
|
||||
|
||||
int pointerDev;
|
||||
int keyboardDev;
|
||||
|
||||
bool pointerGrabbed;
|
||||
bool keyboardGrabbed;
|
||||
bool entered;
|
||||
|
@ -81,12 +84,14 @@ static void x11CBXFixesSelectionNotify(const XFixesSelectionNotifyEvent e);
|
|||
|
||||
static bool x11Init(SDL_SysWMinfo * info)
|
||||
{
|
||||
XIDeviceInfo *devinfo;
|
||||
int count;
|
||||
int event, error;
|
||||
|
||||
memset(&x11, 0, sizeof(x11));
|
||||
x11.display = info->info.x11.display;
|
||||
x11.window = info->info.x11.window;
|
||||
|
||||
int event, error;
|
||||
|
||||
int major = 2;
|
||||
int minor = 3;
|
||||
if (XIQueryVersion(x11.display, &major, &minor) != Success)
|
||||
|
@ -100,8 +105,7 @@ static bool x11Init(SDL_SysWMinfo * info)
|
|||
XQueryExtension(x11.display, "XInputExtension", &x11.xinputOp, &event, &error);
|
||||
|
||||
int num_masks;
|
||||
XIEventMask * mask = XIGetSelectedEvents(x11.display,
|
||||
DefaultRootWindow(x11.display), &num_masks);
|
||||
XIEventMask * mask = XIGetSelectedEvents(x11.display, x11.window, &num_masks);
|
||||
if (!mask)
|
||||
{
|
||||
DEBUG_ERROR("Failed to get the XInput event mask");
|
||||
|
@ -110,15 +114,16 @@ static bool x11Init(SDL_SysWMinfo * info)
|
|||
|
||||
for(int i = 0; i < num_masks; ++i)
|
||||
{
|
||||
XISetMask(mask[i].mask, XI_RawButtonPress );
|
||||
XISetMask(mask[i].mask, XI_RawButtonRelease);
|
||||
XISetMask(mask[i].mask, XI_RawMotion );
|
||||
XISetMask(mask[i].mask, XI_RawKeyPress );
|
||||
XISetMask(mask[i].mask, XI_RawKeyRelease );
|
||||
XISetMask(mask[i].mask, XI_Motion );
|
||||
XISetMask(mask[i].mask, XI_FocusIn );
|
||||
XISetMask(mask[i].mask, XI_FocusOut );
|
||||
XISetMask(mask[i].mask, XI_Enter );
|
||||
XISetMask(mask[i].mask, XI_Leave );
|
||||
XISetMask(mask[i].mask, XI_KeyPress );
|
||||
XISetMask(mask[i].mask, XI_KeyRelease);
|
||||
}
|
||||
|
||||
if (XISelectEvents(x11.display, DefaultRootWindow(x11.display),
|
||||
mask, num_masks) != Success)
|
||||
if (XISelectEvents(x11.display, x11.window, mask, num_masks) != Success)
|
||||
{
|
||||
XFree(mask);
|
||||
DEBUG_ERROR("Failed to select the xinput events");
|
||||
|
@ -127,6 +132,62 @@ static bool x11Init(SDL_SysWMinfo * info)
|
|||
|
||||
XFree(mask);
|
||||
|
||||
devinfo = XIQueryDevice(x11.display, XIAllDevices, &count);
|
||||
if (!devinfo)
|
||||
{
|
||||
DEBUG_ERROR("XIQueryDevice failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool havePointer = false;
|
||||
bool haveKeyboard = false;
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
/* look for the master pointing device */
|
||||
if (!havePointer && devinfo[i].use == XIMasterPointer)
|
||||
for(int j = 0; j < devinfo[i].num_classes; ++j)
|
||||
{
|
||||
XIAnyClassInfo *cdevinfo =
|
||||
(XIAnyClassInfo *)(devinfo[i].classes[j]);
|
||||
if (cdevinfo->type == XIValuatorClass)
|
||||
{
|
||||
havePointer = true;
|
||||
x11.pointerDev = devinfo[i].deviceid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* look for the master keyboard device */
|
||||
if (!haveKeyboard && devinfo[i].use == XIMasterKeyboard)
|
||||
for(int j = 0; j < devinfo[i].num_classes; ++j)
|
||||
{
|
||||
XIAnyClassInfo *cdevinfo =
|
||||
(XIAnyClassInfo *)(devinfo[i].classes[j]);
|
||||
if (cdevinfo->type == XIKeyClass)
|
||||
{
|
||||
haveKeyboard = true;
|
||||
x11.keyboardDev = devinfo[i].deviceid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!havePointer)
|
||||
{
|
||||
DEBUG_ERROR("Failed to find the master pointing device");
|
||||
XIFreeDeviceInfo(devinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!haveKeyboard)
|
||||
{
|
||||
DEBUG_ERROR("Failed to find the master keyboard device");
|
||||
XIFreeDeviceInfo(devinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
XIFreeDeviceInfo(devinfo);
|
||||
|
||||
Atom NETWM_BYPASS_COMPOSITOR = XInternAtom(x11.display,
|
||||
"NETWM_BYPASS_COMPOSITOR", False);
|
||||
|
||||
|
@ -218,6 +279,8 @@ static bool x11EventFilter(SDL_Event * event)
|
|||
case SDL_WINDOWEVENT_CLOSE:
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -258,60 +321,6 @@ static bool x11EventFilter(SDL_Event * event)
|
|||
return true;
|
||||
}
|
||||
|
||||
case FocusIn:
|
||||
if (xe.xfocus.mode != NotifyNormal)
|
||||
return true;
|
||||
|
||||
x11.focused = true;
|
||||
app_handleFocusEvent(true);
|
||||
return true;
|
||||
|
||||
case FocusOut:
|
||||
if (xe.xfocus.mode != NotifyNormal)
|
||||
return true;
|
||||
|
||||
x11.focused = false;
|
||||
app_handleFocusEvent(false);
|
||||
return true;
|
||||
|
||||
case EnterNotify:
|
||||
{
|
||||
int x, y;
|
||||
Window child;
|
||||
XTranslateCoordinates(
|
||||
x11.display,
|
||||
DefaultRootWindow(x11.display),
|
||||
x11.window,
|
||||
xe.xcrossing.x_root, xe.xcrossing.y_root,
|
||||
&x, &y,
|
||||
&child);
|
||||
|
||||
app_updateCursorPos(x, y);
|
||||
app_handleWindowEnter();
|
||||
x11.entered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
case LeaveNotify:
|
||||
{
|
||||
if (xe.xcrossing.mode != NotifyNormal)
|
||||
return true;
|
||||
|
||||
int x, y;
|
||||
Window child;
|
||||
XTranslateCoordinates(x11.display,
|
||||
DefaultRootWindow(x11.display),
|
||||
x11.window,
|
||||
xe.xcrossing.x_root, xe.xcrossing.y_root,
|
||||
&x, &y,
|
||||
&child);
|
||||
|
||||
app_updateCursorPos(x, y);
|
||||
app_handleWindowLeave();
|
||||
x11.entered = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case GenericEvent:
|
||||
{
|
||||
XGenericEventCookie *cookie = (XGenericEventCookie*)&xe.xcookie;
|
||||
|
@ -320,6 +329,77 @@ static bool x11EventFilter(SDL_Event * event)
|
|||
|
||||
switch(cookie->evtype)
|
||||
{
|
||||
case XI_FocusIn:
|
||||
{
|
||||
if (x11.focused)
|
||||
return true;
|
||||
|
||||
XIFocusOutEvent *xie = cookie->data;
|
||||
if (xie->mode != NotifyNormal)
|
||||
return true;
|
||||
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleFocusEvent(true);
|
||||
x11.focused = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_FocusOut:
|
||||
{
|
||||
if (!x11.focused)
|
||||
return true;
|
||||
|
||||
XIFocusOutEvent *xie = cookie->data;
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleFocusEvent(false);
|
||||
x11.focused = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_Enter:
|
||||
{
|
||||
if (x11.entered)
|
||||
return true;
|
||||
|
||||
XIEnterEvent *xie = cookie->data;
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleWindowEnter();
|
||||
x11.entered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_Leave:
|
||||
{
|
||||
if (!x11.entered)
|
||||
return true;
|
||||
|
||||
XILeaveEvent *xie = cookie->data;
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleWindowLeave();
|
||||
x11.entered = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_KeyPress:
|
||||
{
|
||||
if (!x11.focused || x11.keyboardGrabbed)
|
||||
return true;
|
||||
|
||||
XIDeviceEvent *device = cookie->data;
|
||||
app_handleKeyPress(device->detail - 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
if (!x11.focused || x11.keyboardGrabbed)
|
||||
return true;
|
||||
|
||||
XIDeviceEvent *device = cookie->data;
|
||||
app_handleKeyRelease(device->detail - 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
case XI_RawKeyPress:
|
||||
{
|
||||
if (!x11.focused)
|
||||
|
@ -495,16 +575,28 @@ static void x11GrabPointer(void)
|
|||
if (x11.pointerGrabbed)
|
||||
return;
|
||||
|
||||
XGrabPointer(
|
||||
x11.display,
|
||||
x11.window,
|
||||
true,
|
||||
None,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
x11.window,
|
||||
None,
|
||||
CurrentTime);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = {
|
||||
XIAllMasterDevices,
|
||||
sizeof(mask_bits),
|
||||
mask_bits
|
||||
};
|
||||
|
||||
XISetMask(mask.mask, XI_RawButtonPress );
|
||||
XISetMask(mask.mask, XI_RawButtonRelease);
|
||||
XISetMask(mask.mask, XI_RawMotion );
|
||||
|
||||
XIGrabDevice(
|
||||
x11.display,
|
||||
x11.pointerDev,
|
||||
x11.window,
|
||||
CurrentTime,
|
||||
None,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
false,
|
||||
&mask);
|
||||
XSync(x11.display, False);
|
||||
|
||||
x11.pointerGrabbed = true;
|
||||
}
|
||||
|
@ -514,7 +606,9 @@ static void x11UngrabPointer(void)
|
|||
if (!x11.pointerGrabbed)
|
||||
return;
|
||||
|
||||
XUngrabPointer(x11.display, CurrentTime);
|
||||
XIUngrabDevice(x11.display, x11.pointerDev, CurrentTime);
|
||||
XSync(x11.display, False);
|
||||
|
||||
x11.pointerGrabbed = false;
|
||||
}
|
||||
|
||||
|
@ -523,13 +617,28 @@ static void x11GrabKeyboard(void)
|
|||
if (x11.keyboardGrabbed)
|
||||
return;
|
||||
|
||||
XGrabKeyboard(
|
||||
x11.display,
|
||||
x11.window,
|
||||
true,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
CurrentTime);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = {
|
||||
XIAllMasterDevices,
|
||||
sizeof(mask_bits),
|
||||
mask_bits
|
||||
};
|
||||
|
||||
XISetMask(mask.mask, XI_RawKeyPress );
|
||||
XISetMask(mask.mask, XI_RawKeyRelease);
|
||||
|
||||
XIGrabDevice(
|
||||
x11.display,
|
||||
x11.keyboardDev,
|
||||
x11.window,
|
||||
CurrentTime,
|
||||
None,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
false,
|
||||
&mask);
|
||||
|
||||
XSync(x11.display, False);
|
||||
|
||||
x11.keyboardGrabbed = true;
|
||||
}
|
||||
|
@ -539,14 +648,17 @@ static void x11UngrabKeyboard(void)
|
|||
if (!x11.keyboardGrabbed)
|
||||
return;
|
||||
|
||||
XUngrabKeyboard(x11.display, CurrentTime);
|
||||
XIUngrabDevice(x11.display, x11.keyboardDev, CurrentTime);
|
||||
XSync(x11.display, False);
|
||||
|
||||
x11.keyboardGrabbed = false;
|
||||
}
|
||||
|
||||
static void x11WarpPointer(int x, int y, bool exiting)
|
||||
{
|
||||
XWarpPointer(
|
||||
XIWarpPointer(
|
||||
x11.display,
|
||||
x11.pointerDev,
|
||||
None,
|
||||
x11.window,
|
||||
0, 0, 0, 0,
|
||||
|
|
|
@ -1951,7 +1951,7 @@ static int lg_run(void)
|
|||
params.w,
|
||||
params.h,
|
||||
(
|
||||
SDL_WINDOW_SHOWN |
|
||||
SDL_WINDOW_HIDDEN |
|
||||
(params.allowResize ? SDL_WINDOW_RESIZABLE : 0) |
|
||||
(params.borderless ? SDL_WINDOW_BORDERLESS : 0) |
|
||||
(params.maximize ? SDL_WINDOW_MAXIMIZED : 0) |
|
||||
|
@ -1977,6 +1977,10 @@ static int lg_run(void)
|
|||
|
||||
g_state.ds->init(&g_state.wminfo);
|
||||
|
||||
// now init has been done we can show the window, doing this before init for
|
||||
// X11 causes us to miss the first focus event
|
||||
SDL_ShowWindow(g_state.window);
|
||||
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
|
||||
params.minimizeOnFocusLoss ? "1" : "0");
|
||||
|
||||
|
|
Loading…
Reference in a new issue