Xpra: Ticket #553: Xpra Cursor Vanishing on Certain Websites in Firefox and Lazarus Browser

The pointer is disappearing in certain websites.

It is reproducible in Firefox and in Lazarus Browser on the website http://www.crackle.com/c/sleuth by hovering over the flash preview, which causes the pointer to vanish. It will only reappear if you hover over text, or something that changes the pointer to a hand. In Lazarus browser, hovering back over white space causes the pointer to vanish again. In Firefox, repeating this, the pointer does not vanish, it just goes back to the normal pointer. In Chrome, the pointer will vanish when it's supposed to, but moving the pointer causes it to immediately reappear. On local Firefox, after hovering over text then back over whitespace, the cursor will vanish for a fraction of a second, then reappear.

I'll attach the full logs from the 3 different browser tests

Pulled from the logs, here are the interesting parts:

Lazarus Browser, making pointer vanish, then hover over text, then over whitespace causing the pointer to vanish again:

2014-03-28 12:02:53,230 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 12:02:53,371 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:02:53,371 new cursor at 8,8 with serial=25, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:02:54,286 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 12:02:55,931 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:02:55,931 new cursor at 8,8 with serial=26, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:02:57,674 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:02:57,809 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:02:57,809 new cursor at 8,8 with serial=26, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:02:57,927 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:02:59,654 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:02:59,654 new cursor at 8,8 with serial=26, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:03:00,377 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:03:00,992 server cursor sizes: default=66, max=(64, 64)

With Firefox, doing something similar:

2014-03-28 13:04:52,088 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 13:04:54,822 server cursor sizes: default=66, max=(64, 64)
2014-03-28 13:04:54,822 new cursor at 8,8 with serial=93, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 13:04:55,454 setting new cursor by name: hand2=<enum GDK_HAND2 of type GdkCursorType>
2014-03-28 13:04:55,927 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 13:04:57,072 server cursor sizes: default=66, max=(64, 64)
2014-03-28 13:04:57,072 new cursor at 8,8 with serial=94, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-03-28 13:05:00,038 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 13:05:00,813 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 13:05:02,141 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 13:05:04,469 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 13:05:05,390 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-03-28 13:05:06,546 setting new cursor by name: hand2=<enum GDK_HAND2 of type GdkCursorType>

Similar test in Chrome:

(I had about 40 lines of these before I started the test while typing in the address)
2014-03-28 12:08:42,980 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:08:42,980 new cursor at 6,4 with  serial=39, dimensions: 24x24, len(pixels)=2304, default cursor size is 32, maximum=(32, 32)
----------------------
2014-03-28 12:08:43,220 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:08:43,220 new cursor at 1,1 with serial=43, dimensions: 1x1, len(pixels)=4, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:08:45,779 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:08:48,335 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:08:48,335 new cursor at 1,1 with serial=43, dimensions: 1x1, len(pixels)=4, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:08:49,584 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:08:52,700 server cursor sizes: default=66, max=(64, 64)
2014-03-28 12:08:52,700 new cursor at 1,1 with serial=43, dimensions: 1x1, len(pixels)=4, default cursor size is 32, maximum=(32, 32)
2014-03-28 12:08:53,256 setting new cursor by name: hand2=<enum GDK_HAND2 of type GdkCursorType>
2014-03-28 12:08:54,019 setting new cursor by name: xterm=<enum GDK_XTERM of type GdkCursorType>
2014-03-28 12:08:57,197 server cursor sizes: default=66, max=(64, 64)


Fri, 28 Mar 2014 20:27:08 GMT - J. Max Mena: attachment set

full logs of the test using lazarus browser


Fri, 28 Mar 2014 20:27:34 GMT - J. Max Mena: attachment set

cursor test using chrome


Fri, 28 Mar 2014 20:27:54 GMT - J. Max Mena: attachment set

cursor test using firefox


Fri, 28 Mar 2014 20:39:00 GMT - J. Max Mena:

I forgot to mention, but this was all running in Windows 7 using r5903.


Sat, 29 Mar 2014 01:31:54 GMT - Antoine Martin: owner changed

Rather than showing dozens of pointer changes, it would be useful to know which ones are causing the cursor to disappear.

At least with chrome, it is pretty clear that we're doing as we are told:

