Wayland: implement focus events (#8170)

Rom Grk created

Implements keyboard focus in/out events.

This also enables vim mode to work on wayland, which is only activated
when an editor gains focus.

Change summary

crates/gpui/src/platform/linux/wayland/client.rs | 26 ++++++++++++++---
crates/gpui/src/platform/linux/wayland/window.rs |  8 ++++
2 files changed, 28 insertions(+), 6 deletions(-)

Detailed changes

crates/gpui/src/platform/linux/wayland/client.rs 🔗

@@ -421,12 +421,29 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
                 state.keymap_state = Some(xkb::State::new(&keymap));
             }
             wl_keyboard::Event::Enter { surface, .. } => {
-                for window in &state.windows {
-                    if window.1.surface.id() == surface.id() {
-                        state.keyboard_focused_window = Some(Rc::clone(&window.1));
-                    }
+                state.keyboard_focused_window = state
+                    .windows
+                    .iter()
+                    .find(|&w| w.1.surface.id() == surface.id())
+                    .map(|w| w.1.clone());
+
+                if let Some(window) = &state.keyboard_focused_window {
+                    window.set_focused(true);
                 }
             }
+            wl_keyboard::Event::Leave { surface, .. } => {
+                let keyboard_focused_window = state
+                    .windows
+                    .iter()
+                    .find(|&w| w.1.surface.id() == surface.id())
+                    .map(|w| w.1.clone());
+
+                if let Some(window) = keyboard_focused_window {
+                    window.set_focused(false);
+                }
+
+                state.keyboard_focused_window = None;
+            }
             wl_keyboard::Event::Modifiers {
                 mods_depressed,
                 mods_latched,
@@ -479,7 +496,6 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
                     }
                 }
             }
-            wl_keyboard::Event::Leave { .. } => {}
             _ => {}
         }
     }

crates/gpui/src/platform/linux/wayland/window.rs 🔗

@@ -228,6 +228,12 @@ impl WaylandWindowState {
             }
         }
     }
+
+    pub fn set_focused(&self, focus: bool) {
+        if let Some(ref mut fun) = self.callbacks.lock().active_status_change {
+            fun(focus);
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -349,7 +355,7 @@ impl PlatformWindow for WaylandWindow {
     }
 
     fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
-        //todo!(linux)
+        self.0.callbacks.lock().active_status_change = Some(callback);
     }
 
     fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {