Skip to content

Commit

Permalink
Automatically capture mouse on windows on mouse down (#695)
Browse files Browse the repository at this point in the history
* Don't log error when WM_CAPTURECHANGED is reentrant, since in that case we'll have called it ourselves and don't require the callback.
  • Loading branch information
teddemunnik authored Mar 21, 2020
1 parent a4f6038 commit 821dc39
Showing 1 changed file with 37 additions and 0 deletions.
37 changes: 37 additions & 0 deletions druid-shell/src/platform/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ struct WndState {
/// The `char` of the last `WM_CHAR` event, if there has not already been
/// a `WM_KEYUP` event.
stashed_char: Option<char>,
// Stores a bit mask of all mouse buttons that are currently holding mouse
// capture. When the first mouse button is down on our window we enter
// capture, and we hold it until the last mouse button is up.
captured_mouse_buttons: u32,
//TODO: track surrogate orphan
}

Expand Down Expand Up @@ -257,6 +261,29 @@ impl WndState {
handle.add_idle_callback(move |_| handle2.invalidate());
}
}

fn enter_mouse_capture(&mut self, hwnd: HWND, button: MouseButton) {
if self.captured_mouse_buttons == 0 {
unsafe {
SetCapture(hwnd);
}
}
self.captured_mouse_buttons |= 1 << (button as u32);
}

fn exit_mouse_capture(&mut self, button: MouseButton) {
self.captured_mouse_buttons &= !(1 << (button as u32));
if self.captured_mouse_buttons == 0 {
unsafe {
if ReleaseCapture() == FALSE {
warn!(
"failed to release mouse capture: {}",
Error::Hr(HRESULT_FROM_WIN32(GetLastError()))
);
}
}
}
}
}

impl MyWndProc {
Expand Down Expand Up @@ -630,9 +657,11 @@ impl WndProc for MyWndProc {
count,
};
if count > 0 {
s.enter_mouse_capture(hwnd, button);
s.handler.mouse_down(&event);
} else {
s.handler.mouse_up(&event);
s.exit_mouse_capture(button);
}
} else {
self.log_dropped_msg(hwnd, msg, wparam, lparam);
Expand Down Expand Up @@ -667,6 +696,13 @@ impl WndProc for MyWndProc {
}
Some(1)
}
WM_CAPTURECHANGED => {
if let Ok(mut s) = self.state.try_borrow_mut() {
let s = s.as_mut().unwrap();
s.captured_mouse_buttons = 0;
}
Some(0)
}
XI_RUN_IDLE => {
if let Ok(mut s) = self.state.try_borrow_mut() {
let s = s.as_mut().unwrap();
Expand Down Expand Up @@ -788,6 +824,7 @@ impl WindowBuilder {
dpi,
stashed_key_code: KeyCode::Unknown(0),
stashed_char: None,
captured_mouse_buttons: 0,
};
win.wndproc.connect(&handle, state);

Expand Down

0 comments on commit 821dc39

Please sign in to comment.