Skip to content

Commit 58b08ea

Browse files
committed
Fix mouse events interaction with ALT/F10 on Windows.
1 parent 05311d1 commit 58b08ea

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
117117
- X11: Support mouse scrolling. ([#961] by [@jneem])
118118
- `Painter` now properly repaints on data change in `Container`. ([#991] by [@cmyr])
119119
- macOS: The application menu is now immediately interactable after launch. ([#994] by [@xStrom])
120+
- Windows: Keep receiving mouse events after pressing ALT or F10 when the window has no menu. ([#997] by [@xStrom])
120121

121122
### Visual
122123

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

256258
## [0.5.0] - 2020-04-01

druid-shell/src/platform/windows/window.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct WindowState {
138138
hwnd: Cell<HWND>,
139139
scale: Cell<Scale>,
140140
area: Cell<ScaledArea>,
141+
has_menu: Cell<bool>,
141142
wndproc: Box<dyn WndProc>,
142143
idle_queue: Arc<Mutex<Vec<IdleKind>>>,
143144
timers: Arc<Mutex<TimerSlots>>,
@@ -358,40 +359,34 @@ impl MyWndProc {
358359
);
359360
}
360361

361-
fn scale(&self) -> Scale {
362-
self.handle
362+
fn with_window_state<F, R>(&self, f: F) -> R
363+
where
364+
F: FnOnce(Rc<WindowState>) -> R,
365+
{
366+
f(self
367+
.handle
363368
// Right now there aren't any mutable borrows to this.
364369
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
365370
.borrow()
366371
.state
367372
.upgrade()
368-
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
369-
.scale
370-
.get()
373+
.unwrap()) // WindowState drops after WM_NCDESTROY, so it's always here.
374+
}
375+
376+
fn scale(&self) -> Scale {
377+
self.with_window_state(|state| state.scale.get())
371378
}
372379

373380
fn area(&self) -> ScaledArea {
374-
self.handle
375-
// Right now there aren't any mutable borrows to this.
376-
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
377-
.borrow()
378-
.state
379-
.upgrade()
380-
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
381-
.area
382-
.get()
381+
self.with_window_state(|state| state.area.get())
383382
}
384383

385384
fn set_area(&self, area: ScaledArea) {
386-
self.handle
387-
// Right now there aren't any mutable borrows to this.
388-
// TODO: Attempt to guarantee this by making mutable handle borrows useless.
389-
.borrow()
390-
.state
391-
.upgrade()
392-
.unwrap() // WindowState drops after WM_NCDESTROY, so it's always here.
393-
.area
394-
.set(area)
385+
self.with_window_state(move |state| state.area.set(area))
386+
}
387+
388+
fn has_menu(&self) -> bool {
389+
self.with_window_state(|state| state.has_menu.get())
395390
}
396391
}
397392

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

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

1042+
let (hmenu, accels, has_menu) = match self.menu {
1043+
Some(menu) => {
1044+
let accels = menu.accels();
1045+
(menu.into_hmenu(), accels, true)
1046+
}
1047+
None => (0 as HMENU, None, false),
1048+
};
1049+
10411050
let window = WindowState {
10421051
hwnd: Cell::new(0 as HWND),
10431052
scale: Cell::new(scale),
10441053
area: Cell::new(area),
1054+
has_menu: Cell::new(has_menu),
10451055
wndproc: Box::new(wndproc),
10461056
idle_queue: Default::default(),
10471057
timers: Arc::new(Mutex::new(TimerSlots::new(1))),
@@ -1064,14 +1074,6 @@ impl WindowBuilder {
10641074
};
10651075
win.wndproc.connect(&handle, state);
10661076

1067-
let (hmenu, accels) = match self.menu {
1068-
Some(menu) => {
1069-
let accels = menu.accels();
1070-
(menu.into_hmenu(), accels)
1071-
}
1072-
None => (0 as HMENU, None),
1073-
};
1074-
10751077
let mut dwStyle = WS_OVERLAPPEDWINDOW;
10761078
if !self.resizable {
10771079
dwStyle &= !(WS_THICKFRAME | WS_MAXIMIZEBOX);
@@ -1406,6 +1408,7 @@ impl WindowHandle {
14061408
if SetMenu(hwnd, hmenu) == FALSE {
14071409
warn!("failed to set window menu");
14081410
} else {
1411+
w.has_menu.set(true);
14091412
DestroyMenu(old_menu);
14101413
}
14111414
if let Some(accels) = accels {

0 commit comments

Comments
 (0)