new cursor at 1,1 with serial=43, dimensions: 1x1

And creating a 1 pixel cursor (a 1 pixel cursor is often used by applications to hide the cursor since there is no API for hiding the cursor). So my guess is that the application has chosen to hide the cursor, and we honour it. Having the server log may help.


Tue, 01 Apr 2014 20:13:36 GMT - alas:

Testing again, solely with firefox (lazarus is even more problematic, as usual), win32 client 0.12.2 r5975; fedora 19 server 0.12.2 r5975.

I simplified the repro to simply navigating to http://www.crackle.com/c/sleuth, mousing over the video window & waiting a couple of seconds for the cursor to disappear, then moving the cursor to some "unoccupied" space of the window above the video frame.

Once the mouse is moved (while over the video frame) the cursor "reappears" as a left pointer arrow.

However, after a couple of seconds over the "unoccupied" region of the window, the cursor disappears again (not expected) and it doesn't reappear while the mouse is moved back and forth in the "unoccupied" region of the window.

(With the lazarus browser, this failure to send_cursor() as no longer being '' seems to actually spill over to other tabs, leaving an invisible cursor over news site text areas, some site's widgets, etc.)

I'll attach server-side and client-side logs with -d mouse,cursor output. From what I can tell though, the "disappearance" of the cursor, followed by its "reappearance" over the video reads as follows:

Client-side:

2014-04-01 12:37:48,841 server cursor sizes: default=66, max=(64, 64)
2014-04-01 12:37:48,842 new cursor at 8,8 with serial=6, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-04-01 12:37:49,849 do_motion_notify_event(<gtk.gdk.Event at 080B2EF0: GDK_MOTION_NOTIFY x=591.00, y=292.00>) wid=1, pointer=(599, 322), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:49,854 do_motion_notify_event(<gtk.gdk.Event at 080B2E48: GDK_MOTION_NOTIFY x=590.00, y=286.00>) wid=1, pointer=(598, 316), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:49,861 do_motion_notify_event(<gtk.gdk.Event at 080B2E48: GDK_MOTION_NOTIFY x=590.00, y=282.00>) wid=1, pointer=(598, 312), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:49,869 do_motion_notify_event(<gtk.gdk.Event at 080B2E48: GDK_MOTION_NOTIFY x=589.00, y=276.00>) wid=1, pointer=(597, 306), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:49,887 do_motion_notify_event(<gtk.gdk.Event at 080B2EF0: GDK_MOTION_NOTIFY x=589.00, y=266.00>) wid=1, pointer=(597, 296), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:49,917 setting new cursor by name: left_ptr=<enum GDK_LEFT_PTR of type GdkCursorType>
2014-04-01 12:37:49,924 do_motion_notify_event(<gtk.gdk.Event at 080B28A8: GDK_MOTION_NOTIFY x=587.00, y=248.00>) wid=1, pointer=(595, 278), modifiers=['mod2'], buttons=[]

Server side:

2014-04-01 12:37:48,929 cursor_event: <X11Event {'delivered_to': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'send_event': 0, 'cursor_serial': 6L, 'window': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'cursor_name': None, 'serial': 4063L, 'type': 87, 'display': <gtk.gdk.Display object at 0x7f279353e460 (GdkDisplayX11 at 0x10c5230)>}>
2014-04-01 12:37:48,940 send_cursor() cursor=[600, 328, 16, 16, 8, 8, 6L, '1024 bytes', '']
2014-04-01 12:37:49,996 raising WindowModel(0xa0007f)
2014-04-01 12:37:49,996 move_pointer(1, (599, 322))
2014-04-01 12:37:50,001 cursor_event: <X11Event {'delivered_to': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'send_event': 0, 'cursor_serial': 5L, 'window': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'cursor_name': 'left_ptr', 'serial': 4328L, 'type': 87, 'display': <gtk.gdk.Display object at 0x7f279353e460 (GdkDisplayX11 at 0x10c5230)>}>
2014-04-01 12:37:50,006 raising WindowModel(0xa0007f)
2014-04-01 12:37:50,007 move_pointer(1, (598, 312))
2014-04-01 12:37:50,014 send_cursor() cursor=[598, 312, 24, 24, 7, 4, 5L, '2304 bytes', 'left_ptr']

While the "disappearance", followed by motion with no "reappearance" reads, as sort of expected to read.

Client side:

2014-04-01 12:37:50,710 do_motion_notify_event(<gtk.gdk.Event at 080B2E78: GDK_MOTION_NOTIFY x=585.00, y=23.00>) wid=1, pointer=(593, 53), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:51,645 server cursor sizes: default=66, max=(64, 64)
2014-04-01 12:37:51,647 new cursor at 8,8 with serial=7, dimensions: 16x16, len(pixels)=1024, default cursor size is 32, maximum=(32, 32)
2014-04-01 12:37:52,977 do_motion_notify_event(<gtk.gdk.Event at 080B2F50: GDK_MOTION_NOTIFY x=585.00, y=22.00>) wid=1, pointer=(593, 52), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:52,983 do_motion_notify_event(<gtk.gdk.Event at 080B2E18: GDK_MOTION_NOTIFY x=582.00, y=22.00>) wid=1, pointer=(590, 52), modifiers=['mod2'], buttons=[]
2014-04-01 12:37:52,994 do_motion_notify_event(<gtk.gdk.Event at 080B2D88: GDK_MOTION_NOTIFY x=577.00, y=22.00>) wid=1, pointer=(585, 52), modifiers=['mod2'], buttons=[]

Server side:

2014-04-01 12:37:50,872 move_pointer(1, (593, 53))
2014-04-01 12:37:51,675 cursor_event: <X11Event {'delivered_to': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'send_event': 0, 'cursor_serial': 7L, 'window': <gtk.gdk.Window object at 0x17fe050 (GdkWindow at 0xf51360)>, 'cursor_name': None, 'serial': 4921L, 'type': 87, 'display': <gtk.gdk.Display object at 0x7f279353e460 (GdkDisplayX11 at 0x10c5230)>}>
2014-04-01 12:37:51,686 send_cursor() cursor=[593, 53, 16, 16, 8, 8, 7L, '1024 bytes', '']
2014-04-01 12:37:53,123 raising WindowModel(0xa0007f)
2014-04-01 12:37:53,123 move_pointer(1, (593, 52))
2014-04-01 12:37:53,129 raising WindowModel(0xa0007f)
2014-04-01 12:37:53,130 move_pointer(1, (590, 52))

In each case, the logs show no "reappearance" when the cursor is not "reappearing". Any thoughts on other -d options that might capture what is happening properly in the case of the mouse movement "over" the video frame vs. mouse movement over the "unoccupied" portion of the window?


Tue, 01 Apr 2014 20:15:25 GMT - alas: attachment set

ticket 553 -d cursor,mouse client test logs


Tue, 01 Apr 2014 20:16:16 GMT - alas: attachment set

ticket 553 -d cursor,mouse server side logs r5975


Wed, 02 Apr 2014 01:29:08 GMT - Antoine Martin:

The difference between the two is the missing cursor_event.

This is the event the browser uses to request a cursor change. If we don't receive it, there is nothing we can do.

I very much doubt that we lose X11 events, and adding -d x11 or -d verbose (or even both, maybe also -d focus), will swamp your server log file... which you can then try to grep or search for "cursor".

I suspect that this won't help much, this is probably an issue with the embedded flash player. Does this happen with any other player or just this one? HTML5? Does it happen with browsers that have flash embedded without a plugin (like chrome I believe)? It's almost as if the browser thinks that the player has the focus it passes mouse motion events to it, then the player decides what shape it should have.

It would probably be easier to add debugging to your application on the code that does handle cursor and shape changes, rather than trying to infer what is going on from the missing events we don't receive..

Another thing worth checking is latest trunk (just in case), and going as far back as possible (maybe v0.5 or even older - will require an older client to go further back)


Tue, 15 Apr 2014 20:08:00 GMT - alas:

Double checking with google-chrome, I find that the cursor is behaving as expected, rather than disappearing - which makes it seem likely to be a bug in how the webkit browsers are interacting with the video player, rather than anything in the xpra.

That said, I suppose this ticket could be closed, and a new one opened if the browser's handling of the pointer state is fixed and problems remain for the xpra handling of that... in the future.


Fri, 01 Aug 2014 13:09:35 GMT - Antoine Martin: status changed; resolution set

OK, closing.


Sat, 23 Jan 2021 04:59:10 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/553