1use super::{MAX_PROPERTY_VALUE_LEN, MOUSEMASK, Screen, WindowHandle, XlibError};
3use crate::{XWrap, XlibWindowHandle};
4use leftwm_core::models::{BBox, DockArea, WindowState, WindowType, XyhwChange};
5use std::ffi::{CStr, CString};
6use std::os::raw::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong};
7use std::slice;
8use x11_dl::xinerama::XineramaScreenInfo;
9use x11_dl::xlib::{self, XWindowAttributes};
10use x11_dl::xrandr::XRRCrtcInfo;
11
12impl XWrap {
13 pub fn get_all_windows(&self) -> Result<Vec<xlib::Window>, String> {
21 let mut all = Vec::new();
22 for root in self.get_roots() {
23 {
24 let some_windows = self.get_windows_for_root(root)?;
25 for w in some_windows {
26 all.push(*w);
27 }
28 }
29 }
30 Ok(all)
31 }
32
33 #[must_use]
38 pub fn get_color(&self, color: String) -> c_ulong {
39 unsafe {
40 let screen = (self.xlib.XDefaultScreen)(self.display);
41 let cmap: xlib::Colormap = (self.xlib.XDefaultColormap)(self.display, screen);
42 let color_cstr = CString::new(color).unwrap_or_default().into_raw();
43 let mut color: xlib::XColor = std::mem::zeroed();
44 (self.xlib.XAllocNamedColor)(
45 self.display,
46 cmap,
47 color_cstr,
48 &raw mut color,
49 &raw mut color,
50 );
51 color.pixel
52 }
53 }
54
55 pub fn get_cursor_point(&self) -> Result<(i32, i32), XlibError> {
61 let roots = self.get_roots();
62 for w in roots {
63 let mut root_return: xlib::Window = 0;
64 let mut child_return: xlib::Window = 0;
65 let mut root_x_return: c_int = 0;
66 let mut root_y_return: c_int = 0;
67 let mut win_x_return: c_int = 0;
68 let mut win_y_return: c_int = 0;
69 let mut mask_return: c_uint = 0;
70 let success = unsafe {
71 (self.xlib.XQueryPointer)(
72 self.display,
73 w,
74 &raw mut root_return,
75 &raw mut child_return,
76 &raw mut root_x_return,
77 &raw mut root_y_return,
78 &raw mut win_x_return,
79 &raw mut win_y_return,
80 &raw mut mask_return,
81 )
82 };
83 if success > 0 {
84 return Ok((win_x_return, win_y_return));
85 }
86 }
87 Err(XlibError::RootWindowNotFound)
88 }
89
90 pub fn get_cursor_window(&self) -> Result<WindowHandle<XlibWindowHandle>, XlibError> {
96 let roots = self.get_roots();
97 for w in roots {
98 let mut root_return: xlib::Window = 0;
99 let mut child_return: xlib::Window = 0;
100 let mut root_x_return: c_int = 0;
101 let mut root_y_return: c_int = 0;
102 let mut win_x_return: c_int = 0;
103 let mut win_y_return: c_int = 0;
104 let mut mask_return: c_uint = 0;
105 let success = unsafe {
106 (self.xlib.XQueryPointer)(
107 self.display,
108 w,
109 &raw mut root_return,
110 &raw mut child_return,
111 &raw mut root_x_return,
112 &raw mut root_y_return,
113 &raw mut win_x_return,
114 &raw mut win_y_return,
115 &raw mut mask_return,
116 )
117 };
118 if success > 0 {
119 return Ok(WindowHandle(XlibWindowHandle(child_return)));
120 }
121 }
122 Err(XlibError::RootWindowNotFound)
123 }
124
125 #[must_use]
127 pub const fn get_default_root_handle(&self) -> WindowHandle<XlibWindowHandle> {
128 WindowHandle(XlibWindowHandle(self.root))
129 }
130
131 #[must_use]
133 pub const fn get_default_root(&self) -> xlib::Window {
134 self.root
135 }
136
137 #[must_use]
139 pub fn get_hint_sizing_as_xyhw(&self, window: xlib::Window) -> Option<XyhwChange> {
140 let hint = self.get_hint_sizing(window);
141 if let Some(size) = hint {
142 let mut xyhw = XyhwChange::default();
143
144 if (size.flags & xlib::PSize) != 0 || (size.flags & xlib::USSize) != 0 {
145 xyhw.w = Some(size.width);
147 xyhw.h = Some(size.height);
148 } else if (size.flags & xlib::PBaseSize) != 0 {
149 xyhw.w = Some(size.base_width);
150 xyhw.h = Some(size.base_height);
151 }
152
153 if (size.flags & xlib::PResizeInc) != 0 {
154 xyhw.w = Some(size.width_inc);
155 xyhw.h = Some(size.height_inc);
156 }
157
158 if (size.flags & xlib::PMaxSize) != 0 {
159 xyhw.maxw = Some(size.max_width);
160 xyhw.maxh = Some(size.max_height);
161 }
162
163 if (size.flags & xlib::PMinSize) != 0 {
164 xyhw.minw = Some(size.min_width);
165 xyhw.minh = Some(size.min_height);
166 }
167 xyhw.w = std::cmp::max(xyhw.w, xyhw.minw);
169 xyhw.h = std::cmp::max(xyhw.h, xyhw.minh);
170 xyhw.w = xyhw.w.filter(|&w| w != 0);
172 xyhw.h = xyhw.h.filter(|&h| h != 0);
173
174 if (size.flags & xlib::PPosition) != 0 || (size.flags & xlib::USPosition) != 0 {
175 xyhw.x = Some(size.x);
177 xyhw.y = Some(size.y);
178 }
179 return Some(xyhw);
186 }
187 None
188 }
189
190 #[must_use]
193 pub fn get_mask_event(&self) -> xlib::XEvent {
194 unsafe {
195 let mut event: xlib::XEvent = std::mem::zeroed();
196 (self.xlib.XMaskEvent)(
197 self.display,
198 MOUSEMASK | xlib::SubstructureRedirectMask | xlib::ExposureMask,
199 &raw mut event,
200 );
201 event
202 }
203 }
204
205 #[must_use]
208 pub fn get_next_event(&self) -> xlib::XEvent {
209 unsafe {
210 let mut event: xlib::XEvent = std::mem::zeroed();
211 (self.xlib.XNextEvent)(self.display, &raw mut event);
212 event
213 }
214 }
215
216 #[must_use]
222 pub fn get_screens(&self) -> Vec<Screen<XlibWindowHandle>> {
223 use x11_dl::xinerama::Xlib;
224 use x11_dl::xrandr::Xrandr;
225 let xlib = Xlib::open().expect("Couldn't not connect to Xorg Server");
226
227 if let Ok(xrandr) = Xrandr::open() {
230 unsafe {
231 let screen_resources = (xrandr.XRRGetScreenResources)(self.display, self.root);
232 let outputs = slice::from_raw_parts(
233 (*screen_resources).outputs,
234 (*screen_resources).noutput as usize,
235 );
236
237 return outputs
238 .iter()
239 .map(|output| {
240 (xrandr.XRRGetOutputInfo)(self.display, screen_resources, *output)
241 })
242 .filter(|&output_info| (*output_info).crtc != 0)
243 .map(|output_info| {
244 let crtc_info = (xrandr.XRRGetCrtcInfo)(
245 self.display,
246 screen_resources,
247 (*output_info).crtc,
248 );
249 let mut s: Screen<XlibWindowHandle> =
250 XRRCrtcInfoIntoScreen(*crtc_info).into();
251 s.root = self.get_default_root_handle();
252 s.output = CStr::from_ptr((*output_info).name)
253 .to_string_lossy()
254 .into_owned();
255 s
256 })
257 .collect();
258 }
259 }
260
261 let xinerama = unsafe { (xlib.XineramaIsActive)(self.display) } > 0;
262 if xinerama {
263 let root = self.get_default_root_handle();
264 let mut screen_count = 0;
265 let info_array_raw =
266 unsafe { (xlib.XineramaQueryScreens)(self.display, &raw mut screen_count) };
267 let xinerama_infos: &[XineramaScreenInfo] =
269 unsafe { slice::from_raw_parts(info_array_raw, screen_count as usize) };
270 xinerama_infos
271 .iter()
272 .map(|i| {
273 let mut s: Screen<XlibWindowHandle> = XineramaScreenInfoIntoScreen(i).into();
274 s.root = root;
275 s
276 })
277 .collect()
278 } else {
279 let roots: Result<Vec<xlib::XWindowAttributes>, _> =
281 self.get_roots().map(|w| self.get_window_attrs(w)).collect();
282 let roots = roots.expect("Error: No screen were detected");
283 roots
284 .iter()
285 .map(|attrs| XWindowAttributesIntoScreen(attrs).into())
286 .collect()
287 }
288 }
289
290 #[must_use]
292 pub fn get_screens_area_dimensions(&self) -> (i32, i32) {
293 let mut height = 0;
294 let mut width = 0;
295 for s in self.get_screens() {
296 height = std::cmp::max(height, s.bbox.height + s.bbox.y);
297 width = std::cmp::max(width, s.bbox.width + s.bbox.x);
298 }
299 (height, width)
300 }
301
302 #[must_use]
305 pub fn get_transient_for(&self, window: xlib::Window) -> Option<xlib::Window> {
306 unsafe {
307 let mut transient: xlib::Window = std::mem::zeroed();
308 let status: c_int =
309 (self.xlib.XGetTransientForHint)(self.display, window, &raw mut transient);
310 if status > 0 { Some(transient) } else { None }
311 }
312 }
313
314 #[must_use]
317 pub fn get_window_actions_atoms(&self, window: xlib::Window) -> Vec<xlib::Atom> {
318 let mut format_return: i32 = 0;
319 let mut nitems_return: c_ulong = 0;
320 let mut bytes_remaining: c_ulong = 0;
321 let mut type_return: xlib::Atom = 0;
322 let mut prop_return: *mut c_uchar = unsafe { std::mem::zeroed() };
323 unsafe {
324 let status = (self.xlib.XGetWindowProperty)(
325 self.display,
326 window,
327 self.atoms.NetWMAction,
328 0,
329 MAX_PROPERTY_VALUE_LEN / 4,
330 xlib::False,
331 xlib::XA_ATOM,
332 &raw mut type_return,
333 &raw mut format_return,
334 &raw mut nitems_return,
335 &raw mut bytes_remaining,
336 &raw mut prop_return,
337 );
338 if status == i32::from(xlib::Success) && !prop_return.is_null() {
339 #[allow(clippy::cast_lossless, clippy::cast_ptr_alignment)]
340 let ptr = prop_return as *const c_ulong;
341 let results: &[xlib::Atom] = slice::from_raw_parts(ptr, nitems_return as usize);
342 return results.to_vec();
343 }
344 vec![]
345 }
346 }
347
348 pub fn get_window_attrs(
354 &self,
355 window: xlib::Window,
356 ) -> Result<xlib::XWindowAttributes, XlibError> {
357 let mut attrs: xlib::XWindowAttributes = unsafe { std::mem::zeroed() };
358 let status =
359 unsafe { (self.xlib.XGetWindowAttributes)(self.display, window, &raw mut attrs) };
360 if status == 0 {
361 return Err(XlibError::FailedStatus);
362 }
363 Ok(attrs)
364 }
365
366 #[must_use]
369 pub fn get_window_class(&self, window: xlib::Window) -> Option<(String, String)> {
370 unsafe {
371 let mut class_return: xlib::XClassHint = std::mem::zeroed();
372 let status = (self.xlib.XGetClassHint)(self.display, window, &raw mut class_return);
373 if status == 0 {
374 return None;
375 }
376 let Ok(res_name) =
377 CString::from_raw(class_return.res_name.cast::<c_char>()).into_string()
378 else {
379 return None;
380 };
381 let Ok(res_class) =
382 CString::from_raw(class_return.res_class.cast::<c_char>()).into_string()
383 else {
384 return None;
385 };
386 Some((res_name, res_class))
387 }
388 }
389
390 pub fn get_window_geometry(&self, window: xlib::Window) -> Result<XyhwChange, XlibError> {
396 let mut root_return: xlib::Window = 0;
397 let mut x_return: c_int = 0;
398 let mut y_return: c_int = 0;
399 let mut width_return: c_uint = 0;
400 let mut height_return: c_uint = 0;
401 let mut border_width_return: c_uint = 0;
402 let mut depth_return: c_uint = 0;
403 unsafe {
404 let status = (self.xlib.XGetGeometry)(
405 self.display,
406 window,
407 &raw mut root_return,
408 &raw mut x_return,
409 &raw mut y_return,
410 &raw mut width_return,
411 &raw mut height_return,
412 &raw mut border_width_return,
413 &raw mut depth_return,
414 );
415 if status == 0 {
416 return Err(XlibError::FailedStatus);
417 }
418 }
419 Ok(XyhwChange {
420 x: Some(x_return),
421 y: Some(y_return),
422 w: Some(width_return as i32),
423 h: Some(height_return as i32),
424 ..XyhwChange::default()
425 })
426 }
427
428 #[must_use]
430 pub fn get_window_name(&self, window: xlib::Window) -> Option<String> {
431 if let Ok(text) = self.get_text_prop(window, self.atoms.NetWMName) {
432 return Some(text);
433 }
434 if let Ok(text) = self.get_text_prop(window, xlib::XA_WM_NAME) {
435 return Some(text);
436 }
437 None
438 }
439
440 #[must_use]
442 pub fn get_window_legacy_name(&self, window: xlib::Window) -> Option<String> {
443 if let Ok(text) = self.get_text_prop(window, xlib::XA_WM_NAME) {
444 return Some(text);
445 }
446 None
447 }
448
449 #[must_use]
451 pub fn get_window_pid(&self, window: xlib::Window) -> Option<u32> {
452 let (prop_return, _) = self
453 .get_property(window, self.atoms.NetWMPid, xlib::XA_CARDINAL)
454 .ok()?;
455 unsafe {
456 #[allow(clippy::cast_lossless, clippy::cast_ptr_alignment)]
457 let pid = *prop_return.cast::<u32>();
458 Some(pid)
459 }
460 }
461
462 #[must_use]
464 pub fn get_window_states(&self, window: xlib::Window) -> Vec<WindowState> {
465 let window_states_atoms = self.get_window_states_atoms(window);
466
467 let maximized = window_states_atoms.contains(&self.atoms.NetWMStateMaximizedVert)
471 && window_states_atoms.contains(&self.atoms.NetWMStateMaximizedHorz);
472
473 let mut window_states: Vec<WindowState> = window_states_atoms
474 .iter()
475 .map(|a| match a {
476 x if x == &self.atoms.NetWMStateModal => WindowState::Modal,
477 x if x == &self.atoms.NetWMStateSticky => WindowState::Sticky,
478 x if x == &self.atoms.NetWMStateMaximizedVert && !maximized => {
479 WindowState::MaximizedVert
480 }
481 x if x == &self.atoms.NetWMStateMaximizedHorz && !maximized => {
482 WindowState::MaximizedHorz
483 }
484 x if x == &self.atoms.NetWMStateShaded => WindowState::Shaded,
485 x if x == &self.atoms.NetWMStateSkipTaskbar => WindowState::SkipTaskbar,
486 x if x == &self.atoms.NetWMStateSkipPager => WindowState::SkipPager,
487 x if x == &self.atoms.NetWMStateHidden => WindowState::Hidden,
488 x if x == &self.atoms.NetWMStateFullscreen => WindowState::Fullscreen,
489 x if x == &self.atoms.NetWMStateAbove => WindowState::Above,
490 x if x == &self.atoms.NetWMStateBelow => WindowState::Below,
491 _ => WindowState::Modal,
492 })
493 .collect();
494
495 if maximized {
496 window_states.push(WindowState::Maximized);
497 }
498
499 window_states
500 }
501
502 #[must_use]
505 pub fn get_window_states_atoms(&self, window: xlib::Window) -> Vec<xlib::Atom> {
506 let mut format_return: i32 = 0;
507 let mut nitems_return: c_ulong = 0;
508 let mut bytes_remaining: c_ulong = 0;
509 let mut type_return: xlib::Atom = 0;
510 let mut prop_return: *mut c_uchar = unsafe { std::mem::zeroed() };
511 unsafe {
512 let status = (self.xlib.XGetWindowProperty)(
513 self.display,
514 window,
515 self.atoms.NetWMState,
516 0,
517 MAX_PROPERTY_VALUE_LEN / 4,
518 xlib::False,
519 xlib::XA_ATOM,
520 &raw mut type_return,
521 &raw mut format_return,
522 &raw mut nitems_return,
523 &raw mut bytes_remaining,
524 &raw mut prop_return,
525 );
526 if status == i32::from(xlib::Success) && !prop_return.is_null() {
527 #[allow(clippy::cast_lossless, clippy::cast_ptr_alignment)]
528 let ptr = prop_return as *const c_ulong;
529 let results: &[xlib::Atom] = slice::from_raw_parts(ptr, nitems_return as usize);
530 return results.to_vec();
531 }
532 vec![]
533 }
534 }
535
536 #[must_use]
538 pub fn get_window_strut_array(&self, window: xlib::Window) -> Option<DockArea> {
539 if let Some(d) = self.get_window_strut_array_strut_partial(window) {
541 tracing::trace!("STRUT:[{:?}] {:?}", window, d);
542 return Some(d);
543 }
544 if let Some(d) = self.get_window_strut_array_strut(window) {
546 tracing::trace!("STRUT:[{:?}] {:?}", window, d);
547 return Some(d);
548 }
549 None
550 }
551
552 #[must_use]
554 pub fn get_window_type(&self, window: xlib::Window) -> WindowType {
555 let mut atom = None;
556 if let Ok((prop_return, _)) =
557 self.get_property(window, self.atoms.NetWMWindowType, xlib::XA_ATOM)
558 {
559 #[allow(clippy::cast_lossless, clippy::cast_ptr_alignment)]
560 let atom_ = unsafe { *prop_return.cast::<xlib::Atom>() };
561 atom = Some(atom_);
562 }
563 match atom {
564 x if x == Some(self.atoms.NetWMWindowTypeDesktop) => WindowType::Desktop,
565 x if x == Some(self.atoms.NetWMWindowTypeDock) => WindowType::Dock,
566 x if x == Some(self.atoms.NetWMWindowTypeToolbar) => WindowType::Toolbar,
567 x if x == Some(self.atoms.NetWMWindowTypeMenu) => WindowType::Menu,
568 x if x == Some(self.atoms.NetWMWindowTypeUtility) => WindowType::Utility,
569 x if x == Some(self.atoms.NetWMWindowTypeSplash) => WindowType::Splash,
570 x if x == Some(self.atoms.NetWMWindowTypeDialog) => WindowType::Dialog,
571 x if x == Some(self.atoms.NetWMWindowTypeDropdownMenu) => WindowType::DropdownMenu,
572 x if x == Some(self.atoms.NetWMWindowTypePopupMenu) => WindowType::PopupMenu,
573 x if x == Some(self.atoms.NetWMWindowTypeTooltip) => WindowType::Tooltip,
574 x if x == Some(self.atoms.NetWMWindowTypeNotification) => WindowType::Notification,
575 x if x == Some(self.atoms.NetWMWindowTypeCombo) => WindowType::Combo,
576 x if x == Some(self.atoms.NetWMWindowTypeDnd) => WindowType::Dnd,
577 _ => WindowType::Normal,
578 }
579 }
580
581 #[must_use]
584 pub fn get_wmhints(&self, window: xlib::Window) -> Option<xlib::XWMHints> {
585 unsafe {
586 let hints_ptr: *const xlib::XWMHints = (self.xlib.XGetWMHints)(self.display, window);
587 if hints_ptr.is_null() {
588 return None;
589 }
590 let hints: xlib::XWMHints = *hints_ptr;
591 Some(hints)
592 }
593 }
594
595 #[must_use]
597 pub fn get_wm_state(&self, window: xlib::Window) -> Option<c_long> {
598 let (prop_return, nitems_return) = self
599 .get_property(window, self.atoms.WMState, self.atoms.WMState)
600 .ok()?;
601 if nitems_return == 0 {
602 return None;
603 }
604 #[allow(clippy::cast_ptr_alignment)]
605 Some(unsafe { *prop_return.cast::<c_long>() })
606 }
607
608 pub fn get_xatom_name(&self, atom: xlib::Atom) -> Result<String, XlibError> {
614 unsafe {
615 let cstring = (self.xlib.XGetAtomName)(self.display, atom);
616 if let Ok(s) = CString::from_raw(cstring).into_string() {
617 return Ok(s);
618 }
619 };
620 Err(XlibError::InvalidXAtom)
621 }
622
623 #[must_use]
628 fn get_hint_sizing(&self, window: xlib::Window) -> Option<xlib::XSizeHints> {
629 let mut xsize: xlib::XSizeHints = unsafe { std::mem::zeroed() };
630 let mut msize: c_long = xlib::PSize;
631 let status = unsafe {
632 (self.xlib.XGetWMNormalHints)(self.display, window, &raw mut xsize, &raw mut msize)
633 };
634 match status {
635 0 => None,
636 _ => Some(xsize),
637 }
638 }
639
640 fn get_property(
646 &self,
647 window: xlib::Window,
648 property: xlib::Atom,
649 r#type: xlib::Atom,
650 ) -> Result<(*const c_uchar, c_ulong), XlibError> {
651 let mut format_return: i32 = 0;
652 let mut nitems_return: c_ulong = 0;
653 let mut type_return: xlib::Atom = 0;
654 let mut bytes_after_return: xlib::Atom = 0;
655 let mut prop_return: *mut c_uchar = unsafe { std::mem::zeroed() };
656 unsafe {
657 let status = (self.xlib.XGetWindowProperty)(
658 self.display,
659 window,
660 property,
661 0,
662 MAX_PROPERTY_VALUE_LEN / 4,
663 xlib::False,
664 r#type,
665 &raw mut type_return,
666 &raw mut format_return,
667 &raw mut nitems_return,
668 &raw mut bytes_after_return,
669 &raw mut prop_return,
670 );
671 if status == i32::from(xlib::Success) && !prop_return.is_null() {
672 return Ok((prop_return, nitems_return));
673 }
674 };
675 Err(XlibError::FailedStatus)
676 }
677
678 fn get_roots(&self) -> impl Iterator<Item = xlib::Window> + '_ {
681 self.get_xscreens()
682 .map(|mut s| unsafe { (self.xlib.XRootWindowOfScreen)(&raw mut s) })
683 }
684
685 fn get_text_prop(&self, window: xlib::Window, atom: xlib::Atom) -> Result<String, XlibError> {
693 unsafe {
694 let mut text_prop: xlib::XTextProperty = std::mem::zeroed();
695 let status: c_int =
696 (self.xlib.XGetTextProperty)(self.display, window, &raw mut text_prop, atom);
697 if status == 0 {
698 return Err(XlibError::FailedStatus);
699 }
700 if let Ok(s) = CString::from_raw(text_prop.value.cast::<c_char>()).into_string() {
701 return Ok(s);
702 }
703 };
704 Err(XlibError::FailedStatus)
705 }
706
707 fn get_windows_for_root<'w>(&self, root: xlib::Window) -> Result<&'w [xlib::Window], String> {
713 unsafe {
714 let mut root_return: xlib::Window = std::mem::zeroed();
715 let mut parent_return: xlib::Window = std::mem::zeroed();
716 let mut array: *mut xlib::Window = std::mem::zeroed();
717 let mut length: c_uint = std::mem::zeroed();
718 let status: xlib::Status = (self.xlib.XQueryTree)(
719 self.display,
720 root,
721 &raw mut root_return,
722 &raw mut parent_return,
723 &raw mut array,
724 &raw mut length,
725 );
726 let windows: &[xlib::Window] = slice::from_raw_parts(array, length as usize);
727 match status {
728 0 => { Err("Could not load list of windows".to_string() ) }
729 1 | 2 => { Ok(windows) }
730 _ => { Err("Unknown return status".to_string() ) }
731 }
732 }
733 }
734
735 fn get_window_strut_array_strut(&self, window: xlib::Window) -> Option<DockArea> {
737 let (prop_return, nitems_return) = self
738 .get_property(window, self.atoms.NetWMStrut, xlib::XA_CARDINAL)
739 .ok()?;
740 unsafe {
741 #[allow(clippy::cast_ptr_alignment)]
742 let array_ptr = prop_return.cast::<c_long>();
743 let slice = slice::from_raw_parts(array_ptr, nitems_return as usize);
744 if slice.len() == 12 {
745 return Some(SliceIntoDockArea(slice).into());
746 }
747 None
748 }
749 }
750
751 fn get_window_strut_array_strut_partial(&self, window: xlib::Window) -> Option<DockArea> {
753 let (prop_return, nitems_return) = self
754 .get_property(window, self.atoms.NetWMStrutPartial, xlib::XA_CARDINAL)
755 .ok()?;
756 unsafe {
757 #[allow(clippy::cast_ptr_alignment)]
758 let array_ptr = prop_return.cast::<c_long>();
759 let slice = slice::from_raw_parts(array_ptr, nitems_return as usize);
760 if slice.len() == 12 {
761 return Some(SliceIntoDockArea(slice).into());
762 }
763 None
764 }
765 }
766
767 fn get_xscreens(&self) -> impl Iterator<Item = xlib::Screen> + '_ {
771 let screen_count = unsafe { (self.xlib.XScreenCount)(self.display) };
772
773 let screen_ids = 0..screen_count;
774
775 screen_ids
776 .map(|screen_id| unsafe { *(self.xlib.XScreenOfDisplay)(self.display, screen_id) })
777 }
778}
779
780struct XRRCrtcInfoIntoScreen(XRRCrtcInfo);
781
782impl From<XRRCrtcInfoIntoScreen> for Screen<XlibWindowHandle> {
783 fn from(val: XRRCrtcInfoIntoScreen) -> Self {
784 Screen {
785 bbox: BBox {
786 x: val.0.x,
787 y: val.0.y,
788 width: val.0.width as i32,
789 height: val.0.height as i32,
790 },
791 ..Default::default()
792 }
793 }
794}
795
796struct XineramaScreenInfoIntoScreen<'a>(&'a XineramaScreenInfo);
797
798impl From<XineramaScreenInfoIntoScreen<'_>> for Screen<XlibWindowHandle> {
799 fn from(val: XineramaScreenInfoIntoScreen<'_>) -> Self {
800 Screen {
801 bbox: BBox {
802 height: val.0.height.into(),
803 width: val.0.width.into(),
804 x: val.0.x_org.into(),
805 y: val.0.y_org.into(),
806 },
807 ..Default::default()
808 }
809 }
810}
811
812struct XWindowAttributesIntoScreen<'a>(&'a XWindowAttributes);
813
814impl From<XWindowAttributesIntoScreen<'_>> for Screen<XlibWindowHandle> {
815 fn from(val: XWindowAttributesIntoScreen<'_>) -> Self {
816 Screen {
817 root: WindowHandle(XlibWindowHandle(val.0.root)),
818 bbox: BBox {
819 height: val.0.height,
820 width: val.0.width,
821 x: val.0.x,
822 y: val.0.y,
823 },
824 ..Default::default()
825 }
826 }
827}
828
829#[cfg(target_pointer_width = "64")]
830struct SliceIntoDockArea<'a>(&'a [i64]);
831
832#[cfg(target_pointer_width = "32")]
833struct SliceIntoDockArea<'a>(&'a [i32]);
834
835impl From<SliceIntoDockArea<'_>> for DockArea {
836 fn from(val: SliceIntoDockArea<'_>) -> Self {
837 DockArea {
838 left: val.0[0] as i32,
839 right: val.0[1] as i32,
840 top: val.0[2] as i32,
841 bottom: val.0[3] as i32,
842 left_start_y: val.0[4] as i32,
843 left_end_y: val.0[5] as i32,
844 right_start_y: val.0[6] as i32,
845 right_end_y: val.0[7] as i32,
846 top_start_x: val.0[8] as i32,
847 top_end_x: val.0[9] as i32,
848 bottom_start_x: val.0[10] as i32,
849 bottom_end_x: val.0[11] as i32,
850 }
851 }
852}