wzrd

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in Rust
git clone git://git.deurzen.net/wzrd
Log | Files | Refs | LICENSE

client.rs (22408B)


      1 use crate::change::Toggle;
      2 use crate::compare::MatchMethod;
      3 use crate::decoration::Color;
      4 use crate::decoration::Decoration;
      5 use crate::identify::Ident;
      6 use crate::identify::Identify;
      7 use crate::placement::PlacementClass;
      8 use crate::zone::ZoneId;
      9 
     10 use winsys::connection::Pid;
     11 use winsys::geometry::Extents;
     12 use winsys::geometry::Pos;
     13 use winsys::geometry::Region;
     14 use winsys::hints::SizeHints;
     15 use winsys::window::Window;
     16 use winsys::window::WindowType;
     17 
     18 use std::cell::Cell;
     19 use std::cell::RefCell;
     20 use std::time::SystemTime;
     21 
     22 #[derive(Clone, Copy, Debug)]
     23 pub enum OutsideState {
     24     Focused,
     25     FocusedDisowned,
     26     FocusedSticky,
     27     Unfocused,
     28     UnfocusedDisowned,
     29     UnfocusedSticky,
     30     Urgent,
     31 }
     32 
     33 impl std::ops::Not for OutsideState {
     34     type Output = Self;
     35 
     36     fn not(self) -> Self::Output {
     37         match self {
     38             Self::Focused => Self::Unfocused,
     39             Self::FocusedDisowned => Self::UnfocusedDisowned,
     40             Self::FocusedSticky => Self::UnfocusedSticky,
     41             Self::Unfocused => Self::Focused,
     42             Self::UnfocusedDisowned => Self::FocusedDisowned,
     43             Self::UnfocusedSticky => Self::FocusedSticky,
     44             other => other,
     45         }
     46     }
     47 }
     48 
     49 pub struct Client {
     50     zone: ZoneId,
     51     window: Window,
     52     frame: Window,
     53     name: RefCell<String>,
     54     class: RefCell<String>,
     55     instance: RefCell<String>,
     56     context: Cell<usize>,
     57     workspace: Cell<usize>,
     58     window_type: WindowType,
     59     active_region: Cell<Region>,
     60     previous_region: Cell<Region>,
     61     inner_region: Cell<Region>,
     62     free_region: Cell<Region>,
     63     tile_region: Cell<Region>,
     64     decoration: Cell<Decoration>,
     65     size_hints: Cell<Option<SizeHints>>,
     66     warp_pos: Cell<Option<Pos>>,
     67     parent: Option<Window>,
     68     children: RefCell<Vec<Window>>,
     69     leader: Option<Window>,
     70     producer: Cell<Option<Window>>,
     71     consumers: RefCell<Vec<Window>>,
     72     focused: Cell<bool>,
     73     mapped: Cell<bool>,
     74     managed: Cell<bool>,
     75     urgent: Cell<bool>,
     76     floating: Cell<bool>,
     77     fullscreen: Cell<bool>,
     78     contained: Cell<bool>,
     79     invincible: Cell<bool>,
     80     sticky: Cell<bool>,
     81     iconifyable: Cell<bool>,
     82     iconified: Cell<bool>,
     83     disowned: Cell<bool>,
     84     consuming: Cell<bool>,
     85     producing: Cell<bool>,
     86     outside_state: Cell<OutsideState>,
     87     pid: Option<Pid>,
     88     ppid: Option<Pid>,
     89     last_focused: Cell<SystemTime>,
     90     managed_since: SystemTime,
     91     expected_unmap_count: Cell<u8>,
     92 }
     93 
     94 impl Identify for Window {
     95     #[inline(always)]
     96     fn id(&self) -> Ident {
     97         *self
     98     }
     99 }
    100 
    101 impl Identify for Client {
    102     #[inline(always)]
    103     fn id(&self) -> Ident {
    104         self.window
    105     }
    106 }
    107 
    108 impl Client {
    109     pub fn new(
    110         zone: ZoneId,
    111         window: Window,
    112         frame: Window,
    113         name: impl Into<String>,
    114         class: impl Into<String>,
    115         instance: impl Into<String>,
    116         window_type: WindowType,
    117         pid: Option<Pid>,
    118         ppid: Option<Pid>,
    119     ) -> Self {
    120         Self {
    121             zone,
    122             window,
    123             frame,
    124             name: RefCell::new(name.into()),
    125             class: RefCell::new(class.into()),
    126             instance: RefCell::new(instance.into()),
    127             context: Cell::new(0),
    128             workspace: Cell::new(0),
    129             window_type,
    130             active_region: Cell::new(Default::default()),
    131             previous_region: Cell::new(Default::default()),
    132             inner_region: Cell::new(Default::default()),
    133             free_region: Cell::new(Default::default()),
    134             tile_region: Cell::new(Default::default()),
    135             decoration: Cell::new(Default::default()),
    136             size_hints: Cell::new(None),
    137             warp_pos: Cell::new(None),
    138             parent: None,
    139             children: RefCell::new(Vec::new()),
    140             leader: None,
    141             producer: Cell::new(None),
    142             consumers: RefCell::new(Vec::new()),
    143             focused: Cell::new(false),
    144             mapped: Cell::new(false),
    145             managed: Cell::new(true),
    146             urgent: Cell::new(false),
    147             floating: Cell::new(false),
    148             fullscreen: Cell::new(false),
    149             contained: Cell::new(false),
    150             invincible: Cell::new(false),
    151             sticky: Cell::new(false),
    152             iconifyable: Cell::new(true),
    153             iconified: Cell::new(false),
    154             disowned: Cell::new(false),
    155             consuming: Cell::new(false),
    156             producing: Cell::new(true),
    157             outside_state: Cell::new(OutsideState::Unfocused),
    158             pid,
    159             ppid,
    160             last_focused: Cell::new(SystemTime::now()),
    161             managed_since: SystemTime::now(),
    162             expected_unmap_count: Cell::new(0),
    163         }
    164     }
    165 
    166     #[inline]
    167     pub fn zone(&self) -> ZoneId {
    168         self.zone
    169     }
    170 
    171     #[inline]
    172     pub fn windows(&self) -> (Window, Window) {
    173         (self.window, self.frame)
    174     }
    175 
    176     #[inline]
    177     pub fn window(&self) -> Window {
    178         self.window
    179     }
    180 
    181     #[inline]
    182     pub fn frame(&self) -> Window {
    183         self.frame
    184     }
    185 
    186     #[inline]
    187     pub fn set_name(
    188         &self,
    189         name: impl Into<String>,
    190     ) {
    191         self.name.replace(name.into());
    192     }
    193 
    194     #[inline]
    195     pub fn name(&self) -> String {
    196         self.name.borrow().to_owned()
    197     }
    198 
    199     #[inline]
    200     pub fn name_matches(
    201         &self,
    202         match_method: MatchMethod<&'static str>,
    203     ) -> bool {
    204         match match_method {
    205             MatchMethod::Equals(comp) => &*self.name.borrow() == comp,
    206             MatchMethod::Contains(comp) => (&*self.name.borrow()).contains(comp),
    207         }
    208     }
    209 
    210     #[inline]
    211     pub fn set_class(
    212         &self,
    213         class: impl Into<String>,
    214     ) {
    215         self.class.replace(class.into());
    216     }
    217 
    218     #[inline]
    219     pub fn class(&self) -> String {
    220         self.class.borrow().to_owned()
    221     }
    222 
    223     #[inline]
    224     pub fn class_matches(
    225         &self,
    226         match_method: MatchMethod<&'static str>,
    227     ) -> bool {
    228         match match_method {
    229             MatchMethod::Equals(comp) => &*self.class.borrow() == comp,
    230             MatchMethod::Contains(comp) => (&*self.class.borrow()).contains(comp),
    231         }
    232     }
    233 
    234     #[inline]
    235     pub fn set_instance(
    236         &self,
    237         instance: impl Into<String>,
    238     ) {
    239         self.instance.replace(instance.into());
    240     }
    241 
    242     #[inline]
    243     pub fn instance(&self) -> String {
    244         self.instance.borrow().to_owned()
    245     }
    246 
    247     #[inline]
    248     pub fn instance_matches(
    249         &self,
    250         match_method: MatchMethod<&'static str>,
    251     ) -> bool {
    252         match match_method {
    253             MatchMethod::Equals(comp) => &*self.instance.borrow() == comp,
    254             MatchMethod::Contains(comp) => (&*self.instance.borrow()).contains(comp),
    255         }
    256     }
    257 
    258     #[inline]
    259     pub fn set_context(
    260         &self,
    261         context: usize,
    262     ) {
    263         self.context.set(context);
    264     }
    265 
    266     #[inline]
    267     pub fn context(&self) -> usize {
    268         self.context.get()
    269     }
    270 
    271     #[inline]
    272     pub fn set_workspace(
    273         &self,
    274         workspace: usize,
    275     ) {
    276         self.workspace.set(workspace);
    277     }
    278 
    279     #[inline]
    280     pub fn workspace(&self) -> usize {
    281         self.workspace.get()
    282     }
    283 
    284     #[inline]
    285     pub fn window_type(&self) -> WindowType {
    286         self.window_type
    287     }
    288 
    289     #[inline]
    290     fn set_active_region(
    291         &self,
    292         active_region: Region,
    293     ) {
    294         self.set_inner_region(active_region);
    295         self.previous_region
    296             .set(self.active_region.replace(active_region));
    297     }
    298 
    299     #[inline]
    300     pub fn active_region(&self) -> Region {
    301         self.active_region.get()
    302     }
    303 
    304     #[inline]
    305     pub fn previous_region(&self) -> Region {
    306         self.previous_region.get()
    307     }
    308 
    309     #[inline]
    310     fn set_inner_region(
    311         &self,
    312         active_region: Region,
    313     ) {
    314         self.inner_region
    315             .set(if let Some(frame) = self.decoration.get().frame {
    316                 let mut inner_region = active_region - frame.extents;
    317 
    318                 inner_region.pos.x = frame.extents.left;
    319                 inner_region.pos.y = frame.extents.top;
    320 
    321                 inner_region.dim.w = active_region.dim.w - frame.extents.left - frame.extents.right;
    322                 inner_region.dim.h = active_region.dim.h - frame.extents.top - frame.extents.bottom;
    323 
    324                 inner_region
    325             } else {
    326                 let mut inner_region = active_region;
    327 
    328                 inner_region.pos.x = 0;
    329                 inner_region.pos.y = 0;
    330 
    331                 inner_region
    332             });
    333     }
    334 
    335     #[inline]
    336     pub fn set_region(
    337         &self,
    338         region: PlacementClass<Region>,
    339     ) {
    340         match region {
    341             PlacementClass::Free(region) => {
    342                 self.free_region.set(region);
    343                 self.set_active_region(region);
    344             },
    345             PlacementClass::Tile(region) => {
    346                 self.tile_region.set(region);
    347                 self.set_active_region(region);
    348             },
    349         }
    350     }
    351 
    352     #[inline]
    353     pub fn free_region(&self) -> Region {
    354         self.free_region.get()
    355     }
    356 
    357     #[inline]
    358     pub fn tile_region(&self) -> Region {
    359         self.tile_region.get()
    360     }
    361 
    362     #[inline]
    363     pub fn inner_region(&self) -> Region {
    364         self.inner_region.get()
    365     }
    366 
    367     #[inline]
    368     pub fn set_decoration(
    369         &self,
    370         decoration: Decoration,
    371     ) {
    372         self.decoration.set(decoration);
    373     }
    374 
    375     #[inline]
    376     pub fn decoration(&self) -> Decoration {
    377         self.decoration.get().to_owned()
    378     }
    379 
    380     #[inline(always)]
    381     pub fn decoration_colors(&self) -> (Option<(u32, Color)>, Option<Color>) {
    382         let outside_state = self.outside_state();
    383         let decoration = self.decoration.get();
    384 
    385         match outside_state {
    386             OutsideState::Focused => (
    387                 decoration
    388                     .border
    389                     .map(|border| (border.width, border.colors.focused)),
    390                 decoration.frame.map(|frame| frame.colors.focused),
    391             ),
    392             OutsideState::FocusedDisowned => (
    393                 decoration
    394                     .border
    395                     .map(|border| (border.width, border.colors.fdisowned)),
    396                 decoration.frame.map(|frame| frame.colors.fdisowned),
    397             ),
    398             OutsideState::FocusedSticky => (
    399                 decoration
    400                     .border
    401                     .map(|border| (border.width, border.colors.fsticky)),
    402                 decoration.frame.map(|frame| frame.colors.fsticky),
    403             ),
    404             OutsideState::Unfocused => (
    405                 decoration
    406                     .border
    407                     .map(|border| (border.width, border.colors.unfocused)),
    408                 decoration.frame.map(|frame| frame.colors.unfocused),
    409             ),
    410             OutsideState::UnfocusedDisowned => (
    411                 decoration
    412                     .border
    413                     .map(|border| (border.width, border.colors.udisowned)),
    414                 decoration.frame.map(|frame| frame.colors.udisowned),
    415             ),
    416             OutsideState::UnfocusedSticky => (
    417                 decoration
    418                     .border
    419                     .map(|border| (border.width, border.colors.usticky)),
    420                 decoration.frame.map(|frame| frame.colors.usticky),
    421             ),
    422             OutsideState::Urgent => (
    423                 decoration
    424                     .border
    425                     .map(|border| (border.width, border.colors.urgent)),
    426                 decoration.frame.map(|frame| frame.colors.urgent),
    427             ),
    428         }
    429     }
    430 
    431     #[inline]
    432     pub fn frame_extents(&self) -> Extents {
    433         Extents {
    434             left: 0,
    435             right: 0,
    436             top: 0,
    437             bottom: 0,
    438         } + self.decoration.get().to_owned()
    439     }
    440 
    441     #[inline]
    442     pub fn set_size_hints(
    443         &self,
    444         size_hints: Option<SizeHints>,
    445     ) {
    446         self.size_hints.set(size_hints);
    447     }
    448 
    449     #[inline]
    450     pub fn size_hints(&self) -> Option<SizeHints> {
    451         self.size_hints.get()
    452     }
    453 
    454     #[inline]
    455     pub fn set_warp_pos(
    456         &self,
    457         pointer_pos: Pos,
    458     ) {
    459         self.warp_pos.set(Some(pointer_pos));
    460     }
    461 
    462     #[inline]
    463     pub fn unset_warp_pos(&self) {
    464         self.warp_pos.set(None);
    465     }
    466 
    467     #[inline]
    468     pub fn warp_pos(&self) -> Option<Pos> {
    469         self.warp_pos.get().to_owned()
    470     }
    471 
    472     #[inline]
    473     pub fn set_parent(
    474         &mut self,
    475         parent: Window,
    476     ) {
    477         self.parent = Some(parent);
    478     }
    479 
    480     #[inline]
    481     pub fn parent(&self) -> Option<Window> {
    482         self.parent
    483     }
    484 
    485     #[inline]
    486     pub fn add_child(
    487         &self,
    488         child: Window,
    489     ) {
    490         self.children.borrow_mut().push(child);
    491     }
    492 
    493     #[inline]
    494     pub fn remove_child(
    495         &self,
    496         child: Window,
    497     ) {
    498         let mut children = self.children.borrow_mut();
    499         if let Some(index) = children.iter().rposition(|&c| c == child) {
    500             children.remove(index);
    501         }
    502     }
    503 
    504     #[inline]
    505     pub fn set_leader(
    506         &mut self,
    507         leader: Window,
    508     ) {
    509         self.leader = Some(leader);
    510     }
    511 
    512     #[inline]
    513     pub fn leader(&self) -> Option<Window> {
    514         self.leader
    515     }
    516 
    517     #[inline]
    518     pub fn set_producer(
    519         &self,
    520         producer: Window,
    521     ) {
    522         self.producer.set(Some(producer));
    523     }
    524 
    525     #[inline]
    526     pub fn unset_producer(&self) {
    527         self.producer.set(None);
    528     }
    529 
    530     #[inline]
    531     pub fn producer(&self) -> Option<Window> {
    532         self.producer.get()
    533     }
    534 
    535     #[inline]
    536     pub fn add_consumer(
    537         &self,
    538         consumer: Window,
    539     ) {
    540         self.consumers.borrow_mut().push(consumer);
    541     }
    542 
    543     #[inline]
    544     pub fn remove_consumer(
    545         &self,
    546         consumer: Window,
    547     ) {
    548         let mut consumers = self.consumers.borrow_mut();
    549         if let Some(index) = consumers.iter().rposition(|&c| c == consumer) {
    550             consumers.remove(index);
    551         }
    552     }
    553 
    554     #[inline]
    555     pub fn consumer_len(&self) -> usize {
    556         self.consumers.borrow().len()
    557     }
    558 
    559     #[inline]
    560     pub fn is_consuming(&self) -> bool {
    561         self.producer.get().is_some()
    562     }
    563 
    564     #[inline]
    565     pub fn set_focused(
    566         &self,
    567         toggle: Toggle,
    568     ) {
    569         if Toggle::from(self.focused.get()) != toggle {
    570             self.focused.set(toggle.eval(self.focused.get()));
    571             self.outside_state.set(!self.outside_state.get());
    572         }
    573     }
    574 
    575     #[inline]
    576     pub fn is_focused(&self) -> bool {
    577         self.focused.get()
    578     }
    579 
    580     #[inline]
    581     pub fn set_mapped(
    582         &self,
    583         toggle: Toggle,
    584     ) {
    585         self.mapped.set(toggle.eval(self.mapped.get()));
    586     }
    587 
    588     #[inline]
    589     pub fn is_mapped(&self) -> bool {
    590         self.mapped.get()
    591     }
    592 
    593     #[inline]
    594     pub fn set_managed(
    595         &self,
    596         toggle: Toggle,
    597     ) {
    598         self.managed.set(toggle.eval(self.managed.get()));
    599     }
    600 
    601     #[inline]
    602     pub fn is_managed(&self) -> bool {
    603         self.managed.get()
    604     }
    605 
    606     #[inline]
    607     pub fn set_urgent(
    608         &self,
    609         toggle: Toggle,
    610     ) {
    611         let urgent = toggle.eval(self.urgent.get());
    612         self.urgent.set(urgent);
    613 
    614         if urgent {
    615             self.outside_state.set(OutsideState::Urgent);
    616         }
    617     }
    618 
    619     #[inline]
    620     pub fn is_urgent(&self) -> bool {
    621         self.urgent.get()
    622     }
    623 
    624     #[inline]
    625     pub fn is_free(&self) -> bool {
    626         self.floating.get() && (!self.fullscreen.get() || self.contained.get())
    627             || self.disowned.get()
    628             || !self.managed.get()
    629     }
    630 
    631     #[inline]
    632     pub fn set_floating(
    633         &self,
    634         toggle: Toggle,
    635     ) {
    636         self.floating.set(toggle.eval(self.floating.get()));
    637     }
    638 
    639     #[inline]
    640     pub fn is_floating(&self) -> bool {
    641         self.floating.get()
    642     }
    643 
    644     #[inline]
    645     pub fn set_fullscreen(
    646         &self,
    647         toggle: Toggle,
    648     ) {
    649         self.fullscreen.set(toggle.eval(self.fullscreen.get()));
    650     }
    651 
    652     #[inline]
    653     pub fn is_fullscreen(&self) -> bool {
    654         self.fullscreen.get()
    655     }
    656 
    657     #[inline]
    658     pub fn set_contained(
    659         &self,
    660         toggle: Toggle,
    661     ) {
    662         self.contained.set(toggle.eval(self.contained.get()));
    663     }
    664 
    665     #[inline]
    666     pub fn is_contained(&self) -> bool {
    667         self.contained.get()
    668     }
    669 
    670     #[inline]
    671     pub fn set_invincible(
    672         &self,
    673         toggle: Toggle,
    674     ) {
    675         self.invincible.set(toggle.eval(self.invincible.get()));
    676     }
    677 
    678     #[inline]
    679     pub fn is_invincible(&self) -> bool {
    680         self.invincible.get()
    681     }
    682 
    683     #[inline]
    684     pub fn set_iconifyable(
    685         &self,
    686         toggle: Toggle,
    687     ) {
    688         self.iconifyable.set(toggle.eval(self.iconifyable.get()));
    689     }
    690 
    691     #[inline]
    692     pub fn is_iconifyable(&self) -> bool {
    693         self.iconifyable.get()
    694     }
    695 
    696     #[inline]
    697     pub fn set_producing(
    698         &self,
    699         toggle: Toggle,
    700     ) {
    701         self.producing.set(toggle.eval(self.producing.get()));
    702     }
    703 
    704     #[inline]
    705     pub fn is_producing(&self) -> bool {
    706         self.producing.get()
    707     }
    708 
    709     #[inline]
    710     pub fn set_iconified(
    711         &self,
    712         toggle: Toggle,
    713     ) {
    714         self.iconified.set(toggle.eval(self.iconified.get()));
    715     }
    716 
    717     #[inline]
    718     pub fn is_iconified(&self) -> bool {
    719         self.iconified.get()
    720     }
    721 
    722     #[inline]
    723     pub fn set_sticky(
    724         &self,
    725         toggle: Toggle,
    726     ) {
    727         let sticky = toggle.eval(self.sticky.get());
    728         self.sticky.set(sticky);
    729 
    730         self.outside_state.set(match self.outside_state.get() {
    731             OutsideState::Focused if sticky => OutsideState::FocusedSticky,
    732             OutsideState::Unfocused if sticky => OutsideState::UnfocusedSticky,
    733             OutsideState::FocusedSticky if !sticky => OutsideState::Focused,
    734             OutsideState::UnfocusedSticky if !sticky => OutsideState::Unfocused,
    735             _ => return,
    736         });
    737     }
    738 
    739     #[inline]
    740     pub fn is_sticky(&self) -> bool {
    741         self.sticky.get()
    742     }
    743 
    744     #[inline]
    745     pub fn set_disowned(
    746         &self,
    747         toggle: Toggle,
    748     ) {
    749         let disowned = toggle.eval(self.disowned.get());
    750         self.disowned.set(disowned);
    751 
    752         self.outside_state.set(match self.outside_state.get() {
    753             OutsideState::Focused if disowned => OutsideState::FocusedDisowned,
    754             OutsideState::Unfocused if disowned => OutsideState::UnfocusedDisowned,
    755             OutsideState::FocusedDisowned if !disowned => OutsideState::Focused,
    756             OutsideState::UnfocusedDisowned if !disowned => OutsideState::Unfocused,
    757             _ => return,
    758         });
    759     }
    760 
    761     #[inline]
    762     pub fn is_disowned(&self) -> bool {
    763         self.disowned.get()
    764     }
    765 
    766     #[inline]
    767     pub fn outside_state(&self) -> OutsideState {
    768         if self.urgent.get() {
    769             OutsideState::Urgent
    770         } else {
    771             self.outside_state.get()
    772         }
    773     }
    774 
    775     #[inline]
    776     pub fn pid(&self) -> Option<Pid> {
    777         self.pid
    778     }
    779 
    780     #[inline]
    781     pub fn ppid(&self) -> Option<Pid> {
    782         self.ppid
    783     }
    784 
    785     #[inline]
    786     pub fn last_focused(&self) -> SystemTime {
    787         self.last_focused.get()
    788     }
    789 
    790     #[inline]
    791     pub fn managed_since(&self) -> SystemTime {
    792         self.managed_since
    793     }
    794 
    795     #[inline]
    796     pub fn expect_unmap(&self) {
    797         self.expected_unmap_count
    798             .set(self.expected_unmap_count.get() + 1);
    799     }
    800 
    801     #[inline]
    802     pub fn consume_unmap_if_expecting(&self) -> bool {
    803         let expected_unmap_count = self.expected_unmap_count.get();
    804         let expecting = expected_unmap_count > 0;
    805 
    806         if expecting {
    807             self.expected_unmap_count.set(expected_unmap_count - 1);
    808         }
    809 
    810         expecting
    811     }
    812 
    813     #[inline]
    814     pub fn is_expecting_unmap(&self) -> bool {
    815         self.expected_unmap_count.get() > 0
    816     }
    817 }
    818 
    819 impl PartialEq for Client {
    820     fn eq(
    821         &self,
    822         other: &Self,
    823     ) -> bool {
    824         self.window == other.window
    825     }
    826 }
    827 
    828 pub struct Hex32(pub u32);
    829 
    830 impl std::fmt::Debug for Hex32 {
    831     fn fmt(
    832         &self,
    833         f: &mut std::fmt::Formatter<'_>,
    834     ) -> std::fmt::Result {
    835         write!(f, "{:#0x}", &self.0)
    836     }
    837 }
    838 
    839 impl std::fmt::Debug for Client {
    840     fn fmt(
    841         &self,
    842         f: &mut std::fmt::Formatter<'_>,
    843     ) -> std::fmt::Result {
    844         f.debug_struct("Client")
    845             .field("window", &Hex32(self.window))
    846             .field("frame", &Hex32(self.frame))
    847             .field("name", &self.name)
    848             .field("class", &self.class)
    849             .field("instance", &self.instance)
    850             .field("context", &self.context)
    851             .field("workspace", &self.workspace)
    852             .field("window_type", &self.window_type)
    853             .field("active_region", &self.active_region)
    854             .field("previous_region", &self.previous_region)
    855             .field("inner_region", &self.inner_region)
    856             .field("free_region", &self.free_region)
    857             .field("tile_region", &self.tile_region)
    858             .field("decoration", &self.decoration)
    859             .field("size_hints", &self.size_hints)
    860             .field("warp_pos", &self.warp_pos)
    861             .field("parent", &self.parent.map(Hex32))
    862             .field(
    863                 "children",
    864                 &self
    865                     .children
    866                     .borrow()
    867                     .iter()
    868                     .map(|&child| Hex32(child))
    869                     .collect::<Vec<Hex32>>(),
    870             )
    871             .field("leader", &self.leader)
    872             .field("producer", &self.producer)
    873             .field("consumers", &self.consumers)
    874             .field("focused", &self.focused)
    875             .field("mapped", &self.mapped)
    876             .field("managed", &self.managed)
    877             .field("contained", &self.contained)
    878             .field("floating", &self.floating)
    879             .field("fullscreen", &self.fullscreen)
    880             .field("iconified", &self.iconified)
    881             .field("disowned", &self.disowned)
    882             .field("sticky", &self.sticky)
    883             .field("invincible", &self.invincible)
    884             .field("urgent", &self.urgent)
    885             .field("consuming", &self.consuming)
    886             .field("pid", &self.pid)
    887             .field("ppid", &self.ppid)
    888             .field("last_focused", &self.last_focused)
    889             .field("managed_since", &self.managed_since)
    890             .field("expected_unmap_count", &self.expected_unmap_count)
    891             .finish()
    892     }
    893 }