Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[X11] fix cursor jumping when grabbed #834

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 102 additions & 80 deletions src/input/x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

static Display *display;
static Window window;
static XEvent event;

static Atom wm_deletemessage;

Expand All @@ -46,101 +47,122 @@ static const char data[1] = {0};
static Cursor cursor;
static bool grabbed = True;

static int motion_x, motion_y;

static int x11_handle_motion_notify() {
motion_x = 0;
motion_y = 0;
int i;
for (
i = 0;
i < 100 &&
XPending(display) &&
XCheckMaskEvent(display, PointerMotionMask, &event);
++i
) {
motion_x = event.xmotion.x - last_x;
motion_y = event.xmotion.y - last_y;
if (abs(motion_x) > 0 || abs(motion_y) > 0) {
if (last_x >= 0 && last_y >= 0)
LiSendMouseMoveEvent(motion_x, motion_y);

last_x = event.xmotion.x;
last_y = event.xmotion.y;
}
}

if (i == 0 && grabbed) {
XWarpPointer(display, None, window, 0, 0, 0, 0, 640, 360);
last_x = 640;
last_y = 360;
}
return i;
}

static int x11_handler(int fd) {
XEvent event;
int button = 0;
int motion_x, motion_y;

while (XPending(display)) {
XNextEvent(display, &event);
switch (event.type) {
case KeyPress:
case KeyRelease:
if (event.xkey.keycode >= 8 && event.xkey.keycode < (sizeof(keyCodes)/sizeof(keyCodes[0]) + 8)) {
if ((keyboard_modifiers & ACTION_MODIFIERS) == ACTION_MODIFIERS && event.type == KeyRelease) {
if (event.xkey.keycode == QUIT_KEY)
return LOOP_RETURN;
else {
grabbed = !grabbed;
XDefineCursor(display, window, grabbed ? cursor : 0);
XPeekEvent(display, &event);
while (x11_handle_motion_notify() > 0) {}
if (XCheckMaskEvent(display, ~PointerMotionMask, &event)) {
switch (event.type) {
case KeyPress:
case KeyRelease:
if (event.xkey.keycode >= 8 && event.xkey.keycode < (sizeof(keyCodes)/sizeof(keyCodes[0]) + 8)) {
if ((keyboard_modifiers & ACTION_MODIFIERS) == ACTION_MODIFIERS && event.type == KeyRelease) {
if (event.xkey.keycode == QUIT_KEY)
return LOOP_RETURN;
else {
grabbed = !grabbed;
XDefineCursor(display, window, grabbed ? cursor : 0);
}
}

int modifier = 0;
switch (event.xkey.keycode) {
case 0x32:
case 0x3e:
modifier = MODIFIER_SHIFT;
break;
case 0x40:
case 0x6c:
modifier = MODIFIER_ALT;
break;
case 0x25:
case 0x69:
modifier = MODIFIER_CTRL;
break;
}

if (modifier != 0) {
if (event.type == KeyPress)
keyboard_modifiers |= modifier;
else
keyboard_modifiers &= ~modifier;
}
}

int modifier = 0;
switch (event.xkey.keycode) {
case 0x32:
case 0x3e:
modifier = MODIFIER_SHIFT;
short code = 0x80 << 8 | keyCodes[event.xkey.keycode - 8];
LiSendKeyboardEvent(code, event.type == KeyPress ? KEY_ACTION_DOWN : KEY_ACTION_UP, keyboard_modifiers);
}
break;
case ButtonPress:
case ButtonRelease:
switch (event.xbutton.button) {
case Button1:
button = BUTTON_LEFT;
break;
case 0x40:
case 0x6c:
modifier = MODIFIER_ALT;
case Button2:
button = BUTTON_MIDDLE;
break;
case 0x25:
case 0x69:
modifier = MODIFIER_CTRL;
case Button3:
button = BUTTON_RIGHT;
break;
case Button4:
LiSendScrollEvent(1);
break;
case Button5:
LiSendScrollEvent(-1);
break;
case 8:
button = BUTTON_X1;
break;
case 9:
button = BUTTON_X2;
break;
}

if (modifier != 0) {
if (event.type == KeyPress)
keyboard_modifiers |= modifier;
else
keyboard_modifiers &= ~modifier;
}

short code = 0x80 << 8 | keyCodes[event.xkey.keycode - 8];
LiSendKeyboardEvent(code, event.type == KeyPress ? KEY_ACTION_DOWN : KEY_ACTION_UP, keyboard_modifiers);
}
break;
case ButtonPress:
case ButtonRelease:
switch (event.xbutton.button) {
case Button1:
button = BUTTON_LEFT;
break;
case Button2:
button = BUTTON_MIDDLE;
break;
case Button3:
button = BUTTON_RIGHT;
if (button != 0)
LiSendMouseButtonEvent(event.type==ButtonPress ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, button);
break;
case Button4:
LiSendScrollEvent(1);
case MotionNotify: //will never happen
break;
case Button5:
LiSendScrollEvent(-1);
break;
case 8:
button = BUTTON_X1;
break;
case 9:
button = BUTTON_X2;
break;
}
case ClientMessage:
if (event.xclient.data.l[0] == wm_deletemessage)
return LOOP_RETURN;

if (button != 0)
LiSendMouseButtonEvent(event.type==ButtonPress ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, button);
break;
case MotionNotify:
motion_x = event.xmotion.x - last_x;
motion_y = event.xmotion.y - last_y;
if (abs(motion_x) > 0 || abs(motion_y) > 0) {
if (last_x >= 0 && last_y >= 0)
LiSendMouseMoveEvent(motion_x, motion_y);

if (grabbed)
XWarpPointer(display, None, window, 0, 0, 0, 0, 640, 360);
break;
}

last_x = grabbed ? 640 : event.xmotion.x;
last_y = grabbed ? 360 : event.xmotion.y;
break;
case ClientMessage:
if (event.xclient.data.l[0] == wm_deletemessage)
return LOOP_RETURN;

break;
}
}

Expand Down