> What are the coordinates on these events? That might be a source of
> the problem, where the coordinates are root-relative, so vncviewer
> thinks the cursor is still over its own window.
It is indeed the source of the problem.
If I start in a non-zaphod configuration, this is the
sequence of events:
-----------------------------------------------------------------
DesktopWindow: intercept_handler: type: MotionNotify
DesktopWindow: serial: 1663
DesktopWindow: send_event: True
DesktopWindow: display: 0x16f33a0
DesktopWindow: window: 27263078
DesktopWindow: root: 1731
DesktopWindow: subwindow: 0
DesktopWindow: x: 2
DesktopWindow: y: 200
DesktopWindow: x_root: 1922
DesktopWindow: y_root: 200
DesktopWindow: state: 0
DesktopWindow: is_hint:
DesktopWindow: fltkDispatch: event: FL_MOVE win: 0x1847d80
DesktopWindow: handle: event: FL_MOVE
DesktopWindow: intercept_handler: type: GenericEvent
DesktopWindow: serial: 1663
DesktopWindow: send_event: False
DesktopWindow: display: 0x16f33a0
DesktopWindow: extension: XInputExtension
DesktopWindow: evtype: 6
DesktopWindow: intercept_handler: type: LeaveNotify
DesktopWindow: serial: 1663
DesktopWindow: send_event: False
DesktopWindow: display: 0x16f33a0
DesktopWindow: window: 27263078
DesktopWindow: root: 1731
DesktopWindow: subwindow: 0
DesktopWindow: x: -4
DesktopWindow: y: 200
DesktopWindow: x_root: 1916
DesktopWindow: y_root: 200
DesktopWindow: mode: NotifyNormal
DesktopWindow: detail: NotifyAncestor
DesktopWindow: same screen: True
DesktopWindow: focus: True
DesktopWindow: state: 0
DesktopWindow: intercept_handler: type: GenericEvent
DesktopWindow: serial: 1663
DesktopWindow: send_event: False
DesktopWindow: display: 0x16f33a0
DesktopWindow: extension: XInputExtension
DesktopWindow: evtype: 6
DesktopWindow: fltkDispatch: event: FL_LEAVE win: (nil)
DesktopWindow: handle: event: FL_LEAVE
DesktopWindow: ungrabPointer: ungrabbing mouse
-----------------------------------------------------------------
The LeaveNotify event makes its way to DesktopWindow::handle,
where in the FL_LEAVE case, this is executed:
-----------------------------------------------------------------
if (mouseGrabbed) {
if ((Fl::event_x() < 0) || (Fl::event_x() >= w()) ||
(Fl::event_y() < 0) || (Fl::event_y() >= h())) {
ungrabPointer();
}
}
-----------------------------------------------------------------
and the mouse let go.
In the zaphod configuration, this is the sequence:
-----------------------------------------------------------------
DesktopWindow: intercept_handler: type: MotionNotify
DesktopWindow: serial: 1750
DesktopWindow: send_event: True
DesktopWindow: display: 0xf4e3a0
DesktopWindow: window: 60817513
DesktopWindow: root: 3384
DesktopWindow: subwindow: 0
DesktopWindow: x: 3
DesktopWindow: y: 306
DesktopWindow: x_root: 3
DesktopWindow: y_root: 306
DesktopWindow: state: 0
DesktopWindow: is_hint:
DesktopWindow: fltkDispatch: event: FL_MOVE win: 0x10abee0
DesktopWindow: handle: event: FL_MOVE
DesktopWindow: intercept_handler: type: GenericEvent
DesktopWindow: serial: 1750
DesktopWindow: send_event: False
DesktopWindow: display: 0xf4e3a0
DesktopWindow: extension: XInputExtension
DesktopWindow: evtype: 6
DesktopWindow: intercept_handler: type: LeaveNotify
DesktopWindow: serial: 1750
DesktopWindow: send_event: False
DesktopWindow: display: 0xf4e3a0
DesktopWindow: window: 60817513
DesktopWindow: root: 3382
DesktopWindow: subwindow: 0
DesktopWindow: x: 0
DesktopWindow: y: 0
DesktopWindow: x_root: 1906
DesktopWindow: y_root: 306
DesktopWindow: mode: NotifyNormal
DesktopWindow: detail: NotifyNonlinear
DesktopWindow: same screen: False
DesktopWindow: focus: True
DesktopWindow: state: 0
DesktopWindow: intercept_handler: type: GenericEvent
DesktopWindow: serial: 1750
DesktopWindow: send_event: False
DesktopWindow: display: 0xf4e3a0
DesktopWindow: extension: XInputExtension
DesktopWindow: evtype: 6
DesktopWindow: fltkDispatch: event: FL_LEAVE win: (nil)
DesktopWindow: handle: event: FL_LEAVE
-----------------------------------------------------------------
which is not followed by this
DesktopWindow: ungrabPointer: ungrabbing mouse
as x=0 and y=0, i.e. not less than 0, nor greater than
width/height, and thus the mouse is not let go.
Note the root coordinates, they are 1906 and 306, which
happen to be the coordinates of the mouse on the other
screen. I moved from the right zaphod head to the left
zaphod head, thus the mouse is close to the right edge of
that head, which has geometry 1920x1080.
This is confirmed by the root field. On the non-zaphod case
the root screen is always the same, 1731, in the zaphod
case, the first MotionNotify I show, and all previous ones,
have a root window of 3384 and, the leave event that ought
to trigger the mouse ungrab is on root 3382. I don't think
FLTK provides a way to get the root window.
Before the mouse moves out of the zaphod head, as vncviewer
is in full window mode, x==x_root and y==y_root. After that
x_root and y_root seem correct in the other head, but
x==y==0, always.
A "simple" solution that works, IF AND ONLY IF, all monitors
have the same resolution, is to replace the check in the
DesktopWindow::handle, FL_LEAVE case, with:
-----------------------------------------------------------------
if (mouseGrabbed) {
if ((Fl::event_x() < 0) || (Fl::event_x() >= w()) ||
(Fl::event_y() < 0) || (Fl::event_y() >= h()) ||
((Fl::event_x_root() - Fl::event_x()) % Fl::w()) ||
((Fl::event_y_root() - Fl::event_y()) % Fl::h())) {
ungrabPointer();
}
}
-----------------------------------------------------------------
Works like a charm. It's Sunday morning PST, I have a bunch
of house related stuff to do. I'll try to work a generic
solution, though maybe someone on this mailing list could
come up with it much faster than me :-)
-- Henrique