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

Multi-click mouse events on Windows #1157

Merged
merged 2 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ You can find its changes [documented below](#060---2020-06-01).
- Allow submit_command from the layout method in Widgets ([#1119] by [@rjwittams])
- Allow derivation of lenses for generic types ([#1120]) by [@rjwittams])
- Switch widget: Toggle animation being window refresh rate dependent ([#1145] by [@ForLoveOfCats])
- Multi-click on Windows, partial fix for #859 ([#1157] by [@raphlinus])

### Visual

Expand Down Expand Up @@ -399,6 +400,7 @@ Last release without a changelog :(
[#1143]: https://github.com/linebender/druid/pull/1143
[#1145]: https://github.com/linebender/druid/pull/1145
[#1152]: https://github.com/linebender/druid/pull/1152
[#1157]: https://github.com/linebender/druid/pull/1157

[Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master
[0.6.0]: https://github.com/linebender/druid/compare/v0.5.0...v0.6.0
Expand Down
35 changes: 26 additions & 9 deletions druid-shell/src/platform/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::mem;
use std::ptr::{null, null_mut};
use std::rc::{Rc, Weak};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use log::{debug, error, warn};
use winapi::ctypes::{c_int, c_void};
Expand Down Expand Up @@ -186,6 +187,8 @@ struct WndState {
// Is this window the topmost window under the mouse cursor
has_mouse_focus: bool,
//TODO: track surrogate orphan
last_click_time: Instant,
click_count: u8,
}

/// State for DirectComposition. This is optional because it is only supported
Expand Down Expand Up @@ -741,8 +744,10 @@ impl WndProc for MyWndProc {
}
Some(0)
}
// TODO: not clear where double-click processing should happen. Currently disabled
// because CS_DBLCLKS is not set
// Note: we handle the double-click events out of caution here, but we don't expect
// to actually receive any, because we don't set CS_DBLCLKS on the window class style.
// And the reason for that is that we want click counts that go above 2, so it just
// makes a lot more sense to do the click count logic ourselves.
WM_LBUTTONDBLCLK | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_RBUTTONDBLCLK
| WM_RBUTTONDOWN | WM_RBUTTONUP | WM_MBUTTONDBLCLK | WM_MBUTTONDOWN | WM_MBUTTONUP
| WM_XBUTTONDBLCLK | WM_XBUTTONDOWN | WM_XBUTTONUP => {
Expand All @@ -766,18 +771,28 @@ impl WndProc for MyWndProc {
} {
if let Ok(mut s) = self.state.try_borrow_mut() {
let s = s.as_mut().unwrap();
let count = match msg {
WM_LBUTTONDOWN | WM_MBUTTONDOWN | WM_RBUTTONDOWN | WM_XBUTTONDOWN => 1,
WM_LBUTTONDBLCLK | WM_MBUTTONDBLCLK | WM_RBUTTONDBLCLK
| WM_XBUTTONDBLCLK => 2,
WM_LBUTTONUP | WM_MBUTTONUP | WM_RBUTTONUP | WM_XBUTTONUP => 0,
_ => unreachable!(),
};
let down = matches!(msg, WM_LBUTTONDOWN | WM_MBUTTONDOWN | WM_RBUTTONDOWN | WM_XBUTTONDOWN |
WM_LBUTTONDBLCLK | WM_MBUTTONDBLCLK | WM_RBUTTONDBLCLK
| WM_XBUTTONDBLCLK);
let x = LOWORD(lparam as u32) as i16 as i32;
let y = HIWORD(lparam as u32) as i16 as i32;
let pos = Point::new(x as f64, y as f64).to_dp(self.scale());
let mods = s.keyboard_state.get_modifiers();
let buttons = get_buttons(wparam);
let dct = unsafe { GetDoubleClickTime() };
let threshold = Duration::from_millis(dct as u64);
let count = if down {
// TODO: it may be more precise to use the timestamp from the event.
let this_click = Instant::now();
if this_click - s.last_click_time >= threshold {
s.click_count = 0;
}
s.click_count = s.click_count.saturating_add(1);
s.last_click_time = this_click;
s.click_count
} else {
0
};
let event = MouseEvent {
pos,
buttons,
Expand Down Expand Up @@ -991,6 +1006,8 @@ impl WindowBuilder {
keyboard_state: KeyboardState::new(),
captured_mouse_buttons: MouseButtons::new(),
has_mouse_focus: false,
last_click_time: Instant::now(),
click_count: 0,
};
win.wndproc.connect(&handle, state);

Expand Down