Skip to content

Commit

Permalink
Fix mouse events interaction with ALT/F10 on Windows. (#997)
Browse files Browse the repository at this point in the history
  • Loading branch information
xStrom authored May 31, 2020
1 parent 05311d1 commit cc014e1
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 32 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
- X11: Support mouse scrolling. ([#961] by [@jneem])
- `Painter` now properly repaints on data change in `Container`. ([#991] by [@cmyr])
- macOS: The application menu is now immediately interactable after launch. ([#994] by [@xStrom])
- Windows: Keep receiving mouse events after pressing ALT or F10 when the window has no menu. ([#997] by [@xStrom])

### Visual

Expand Down Expand Up @@ -251,6 +252,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
[#993]: https://github.com/xi-editor/druid/pull/993
[#994]: https://github.com/xi-editor/druid/pull/994
[#996]: https://github.com/xi-editor/druid/pull/996
[#997]: https://github.com/xi-editor/druid/pull/997
[#1001]: https://github.com/xi-editor/druid/pull/1001

## [0.5.0] - 2020-04-01
Expand Down
67 changes: 35 additions & 32 deletions druid-shell/src/platform/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ struct WindowState {
hwnd: Cell<HWND>,
scale: Cell<Scale>,
area: Cell<ScaledArea>,
has_menu: Cell<bool>,
wndproc: Box<dyn WndProc>,
idle_queue: Arc<Mutex<Vec<IdleKind>>>,
timers: Arc<Mutex<TimerSlots>>,
Expand Down Expand Up @@ -358,40 +359,34 @@ impl MyWndProc {
);
}

fn scale(&self) -> Scale {
self.handle
fn with_window_state<F, R>(&self, f: F) -> R
where
F: FnOnce(Rc<WindowState>) -> R,
{
f(self
.handle
// Right now there aren't any mutable borrows to this.
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
.borrow()
.state
.upgrade()
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
.scale
.get()
.unwrap()) // WindowState drops after WM_NCDESTROY, so it's always here.
}

fn scale(&self) -> Scale {
self.with_window_state(|state| state.scale.get())
}

fn area(&self) -> ScaledArea {
self.handle
// Right now there aren't any mutable borrows to this.
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
.borrow()
.state
.upgrade()
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
.area
.get()
self.with_window_state(|state| state.area.get())
}

fn set_area(&self, area: ScaledArea) {
self.handle
// Right now there aren't any mutable borrows to this.
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
.borrow()
.state
.upgrade()
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
.area
.set(area)
self.with_window_state(move |state| state.area.set(area))
}

fn has_menu(&self) -> bool {
self.with_window_state(|state| state.has_menu.get())
}
}

Expand Down Expand Up @@ -677,7 +672,13 @@ impl WndProc for MyWndProc {
let is_repeat = (lparam & 0xFFFF) > 0;
let event = KeyEvent::new(key_code, is_repeat, modifiers, "", "");

if s.handler.key_down(event) {
if s.handler.key_down(event)
// If the window doesn't have a menu, then we need to suppress ALT/F10.
// Otherwise we will stop getting mouse events for no gain.
// When we do have a menu, those keys will focus the menu.
|| (!self.has_menu()
&& (key_code == KeyCode::LeftAlt || key_code == KeyCode::F10))
{
Some(0)
} else {
None
Expand Down Expand Up @@ -1038,10 +1039,19 @@ impl WindowBuilder {
let area = ScaledArea::from_dp(self.size, &scale);
let size_px = area.size_px();

let (hmenu, accels, has_menu) = match self.menu {
Some(menu) => {
let accels = menu.accels();
(menu.into_hmenu(), accels, true)
}
None => (0 as HMENU, None, false),
};

let window = WindowState {
hwnd: Cell::new(0 as HWND),
scale: Cell::new(scale),
area: Cell::new(area),
has_menu: Cell::new(has_menu),
wndproc: Box::new(wndproc),
idle_queue: Default::default(),
timers: Arc::new(Mutex::new(TimerSlots::new(1))),
Expand All @@ -1064,14 +1074,6 @@ impl WindowBuilder {
};
win.wndproc.connect(&handle, state);

let (hmenu, accels) = match self.menu {
Some(menu) => {
let accels = menu.accels();
(menu.into_hmenu(), accels)
}
None => (0 as HMENU, None),
};

let mut dwStyle = WS_OVERLAPPEDWINDOW;
if !self.resizable {
dwStyle &= !(WS_THICKFRAME | WS_MAXIMIZEBOX);
Expand Down Expand Up @@ -1406,6 +1408,7 @@ impl WindowHandle {
if SetMenu(hwnd, hmenu) == FALSE {
warn!("failed to set window menu");
} else {
w.has_menu.set(true);
DestroyMenu(old_menu);
}
if let Some(accels) = accels {
Expand Down

0 comments on commit cc014e1

Please sign in to comment.