1#![cfg(any(
2 target_os = "linux",
3 target_os = "dragonfly",
4 target_os = "freebsd",
5 target_os = "netbsd",
6 target_os = "openbsd"
7))]
8
9use std::os::raw;
10#[cfg(feature = "x11")]
11use std::{ptr, sync::Arc};
12
13use crate::{
14 event_loop::{EventLoop, EventLoopWindowTarget},
15 monitor::MonitorHandle,
16 window::{Window, WindowBuilder},
17};
18
19#[cfg(feature = "x11")]
20use crate::dpi::Size;
21#[cfg(feature = "x11")]
22use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection};
23use crate::platform_impl::{
24 EventLoop as LinuxEventLoop, EventLoopWindowTarget as LinuxEventLoopWindowTarget,
25 Window as LinuxWindow,
26};
27
28#[doc(hidden)]
30#[cfg(feature = "x11")]
31pub use crate::platform_impl::x11;
32#[cfg(feature = "x11")]
33pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported};
34
35pub trait EventLoopWindowTargetExtUnix {
37 #[cfg(feature = "wayland")]
39 fn is_wayland(&self) -> bool;
40
41 #[cfg(feature = "x11")]
43 fn is_x11(&self) -> bool;
44
45 #[doc(hidden)]
46 #[cfg(feature = "x11")]
47 fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
48
49 #[cfg(feature = "wayland")]
56 fn wayland_display(&self) -> Option<*mut raw::c_void>;
57}
58
59impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
60 #[inline]
61 #[cfg(feature = "wayland")]
62 fn is_wayland(&self) -> bool {
63 self.p.is_wayland()
64 }
65
66 #[inline]
67 #[cfg(feature = "x11")]
68 fn is_x11(&self) -> bool {
69 !self.p.is_wayland()
70 }
71
72 #[inline]
73 #[doc(hidden)]
74 #[cfg(feature = "x11")]
75 fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
76 match self.p {
77 LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()),
78 #[cfg(feature = "wayland")]
79 _ => None,
80 }
81 }
82
83 #[inline]
84 #[cfg(feature = "wayland")]
85 fn wayland_display(&self) -> Option<*mut raw::c_void> {
86 match self.p {
87 LinuxEventLoopWindowTarget::Wayland(ref p) => {
88 Some(p.display().get_display_ptr() as *mut _)
89 }
90 #[cfg(feature = "x11")]
91 _ => None,
92 }
93 }
94}
95
96pub trait EventLoopExtUnix {
98 #[cfg(feature = "x11")]
105 fn new_x11() -> Result<Self, XNotSupported>
106 where
107 Self: Sized;
108
109 #[cfg(feature = "wayland")]
116 fn new_wayland() -> Self
117 where
118 Self: Sized;
119
120 fn new_any_thread() -> Self
125 where
126 Self: Sized;
127
128 #[cfg(feature = "x11")]
133 fn new_x11_any_thread() -> Result<Self, XNotSupported>
134 where
135 Self: Sized;
136
137 #[cfg(feature = "wayland")]
142 fn new_wayland_any_thread() -> Self
143 where
144 Self: Sized;
145}
146
147fn wrap_ev<T>(event_loop: LinuxEventLoop<T>) -> EventLoop<T> {
148 EventLoop {
149 event_loop,
150 _marker: std::marker::PhantomData,
151 }
152}
153
154impl<T> EventLoopExtUnix for EventLoop<T> {
155 #[inline]
156 fn new_any_thread() -> Self {
157 wrap_ev(LinuxEventLoop::new_any_thread())
158 }
159
160 #[inline]
161 #[cfg(feature = "x11")]
162 fn new_x11_any_thread() -> Result<Self, XNotSupported> {
163 LinuxEventLoop::new_x11_any_thread().map(wrap_ev)
164 }
165
166 #[inline]
167 #[cfg(feature = "wayland")]
168 fn new_wayland_any_thread() -> Self {
169 wrap_ev(
170 LinuxEventLoop::new_wayland_any_thread()
171 .expect("failed to open Wayland connection"),
173 )
174 }
175
176 #[inline]
177 #[cfg(feature = "x11")]
178 fn new_x11() -> Result<Self, XNotSupported> {
179 LinuxEventLoop::new_x11().map(wrap_ev)
180 }
181
182 #[inline]
183 #[cfg(feature = "wayland")]
184 fn new_wayland() -> Self {
185 wrap_ev(
186 LinuxEventLoop::new_wayland()
187 .expect("failed to open Wayland connection"),
189 )
190 }
191}
192
193pub trait WindowExtUnix {
195 #[cfg(feature = "x11")]
199 fn xlib_window(&self) -> Option<raw::c_ulong>;
200
201 #[cfg(feature = "x11")]
207 fn xlib_display(&self) -> Option<*mut raw::c_void>;
208
209 #[cfg(feature = "x11")]
210 fn xlib_screen_id(&self) -> Option<raw::c_int>;
211
212 #[doc(hidden)]
213 #[cfg(feature = "x11")]
214 fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
215
216 #[cfg(feature = "x11")]
222 fn xcb_connection(&self) -> Option<*mut raw::c_void>;
223
224 #[cfg(feature = "wayland")]
230 fn wayland_surface(&self) -> Option<*mut raw::c_void>;
231
232 #[cfg(feature = "wayland")]
238 fn wayland_display(&self) -> Option<*mut raw::c_void>;
239
240 #[cfg(feature = "wayland")]
242 fn set_wayland_theme<T: Theme>(&self, theme: T);
243
244 #[deprecated]
251 fn is_ready(&self) -> bool;
252}
253
254impl WindowExtUnix for Window {
255 #[inline]
256 #[cfg(feature = "x11")]
257 fn xlib_window(&self) -> Option<raw::c_ulong> {
258 match self.window {
259 LinuxWindow::X(ref w) => Some(w.xlib_window()),
260 #[cfg(feature = "wayland")]
261 _ => None,
262 }
263 }
264
265 #[inline]
266 #[cfg(feature = "x11")]
267 fn xlib_display(&self) -> Option<*mut raw::c_void> {
268 match self.window {
269 LinuxWindow::X(ref w) => Some(w.xlib_display()),
270 #[cfg(feature = "wayland")]
271 _ => None,
272 }
273 }
274
275 #[inline]
276 #[cfg(feature = "x11")]
277 fn xlib_screen_id(&self) -> Option<raw::c_int> {
278 match self.window {
279 LinuxWindow::X(ref w) => Some(w.xlib_screen_id()),
280 #[cfg(feature = "wayland")]
281 _ => None,
282 }
283 }
284
285 #[inline]
286 #[doc(hidden)]
287 #[cfg(feature = "x11")]
288 fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
289 match self.window {
290 LinuxWindow::X(ref w) => Some(w.xlib_xconnection()),
291 #[cfg(feature = "wayland")]
292 _ => None,
293 }
294 }
295
296 #[inline]
297 #[cfg(feature = "x11")]
298 fn xcb_connection(&self) -> Option<*mut raw::c_void> {
299 match self.window {
300 LinuxWindow::X(ref w) => Some(w.xcb_connection()),
301 #[cfg(feature = "wayland")]
302 _ => None,
303 }
304 }
305
306 #[inline]
307 #[cfg(feature = "wayland")]
308 fn wayland_surface(&self) -> Option<*mut raw::c_void> {
309 match self.window {
310 LinuxWindow::Wayland(ref w) => Some(w.surface().as_ref().c_ptr() as *mut _),
311 #[cfg(feature = "x11")]
312 _ => None,
313 }
314 }
315
316 #[inline]
317 #[cfg(feature = "wayland")]
318 fn wayland_display(&self) -> Option<*mut raw::c_void> {
319 match self.window {
320 LinuxWindow::Wayland(ref w) => Some(w.display().get_display_ptr() as *mut _),
321 #[cfg(feature = "x11")]
322 _ => None,
323 }
324 }
325
326 #[inline]
327 #[cfg(feature = "wayland")]
328 fn set_wayland_theme<T: Theme>(&self, theme: T) {
329 match self.window {
330 LinuxWindow::Wayland(ref w) => w.set_theme(theme),
331 #[cfg(feature = "x11")]
332 _ => {}
333 }
334 }
335
336 #[inline]
337 fn is_ready(&self) -> bool {
338 true
339 }
340}
341
342pub trait WindowBuilderExtUnix {
344 #[cfg(feature = "x11")]
345 fn with_x11_visual<T>(self, visual_infos: *const T) -> Self;
346 #[cfg(feature = "x11")]
347 fn with_x11_screen(self, screen_id: i32) -> Self;
348
349 #[cfg(feature = "x11")]
351 fn with_class(self, class: String, instance: String) -> Self;
352 #[cfg(feature = "x11")]
354 fn with_override_redirect(self, override_redirect: bool) -> Self;
355 #[cfg(feature = "x11")]
357 fn with_x11_window_type(self, x11_window_type: Vec<XWindowType>) -> Self;
358 #[cfg(feature = "x11")]
360 fn with_gtk_theme_variant(self, variant: String) -> Self;
361 #[cfg(feature = "x11")]
363 fn with_resize_increments<S: Into<Size>>(self, increments: S) -> Self;
364 #[cfg(feature = "x11")]
366 fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self;
367
368 #[cfg(feature = "wayland")]
374 fn with_app_id(self, app_id: String) -> Self;
375}
376
377impl WindowBuilderExtUnix for WindowBuilder {
378 #[inline]
379 #[cfg(feature = "x11")]
380 fn with_x11_visual<T>(mut self, visual_infos: *const T) -> Self {
381 {
382 self.platform_specific.visual_infos =
383 Some(unsafe { ptr::read(visual_infos as *const XVisualInfo) });
384 }
385 self
386 }
387
388 #[inline]
389 #[cfg(feature = "x11")]
390 fn with_x11_screen(mut self, screen_id: i32) -> Self {
391 self.platform_specific.screen_id = Some(screen_id);
392 self
393 }
394
395 #[inline]
396 #[cfg(feature = "x11")]
397 fn with_class(mut self, instance: String, class: String) -> Self {
398 self.platform_specific.class = Some((instance, class));
399 self
400 }
401
402 #[inline]
403 #[cfg(feature = "x11")]
404 fn with_override_redirect(mut self, override_redirect: bool) -> Self {
405 self.platform_specific.override_redirect = override_redirect;
406 self
407 }
408
409 #[inline]
410 #[cfg(feature = "x11")]
411 fn with_x11_window_type(mut self, x11_window_types: Vec<XWindowType>) -> Self {
412 self.platform_specific.x11_window_types = x11_window_types;
413 self
414 }
415
416 #[inline]
417 #[cfg(feature = "x11")]
418 fn with_gtk_theme_variant(mut self, variant: String) -> Self {
419 self.platform_specific.gtk_theme_variant = Some(variant);
420 self
421 }
422
423 #[inline]
424 #[cfg(feature = "x11")]
425 fn with_resize_increments<S: Into<Size>>(mut self, increments: S) -> Self {
426 self.platform_specific.resize_increments = Some(increments.into());
427 self
428 }
429
430 #[inline]
431 #[cfg(feature = "x11")]
432 fn with_base_size<S: Into<Size>>(mut self, base_size: S) -> Self {
433 self.platform_specific.base_size = Some(base_size.into());
434 self
435 }
436
437 #[inline]
438 #[cfg(feature = "wayland")]
439 fn with_app_id(mut self, app_id: String) -> Self {
440 self.platform_specific.app_id = Some(app_id);
441 self
442 }
443}
444
445pub trait MonitorHandleExtUnix {
447 fn native_id(&self) -> u32;
449}
450
451impl MonitorHandleExtUnix for MonitorHandle {
452 #[inline]
453 fn native_id(&self) -> u32 {
454 self.inner.native_identifier()
455 }
456}
457
458#[cfg(feature = "wayland")]
460pub trait Theme: Send + 'static {
461 fn element_color(&self, element: Element, window_active: bool) -> ARGBColor;
463
464 fn button_color(
466 &self,
467 button: Button,
468 state: ButtonState,
469 foreground: bool,
470 window_active: bool,
471 ) -> ARGBColor;
472
473 fn font(&self) -> Option<(String, f32)> {
479 Some((String::from("sans-serif"), 17.))
482 }
483}
484
485#[cfg(feature = "wayland")]
487#[derive(Clone, Copy, Debug, PartialEq, Eq)]
488pub enum Button {
489 Maximize,
491
492 Minimize,
494
495 Close,
497}
498
499#[cfg(feature = "wayland")]
501#[derive(Clone, Copy, Debug, PartialEq, Eq)]
502pub enum ButtonState {
503 Hovered,
505 Idle,
507 Disabled,
509}
510
511#[cfg(feature = "wayland")]
512#[derive(Clone, Copy, Debug, PartialEq, Eq)]
513pub enum Element {
514 Bar,
516
517 Separator,
519
520 Text,
522}
523
524#[cfg(feature = "wayland")]
525#[derive(Clone, Copy, Debug, PartialEq, Eq)]
526pub struct ARGBColor {
527 pub a: u8,
528 pub r: u8,
529 pub g: u8,
530 pub b: u8,
531}