Hello. After the fixes for #2714 improved so much my quality of life I became encouraged to report some issues I have with xpra. This issue is a little minor, but easy to reproduce, I am betting that a fix on this issue will also cover more severe things that sometimes happen.
The issue is related to drag and drop, and I think it happens on any open program, but i will use gedit here which is easy available for testing.
If i drag something with the mouse, the pointer changes properly to drag and drop pointer (usually some kind of hand instead of the default pointer), then when I release the mouse button the pointer does not return to the original icon (I mean release within the same window, drag and drop across programs is not needed).
I attach pictures for three states when using gedit. Initially in the first.png the pointer is a text selection pointer (like the "I" letter), then i start dragging a text selection i did before and the pointer changes (second.png), finally I release the button and the pointer stays with the hand pointer (third.png) when it should go back to the original form.
I am using one of the latest betas for 3.0.x in the client and server.
Server: "xpra v3.0.9-r26111"
Server operating system: Linux marcelo-vm 5.3.0-46-generic #38~18.04.1-Ubuntu SMP Tue Mar 31 04:17:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Client:
Xpra 3.0.9 Python 3.8, 64bit revision 26113 built on Win7Pro64-PC by Win7 Pro 64 2020-04-13 17:35 using Cython 0.29.16 gcc (Rev2, Built by MSYS2 project) 9.3.0
Extra detail: The pictures I included were doctored a little bit to include the mouse pointer because taking a screenshot on windows does not include the mouse pointer, but the mouse pointers I added are pretty similar to the observed pointers.
The problem only occurs with ms windows clients.
The server is not sending the icon to reset to the cursor, like it does with Linux clients.
This can be seen using XPRA_SAVE_CURSORS=1
on the server. (can be used at both ends too)
With a Linux client, -d cursor,mouse
at both ends (edited):
xtest_fake_button(1, True) xtest_fake_motion(-1, 1853, 443) xtest_fake_motion(-1, 1855, 433) cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5943', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '83', 'cursor_name': 'dnd-none'}> do_send_cursor(..) 24x24 png cursor name='dnd-none', serial=0x53 with delay=10 (cursor_encodings=('raw', 'png')) xtest_fake_motion(-1, 1852, 362) xtest_fake_motion(-1, 1848, 347) cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5a97', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '84', 'cursor_name': 'dnd-move'}> cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5a9d', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '83', 'cursor_name': 'dnd-none'}> cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5a97', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '84', 'cursor_name': 'dnd-move'}> cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5a9d', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '83', 'cursor_name': 'dnd-none'}> do_send_cursor(..) 24x24 png cursor name='dnd-move', serial=0x54 with delay=10 (cursor_encodings=('raw', 'png')) xtest_fake_motion(-1, 1847, 342) xtest_fake_button(1, False) cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5b76', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '1', 'cursor_name': ''}> cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5b77', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '80', 'cursor_name': 'text'}> do_send_cursor(..) 24x24 png cursor name='text', serial=0x50 with delay=10 (cursor_encodings=('raw', 'png')) cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5b89', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '1', 'cursor_name': ''}> cursor_event: <X11:CursorNotify {'send_event': '0', 'serial': '0x5b8b', 'delivered_to': '0x299', 'window': '0x299', 'cursor_serial': '80', 'cursor_name': 'text'}> do_send_cursor(..) cursor identical to the last one we sent, nothing to do
MS Windows clients sometimes work, sometimes not. There is no discernible difference. Once the cursor misses an update, all further cursor updates seem to lag: if I resize the gedit window, the cursor takes the "resizing" shape temporarily, but after clicking into the gedit window it switches back to this shape, long after the operation is finished.
And sure enough... this is a GTK3 bug. I cannot reproduce any problems at all with the GTK2 builds. If this bothers you, download one of the "Python2" builds of the 3.0.x branch.
I will try to find a workaround, if at all possible, in due time - but not for this release.
I would like to share about another phenomenon which seems pretty related and might be a clue for what is happening. If I open firefox, then select some text and drag and drop the text outside the window then firefox misses the even that the mouse was released, and continues to draw the pointer as if I am dragging the text, but not only the pointer, it draws the text copied on top of every other screen. I attach a small screenshot from firefox on CNN.com (mayberelated.png) Even as I am writing this I still get the headlines of CNN over the text I am writing in this form (the firefox window is minimized) (mayberelated2.png). What i am reporting now is the mild version of the problem, some other programs get kind of "stuck" after missing some of these events, not responding for a while or at least not responding properly to mouse clicks.
Sounds like the click release event is not received by the client.
So the server never simulates the xtest_fake_button
to unpress the mouse button.
We could use the GetAsyncKeyState function to detect when we missed the release event, and synthesize one.
We also have to use GetSystemMetrics because The GetAsyncKeyState
function works with mouse buttons. However, it checks on the state of the physical mouse buttons, not on the logical mouse buttons that the physical buttons are mapped to. For example, the call GetAsyncKeyState(VK_LBUTTON)
always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button. You can determine the system's current mapping of physical mouse buttons to logical mouse buttons by calling GetSystemMetrics(SM_SWAPBUTTON)
.
Then there's also bound to be some setups with weird input devices, where the value is going to always be unset, and we don't want to break those... so maybe only check the button state following a button press, and first ensure that the button state matches our initial expectations.
See also #2929
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/2733