[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#972805: xserver-xorg-core: XWarpPointer() corrupts pointer position when mouse accelerated



Package: xserver-xorg-core
Version: 2:1.20.4-1+deb10u1
Severity: normal
File: /usr/bin/X

Dear Maintainer,

I have been pulling my hair out about this problem.  Programs that make
heavy use of XWarpPointer() (like 'Kicad') were totally broken on my
system.  Turns out that speeding up the mouse using 'xset m' or ' xinput
set-prop xx 147' causes pointer position to become corrupt on the first
mouse-movement, after XWarpPointer() was called.

Below I attached an example program that invokes XWarpPointer() when a
key is pressed inside the window.  Bug consistently reproducable via:

 * compile test

   gcc -lX11 -Wall testwrap.c -o testwrap

 * configure your mouse to high speed.

   - find out the ID of your mouse via 'xinput list'.  I.e. for me it
     lists:
   
     Kensington Computer [..] Trackball	id=19	[slave  pointer  (2)]

   - Use that ID to configure a higher speed
   
     input set-prop 19 147 3, 0, 0, 0, 3, 0, 0, 0, 1 

   - ('xset mouse 3 0' also sometimes triggers the bug, however it only
      seems to act on the first connected mouse and none of the
      hot-plugged mice.)

 * invoke ./testwrap, place mouse cursor inside black window

 * Make sure the mouse is steady and press any key.  Observe the mouse
   pointer jumping to the top-left of the window.  That's what it should
   do.

 * now move the mouse just a little.

   - I expect: mouse moves just a little
   
   - What happens: mouse jumps to the bottom-right-most corner of the
     screen
   
 * without accelerating the mouse, this does not happen.  Exactly same
   mis-behaviour happening in Kicad on most GUI operations.  Makes Kicad
   mostly unusable.

The only workaround (other than giving up on accelerating the mouse) for
me currently is to use LD_PRELOAD to fully disable XWarpPointer() for
e.g. Kicad.

cheers,

David

/* derived from examples found here:
 * http://xopendisplay.hilltopia.ca/index.html */
#include <X11/Xlib.h>
#include <stdio.h>

int main(int argc, char ** argv){
	int screen_num, width, height;
	unsigned long background, border;
	Window win;
	XEvent ev;
	Display *dpy;

	/* First connect to the display server */
	dpy = XOpenDisplay(NULL);
	if (!dpy) {fprintf(stderr, "unable to connect to display\n");return 7;}

	screen_num = DefaultScreen(dpy);
	background = BlackPixel(dpy, screen_num);
	border = WhitePixel(dpy, screen_num);

	width = 320;
	height = 200;

	win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), /* display, parent */
		0,0, /* x, y: the window manager will place the window elsewhere */
		width, height, /* width, height */
		2, border, /* border width & colour, unless you have a window manager */
		background); /* background colour */

	/* tell the display server what kind of events we would like to see */
	XSelectInput(dpy, win, ButtonPressMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask|KeymapStateMask);

	/* okay, put the window on the screen, please */
	XMapWindow(dpy, win);

	/* as each event that we asked about occurs, we respond.  In this
	 * case we note if the window's shape changed, and exit if a button
	 * is pressed inside the window */
	while(1){
		XNextEvent(dpy, &ev);
		switch(ev.type){
		case KeymapNotify:
			XRefreshKeyboardMapping(&ev.xmapping);
			break;
		case KeyPress: break; /* ignore these */
		case KeyRelease:
                           XWarpPointer(dpy, None, win, 0, 0, 0, 0, 5, 5);
			break;
		case ButtonPress:
			XCloseDisplay(dpy);
			return 0;
		}
	}
}

Reply to: