i3status_rs/blocks/keyboard_layout/
sway.rs

1// use super::super::prelude::*;
2use super::*;
3use swayipc_async::{Connection, Event, EventType};
4
5pub(super) struct Sway {
6    events: swayipc_async::EventStream,
7    cur_layout: String,
8    kbd: Option<String>,
9}
10
11impl Sway {
12    pub(super) async fn new(kbd: Option<String>) -> Result<Self> {
13        let mut connection = Connection::new()
14            .await
15            .error("Failed to open swayipc connection")?;
16        let cur_layout = connection
17            .get_inputs()
18            .await
19            .error("failed to get current input")?
20            .iter()
21            .find_map(|i| {
22                if i.input_type == "keyboard" && kbd.as_deref().is_none_or(|id| id == i.identifier)
23                {
24                    i.xkb_active_layout_name.clone()
25                } else {
26                    None
27                }
28            })
29            .error("Failed to get current input")?;
30        let events = connection
31            .subscribe(&[EventType::Input])
32            .await
33            .error("Failed to subscribe to events")?;
34        Ok(Self {
35            events,
36            cur_layout,
37            kbd,
38        })
39    }
40}
41
42#[async_trait]
43impl Backend for Sway {
44    async fn get_info(&mut self) -> Result<Info> {
45        Ok(Info::from_layout_variant_str(&self.cur_layout))
46    }
47
48    async fn wait_for_change(&mut self) -> Result<()> {
49        loop {
50            let event = self
51                .events
52                .next()
53                .await
54                .error("swayipc channel closed")?
55                .error("bad event")?;
56            if let Event::Input(event) = event {
57                if self
58                    .kbd
59                    .as_deref()
60                    .is_none_or(|id| id == event.input.identifier)
61                {
62                    if let Some(new_layout) = event.input.xkb_active_layout_name {
63                        if new_layout != self.cur_layout {
64                            self.cur_layout = new_layout;
65                            return Ok(());
66                        }
67                    }
68                }
69            }
70        }
71    }
72}