1#![cfg(any(
6 target_os = "linux",
7 target_os = "dragonfly",
8 target_os = "freebsd",
9 target_os = "netbsd",
10 target_os = "openbsd"
11))]
12
13#[cfg(feature = "x11")]
14use std::{os::raw::c_int, sync::Arc};
15
16#[doc(hidden)]
18#[cfg(feature = "x11")]
19pub use crate::platform_impl::x11;
20
21#[cfg(feature = "x11")]
22use crate::platform_impl::x11::xdisplay::XError;
23pub use crate::platform_impl::EventLoop as UnixEventLoop;
24use crate::{
25 error::{ExternalError, OsError},
26 event_loop::{EventLoopBuilder, EventLoopWindowTarget},
27 monitor::MonitorHandle,
28 platform_impl::{Parent, Window as UnixWindow},
29 window::{Window, WindowBuilder},
30};
31
32#[cfg(feature = "x11")]
33use self::x11::xdisplay::XConnection;
34
35pub trait EventLoopBuilderExtUnix {
37 fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
48
49 fn with_app_id<S: Into<String>>(&mut self, id: S) -> &mut Self;
53}
54
55impl<T> EventLoopBuilderExtUnix for EventLoopBuilder<T> {
56 #[inline]
57 fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
58 self.platform_specific.any_thread = any_thread;
59 self
60 }
61
62 fn with_app_id<S: Into<String>>(&mut self, id: S) -> &mut Self {
63 self.platform_specific.app_id = Some(id.into());
64 self
65 }
66}
67
68pub trait WindowExtUnix {
70 fn new_from_gtk_window<T: 'static>(
74 event_loop_window_target: &EventLoopWindowTarget<T>,
75 window: gtk::ApplicationWindow,
76 ) -> Result<Window, OsError>;
77
78 fn gtk_window(&self) -> >k::ApplicationWindow;
80
81 fn default_vbox(&self) -> Option<>k::Box>;
84
85 fn set_skip_taskbar(&self, skip: bool) -> Result<(), ExternalError>;
87
88 fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>);
89}
90
91impl WindowExtUnix for Window {
92 fn gtk_window(&self) -> >k::ApplicationWindow {
93 &self.window.window
94 }
95
96 fn default_vbox(&self) -> Option<>k::Box> {
97 self.window.default_vbox.as_ref()
98 }
99
100 fn set_skip_taskbar(&self, skip: bool) -> Result<(), ExternalError> {
101 self.window.set_skip_taskbar(skip)
102 }
103
104 fn new_from_gtk_window<T: 'static>(
105 event_loop_window_target: &EventLoopWindowTarget<T>,
106 window: gtk::ApplicationWindow,
107 ) -> Result<Window, OsError> {
108 let window = UnixWindow::new_from_gtk_window(&event_loop_window_target.p, window)?;
109 Ok(Window { window })
110 }
111
112 fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) {
113 self.window.set_badge_count(count, desktop_filename);
114 }
115}
116
117pub trait WindowBuilderExtUnix {
118 fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
120 fn with_transient_for(self, parent: &impl gtk::glib::IsA<gtk::Window>) -> WindowBuilder;
123
124 fn with_transparent_draw(self, draw: bool) -> WindowBuilder;
130
131 fn with_double_buffered(self, double_buffered: bool) -> WindowBuilder;
135
136 fn with_rgba_visual(self, rgba_visual: bool) -> WindowBuilder;
140
141 fn with_app_paintable(self, app_paintable: bool) -> WindowBuilder;
147
148 fn with_cursor_moved_event(self, cursor_moved: bool) -> WindowBuilder;
154
155 fn with_default_vbox(self, add: bool) -> WindowBuilder;
158}
159
160impl WindowBuilderExtUnix for WindowBuilder {
161 fn with_skip_taskbar(mut self, skip: bool) -> WindowBuilder {
162 self.platform_specific.skip_taskbar = skip;
163 self
164 }
165
166 fn with_transient_for(mut self, parent: &impl gtk::glib::IsA<gtk::Window>) -> WindowBuilder {
167 use gtk::glib::Cast;
168 self.platform_specific.parent = Parent::ChildOf(parent.clone().upcast());
169 self
170 }
171
172 fn with_transparent_draw(mut self, draw: bool) -> WindowBuilder {
173 self.platform_specific.auto_transparent = draw;
174 self
175 }
176
177 fn with_double_buffered(mut self, double_buffered: bool) -> WindowBuilder {
178 self.platform_specific.double_buffered = double_buffered;
179 self
180 }
181
182 fn with_rgba_visual(mut self, rgba_visual: bool) -> WindowBuilder {
183 self.platform_specific.rgba_visual = rgba_visual;
184 self
185 }
186
187 fn with_app_paintable(mut self, app_paintable: bool) -> WindowBuilder {
188 self.platform_specific.app_paintable = app_paintable;
189 self
190 }
191
192 fn with_cursor_moved_event(mut self, cursor_moved: bool) -> WindowBuilder {
193 self.platform_specific.cursor_moved = cursor_moved;
194 self
195 }
196
197 fn with_default_vbox(mut self, add: bool) -> WindowBuilder {
198 self.platform_specific.default_vbox = add;
199 self
200 }
201}
202
203pub trait EventLoopWindowTargetExtUnix {
205 fn is_wayland(&self) -> bool;
207
208 #[cfg(feature = "x11")]
210 fn is_x11(&self) -> bool;
211
212 #[cfg(feature = "x11")]
213 fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
214
215 fn gtk_app(&self) -> >k::Application;
225
226 fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>);
228}
229
230impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
231 #[inline]
232 fn is_wayland(&self) -> bool {
233 self.p.is_wayland()
234 }
235
236 #[cfg(feature = "x11")]
237 #[inline]
238 fn is_x11(&self) -> bool {
239 !self.p.is_wayland()
240 }
241
242 #[cfg(feature = "x11")]
243 #[inline]
244 fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
245 if self.is_x11() {
246 if let Ok(xconn) = XConnection::new(Some(x_error_callback)) {
247 Some(Arc::new(xconn))
248 } else {
249 None
250 }
251 } else {
252 None
253 }
254 }
255
256 #[inline]
268 fn gtk_app(&self) -> >k::Application {
269 &self.p.app
270 }
271
272 #[inline]
273 fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) {
274 self.p.set_badge_count(count, desktop_filename);
275 }
276}
277
278#[cfg(feature = "x11")]
279unsafe extern "C" fn x_error_callback(
280 _display: *mut x11::ffi::Display,
281 event: *mut x11::ffi::XErrorEvent,
282) -> c_int {
283 let error = XError {
284 description: String::new(),
286 error_code: (*event).error_code,
287 request_code: (*event).request_code,
288 minor_code: (*event).minor_code,
289 };
290
291 error!("X11 error: {:#?}", error);
292
293 0
295}
296
297pub trait MonitorHandleExtUnix {
299 fn gdk_monitor(&self) -> >k::gdk::Monitor;
301}
302
303impl MonitorHandleExtUnix for MonitorHandle {
304 #[inline]
305 fn gdk_monitor(&self) -> >k::gdk::Monitor {
306 &self.inner.monitor
307 }
308}