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: Always use correct window ID for XInput2 events #372

Merged
merged 1 commit into from
Jan 8, 2018

Conversation

francesca64
Copy link
Member

The CursorMoved events that are used to send position updates alongside Focused and CursorEntered events were using incorrect values for the window ID. This is a direct result of the X11 backend being hard to understand, as those values came from variables in the top-level scope of the function, which one would assume to be valid throughout the entirety of their scope. In reality, their validity is dependent on the event belonging to the XEvent union, so very surprising things can happen if those variables are read in the case of XInput2/XKB/etc. events. To help prevent future accidents, the aforementioned variables have been removed, and are now defined per-event instead.

However, the CursorMoved event sent alongside Focused events is still imperfect. The associated DeviceId is for the core virtual keyboard, as opposed to the core virtual pointer, which is the expected value on all other CursorMoved events. I'm not aware of any straightforward solution to this, as window focus isn't inherently tied to pointer devices.

@Ralith
Copy link
Contributor

Ralith commented Dec 24, 2017

I'm not aware of any straightforward solution to this, as window focus isn't inherently tied to pointer devices.

The intention of the artificial CursorMoved event is to ensure that a freshly focused application knows where the cursors are, right? The correct behavior is presumably then to generate one CursorMoved event per cursor.

@francesca64
Copy link
Member Author

Right, and that seems like a good way to go.

@francesca64
Copy link
Member Author

A CursorMoved event is now sent for every master pointer positioned within the window.

@Ralith
Copy link
Contributor

Ralith commented Dec 28, 2017

Is there a need for additional handling of cursors that were positioned within the window when focus was lost, but are not when focus is regained?

@francesca64
Copy link
Member Author

francesca64 commented Dec 28, 2017

Well, I tried sending CursorLeft for any master pointer that left the window without having already sent CursorLeft, but I wasn't actually able to trigger that condition. CursorLeft was being sent even after the window sent Focused(false), and I noticed that more Focused(false) were being sent than Focused(true).

Since we're using XI_FocusIn/XI_FocusOut, focus is indeed tied to individual devices, but (presumably because of my WM) it works very badly. While it never wants to report a window as focused by multiple devices, it will report a window as unfocused by multiple devices. Even when only focused by one device, the device it's reported as is inconsistent, though the virtual core device is always favored.

I think the most correct implementation in terms of the spec would be to use the attachment field on XIDeviceInfo to get the master pointer that's paired with the master keyboard specified by the deviceid field on these events, which is also the cursor the event_x and event_y fields contain the position of.

While what I've implemented is more usable for more people, I feel that trying to compensate for the inadequacies of multi-pointer support is a dangerous road to go down. From what I've read, basically none of the WMs in use are designed with multi-pointer in mind, and we can't fight the WM's notion of focus.

@Ralith
Copy link
Contributor

Ralith commented Dec 28, 2017

I'm feeling increasingly confused about the behaviors expected by X, the users, and window managers in turn. I agree that mpx probably doesn't deserve intense care, being (yet more) X esoterica that will be rendered further irrelevant as Wayland adoption grows. If there's no obvious way to be both correct and useful, I have no argument against doing the relatively straightforward and mostly sane thing.

@francesca64
Copy link
Member Author

Alright, looks like this is finally done.

As an added bonus, in light of the changes made when modifiers were added to mouse events, I've:

  • implemented From<c_uint> for ModifiersState, thus removing redundant code
  • fixed the modifiers on the CursorMoved event sent with CursorEntered, as they were previously always false

@tomaka
Copy link
Contributor

tomaka commented Dec 29, 2017

implemented From<c_uint> for ModifiersState, thus removing redundant code

Do we want that though? A c_uint is semantically not the same thing as a ModifiersState.

@francesca64
Copy link
Member Author

Come to think of it, all the relevant XInput2 events have a mods field of type XIModifierState, so I could just implement From<XIModifierState> instead.

While keyboard handling doesn't use XInput2 yet, that only accounts for a single call, and it will be removed anyway by my upcoming libxkbcommon PR, so I can just revert that to doing the logic inline.

The `CursorMoved` events that are used to send position updates alongside `Focused` and
`CursorEntered` events were using incorrect values for the window ID. This is a direct
result of the X11 backend being hard to understand, as those values came from variables in
the top-level scope of the function, which one would assume to be valid throughout the
entirety of their scope. In reality, their validity is dependent on the event belonging to
the `XEvent` union, so very surprising things can happen if those variables are read in the
case of XInput2/XKB/etc. events. To prevent future accidents, the aforementioned variables
have been removed, and are now defined per-event instead.

Additionally, the `CursorMoved` event sent alongside `Focused` now uses the correct device
ID; it previously used the ID of a master keyboard, but now uses the ID of the pointer
paired to that keyboard. Note that for those using multi-pointer X, the correctness of this
ID is dependent on the correctness of the window manager's focus model.
@francesca64
Copy link
Member Author

This should be good to go now, if there aren't any other objections.

@tomaka tomaka merged commit 124b16f into rust-windowing:master Jan 8, 2018
@tomaka
Copy link
Contributor

tomaka commented Jan 8, 2018

Thanks!

tmfink pushed a commit to tmfink/winit that referenced this pull request Jan 5, 2022
tmfink pushed a commit to tmfink/winit that referenced this pull request Jan 5, 2022
Implement nested SVG clip paths in the D3D11 backend.

Partially addresses rust-windowing#372.
tmfink pushed a commit to tmfink/winit that referenced this pull request Jan 5, 2022
tmfink pushed a commit to tmfink/winit that referenced this pull request Jan 5, 2022
… r=pcwalton

Allow clip paths to nest in the canvas API.

Closes rust-windowing#372.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants