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

Fixed CursorEntered and CursorLeft events not getting sent when holding a mouse button down #3154

Merged
merged 8 commits into from
Oct 17, 2023

Conversation

YouKnow-sys
Copy link
Contributor

This PR fix the problem mentioned in #3153

  • Tested on all platforms changed
  • Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created or updated an example program if it would help users understand this functionality
  • Updated feature matrix, if new features were added or implemented

Comment on lines 1447 to 1495
'o: {
let mut w = userdata.window_state_lock();
let mouse_was_outside_window =
!w.mouse.cursor_flags().contains(CursorFlags::IN_WINDOW);

// Calling TrackMouseEvent in order to receive mouse leave events.
unsafe {
TrackMouseEvent(&mut TRACKMOUSEEVENT {
cbSize: mem::size_of::<TRACKMOUSEEVENT>() as u32,
dwFlags: TME_LEAVE,
hwndTrack: window,
dwHoverTime: HOVER_DEFAULT,
})
let rect: RECT = unsafe {
let mut rect: RECT = mem::zeroed();
if GetClientRect(window, &mut rect) == false.into() {
break 'o; // exit early if GetClientRect failed
}
rect
};

let x = (rect.left..rect.right).contains(&x);
let y = (rect.top..rect.bottom).contains(&y);

if mouse_was_outside_window && x && y {
w.mouse
.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, true))
.ok();

userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)),
event: CursorEntered {
device_id: DEVICE_ID,
},
});

// Calling TrackMouseEvent in order to receive mouse leave events.
unsafe {
TrackMouseEvent(&mut TRACKMOUSEEVENT {
cbSize: mem::size_of::<TRACKMOUSEEVENT>() as u32,
dwFlags: TME_LEAVE,
hwndTrack: window,
dwHoverTime: HOVER_DEFAULT,
})
};
} else if !(mouse_was_outside_window || x && y) {
w.mouse
.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false))
.ok();

userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)),
event: CursorLeft {
device_id: DEVICE_ID,
},
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you extract all of this mess into a function accepting: window, x, y, position and returning something like PointerMoveKind { Move, Enter, Leave } so you can then do something like that

match get_pointer_move_kind(window, position, x, y) {
    PointerMoveKind::Leave => {
        // Cursor left handling
    }
    PointerMoveKind::Enter => {
       // Cursor enter handling
    }
    PointerMoveKind::Move => (),
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I can do that, although I believe the Move should always happen, so there shouldn't be a separate case for it, maybe instead of creating a new enum with two variant (Leave, Enter) a Option<bool> would be enough?

Copy link
Member

@kchibisov kchibisov Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option<bool> is 3 variants as well, it's just not clear what it means, you can define Move as something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option<bool> is 3 variants as well, it's just not clear what it means, you can define Move as something else.

Ok yeah I understand, I meant in a way that None mean there is no need to do anything and Some(..) we have to do something, but yeah having an enum can make the code more organized so I went by that, I applied your suggestions.

Copy link
Member

@kchibisov kchibisov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also missing a changelog entry.

None,
}

unsafe fn get_pointer_move_kind(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the function itself is safe. Also move it to the bottom of the file with the PointerMoveKind thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the function itself is safe. Also move it to the bottom of the file with the PointerMoveKind thing.

well we do have some unsafe calls inside it, that's why I marked it as unsafe although Im pretty sure none of these unsafe calls are failable so I removed the unsafe.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsafe functions in rust serve a different purpose usually, for example, when you need to hold some lifetime, etc invariant when you call a function, which usually is tracked by rust.

In this case though, we know that it as a whole is safe, since the only call uses HWND is error checked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh ok, thanks for information.

@YouKnow-sys
Copy link
Contributor Author

Also missing a changelog entry.

Done

@kchibisov kchibisov mentioned this pull request Oct 17, 2023
3 tasks
@kchibisov kchibisov merged commit f5b4d69 into rust-windowing:master Oct 17, 2023
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants