i3status_rs/blocks/keyboard_layout/
sway.rs1use 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}