diff --git a/crates/gpui/src/platform/linux/x11/client.rs b/crates/gpui/src/platform/linux/x11/client.rs index 1f64658072afdd28b49933f1c86e115fb371b014..60f9b2202fc2883cf491b103da753bec7462c316 100644 --- a/crates/gpui/src/platform/linux/x11/client.rs +++ b/crates/gpui/src/platform/linux/x11/client.rs @@ -115,7 +115,8 @@ pub struct X11ClientState { pub(crate) _resource_database: Database, pub(crate) atoms: XcbAtoms, pub(crate) windows: HashMap, - pub(crate) focused_window: Option, + pub(crate) mouse_focused_window: Option, + pub(crate) keyboard_focused_window: Option, pub(crate) xkb: xkbc::State, pub(crate) ximc: Option>>, pub(crate) xim_handler: Option, @@ -151,7 +152,12 @@ impl X11ClientStatePtr { x_window ); } - + if state.mouse_focused_window == Some(x_window) { + state.mouse_focused_window = None; + } + if state.keyboard_focused_window == Some(x_window) { + state.keyboard_focused_window = None; + } state.cursor_styles.remove(&x_window); if state.windows.is_empty() { @@ -320,7 +326,8 @@ impl X11Client { _resource_database: resource_database, atoms, windows: HashMap::default(), - focused_window: None, + mouse_focused_window: None, + keyboard_focused_window: None, xkb: xkb_state, ximc, xim_handler, @@ -361,7 +368,7 @@ impl X11Client { .push(AttributeName::ClientWindow, xim_handler.window) .push(AttributeName::FocusWindow, xim_handler.window); - let window_id = state.focused_window; + let window_id = state.keyboard_focused_window; drop(state); if let Some(window_id) = window_id { let window = self.get_window(window_id).unwrap(); @@ -558,19 +565,19 @@ impl X11Client { let window = self.get_window(event.window)?; window.refresh(); } - Event::FocusIn(event) => { + Event::FocusIn(event) if event.mode == xproto::NotifyMode::NORMAL => { let window = self.get_window(event.event)?; window.set_focused(true); let mut state = self.0.borrow_mut(); - state.focused_window = Some(event.event); + state.keyboard_focused_window = Some(event.event); drop(state); self.enable_ime(); } - Event::FocusOut(event) => { + Event::FocusOut(event) if event.mode == xproto::NotifyMode::NORMAL => { let window = self.get_window(event.event)?; window.set_focused(false); let mut state = self.0.borrow_mut(); - state.focused_window = None; + state.keyboard_focused_window = None; if let Some(compose_state) = state.compose_state.as_mut() { compose_state.reset(); } @@ -594,7 +601,7 @@ impl X11Client { if state.modifiers == modifiers { drop(state); } else { - let focused_window_id = state.focused_window?; + let focused_window_id = state.keyboard_focused_window?; state.modifiers = modifiers; drop(state); @@ -844,12 +851,18 @@ impl X11Client { valuator_idx += 1; } } + Event::XinputEnter(event) if event.mode == xinput::NotifyMode::NORMAL => { + let window = self.get_window(event.event)?; + window.set_focused(true); + let mut state = self.0.borrow_mut(); + state.mouse_focused_window = Some(event.event); + } Event::XinputLeave(event) if event.mode == xinput::NotifyMode::NORMAL => { self.0.borrow_mut().scroll_x = None; // Set last scroll to `None` so that a large delta isn't created if scrolling is done outside the window (the valuator is global) self.0.borrow_mut().scroll_y = None; - let window = self.get_window(event.event)?; let mut state = self.0.borrow_mut(); + state.mouse_focused_window = None; let pressed_button = pressed_button_from_mask(event.buttons[0]); let position = point( px(event.event_x as f32 / u16::MAX as f32 / state.scale_factor), @@ -859,11 +872,13 @@ impl X11Client { state.modifiers = modifiers; drop(state); + let window = self.get_window(event.event)?; window.handle_input(PlatformInput::MouseExited(crate::MouseExitEvent { pressed_button, position, modifiers, })); + window.set_focused(false); } _ => {} }; @@ -1046,7 +1061,7 @@ impl LinuxClient for X11Client { fn set_cursor_style(&self, style: CursorStyle) { let mut state = self.0.borrow_mut(); - let Some(focused_window) = state.focused_window else { + let Some(focused_window) = state.mouse_focused_window else { return; }; let current_style = state @@ -1294,7 +1309,7 @@ impl LinuxClient for X11Client { fn active_window(&self) -> Option { let state = self.0.borrow(); - state.focused_window.and_then(|focused_window| { + state.keyboard_focused_window.and_then(|focused_window| { state .windows .get(&focused_window) diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index d81de2a48e4c48f15a7b0cf280b1b0409155c191..0f97071155bee56dc4c75ef7dbfb8f254690a270 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -450,6 +450,7 @@ impl X11WindowState { xinput::XIEventMask::MOTION | xinput::XIEventMask::BUTTON_PRESS | xinput::XIEventMask::BUTTON_RELEASE + | xinput::XIEventMask::ENTER | xinput::XIEventMask::LEAVE, ], }],