Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:52:08.796Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

xdg_desktop_portal.rs

192 lines · 6.3 KB · rust
1//! Provides a [calloop] event source from [XDG Desktop Portal] events
2//!
3//! This module uses the [ashpd] crate
4
5use ashpd::desktop::settings::{ColorScheme, Settings};
6use calloop::channel::Channel;
7use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory};
8use smol::stream::StreamExt;
9
10use gpui::{BackgroundExecutor, WindowAppearance};
11
12pub enum Event {
13    WindowAppearance(WindowAppearance),
14    #[cfg_attr(feature = "x11", allow(dead_code))]
15    CursorTheme(String),
16    #[cfg_attr(feature = "x11", allow(dead_code))]
17    CursorSize(u32),
18    ButtonLayout(String),
19}
20
21pub struct XDPEventSource {
22    channel: Channel<Event>,
23}
24
25impl XDPEventSource {
26    pub fn new(executor: &BackgroundExecutor) -> Self {
27        let (sender, channel) = calloop::channel::channel();
28
29        let background = executor.clone();
30
31        executor
32            .spawn(async move {
33                let settings = Settings::new().await?;
34
35                if let Ok(initial_appearance) = settings.color_scheme().await {
36                    sender.send(Event::WindowAppearance(
37                        window_appearance_from_color_scheme(initial_appearance),
38                    ))?;
39                }
40                if let Ok(initial_theme) = settings
41                    .read::<String>("org.gnome.desktop.interface", "cursor-theme")
42                    .await
43                {
44                    sender.send(Event::CursorTheme(initial_theme))?;
45                }
46
47                // If u32 is used here, it throws invalid type error
48                if let Ok(initial_size) = settings
49                    .read::<i32>("org.gnome.desktop.interface", "cursor-size")
50                    .await
51                {
52                    sender.send(Event::CursorSize(initial_size as u32))?;
53                }
54
55                if let Ok(initial_layout) = settings
56                    .read::<String>("org.gnome.desktop.wm.preferences", "button-layout")
57                    .await
58                {
59                    sender.send(Event::ButtonLayout(initial_layout))?;
60                }
61
62                if let Ok(mut cursor_theme_changed) = settings
63                    .receive_setting_changed_with_args(
64                        "org.gnome.desktop.interface",
65                        "cursor-theme",
66                    )
67                    .await
68                {
69                    let sender = sender.clone();
70                    background
71                        .spawn(async move {
72                            while let Some(theme) = cursor_theme_changed.next().await {
73                                let theme = theme?;
74                                sender.send(Event::CursorTheme(theme))?;
75                            }
76                            anyhow::Ok(())
77                        })
78                        .detach();
79                }
80
81                if let Ok(mut cursor_size_changed) = settings
82                    .receive_setting_changed_with_args::<i32>(
83                        "org.gnome.desktop.interface",
84                        "cursor-size",
85                    )
86                    .await
87                {
88                    let sender = sender.clone();
89                    background
90                        .spawn(async move {
91                            while let Some(size) = cursor_size_changed.next().await {
92                                let size = size?;
93                                sender.send(Event::CursorSize(size as u32))?;
94                            }
95                            anyhow::Ok(())
96                        })
97                        .detach();
98                }
99
100                if let Ok(mut button_layout_changed) = settings
101                    .receive_setting_changed_with_args(
102                        "org.gnome.desktop.wm.preferences",
103                        "button-layout",
104                    )
105                    .await
106                {
107                    let sender = sender.clone();
108                    background
109                        .spawn(async move {
110                            while let Some(layout) = button_layout_changed.next().await {
111                                let layout = layout?;
112                                sender.send(Event::ButtonLayout(layout))?;
113                            }
114                            anyhow::Ok(())
115                        })
116                        .detach();
117                }
118
119                let mut appearance_changed = settings.receive_color_scheme_changed().await?;
120                while let Some(scheme) = appearance_changed.next().await {
121                    sender.send(Event::WindowAppearance(
122                        window_appearance_from_color_scheme(scheme),
123                    ))?;
124                }
125
126                anyhow::Ok(())
127            })
128            .detach();
129
130        Self { channel }
131    }
132}
133
134impl EventSource for XDPEventSource {
135    type Event = Event;
136    type Metadata = ();
137    type Ret = ();
138    type Error = anyhow::Error;
139
140    fn process_events<F>(
141        &mut self,
142        readiness: Readiness,
143        token: Token,
144        mut callback: F,
145    ) -> Result<PostAction, Self::Error>
146    where
147        F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
148    {
149        self.channel.process_events(readiness, token, |evt, _| {
150            if let calloop::channel::Event::Msg(msg) = evt {
151                (callback)(msg, &mut ())
152            }
153        })?;
154
155        Ok(PostAction::Continue)
156    }
157
158    fn register(
159        &mut self,
160        poll: &mut Poll,
161        token_factory: &mut TokenFactory,
162    ) -> calloop::Result<()> {
163        self.channel.register(poll, token_factory)?;
164
165        Ok(())
166    }
167
168    fn reregister(
169        &mut self,
170        poll: &mut Poll,
171        token_factory: &mut TokenFactory,
172    ) -> calloop::Result<()> {
173        self.channel.reregister(poll, token_factory)?;
174
175        Ok(())
176    }
177
178    fn unregister(&mut self, poll: &mut Poll) -> calloop::Result<()> {
179        self.channel.unregister(poll)?;
180
181        Ok(())
182    }
183}
184
185fn window_appearance_from_color_scheme(cs: ColorScheme) -> WindowAppearance {
186    match cs {
187        ColorScheme::PreferDark => WindowAppearance::Dark,
188        ColorScheme::PreferLight => WindowAppearance::Light,
189        ColorScheme::NoPreference => WindowAppearance::Light,
190    }
191}
192
Served at tenant.openagents/omega Member data and write actions are omitted.