From f6a871d1e7a21afaf530842c5ea58aedb618e314 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 18:15:45 +0100 Subject: [PATCH] changed `FullscreenEvent` to be `On, Off, Toggle` instead of a simple bool --- src/backends/window_event.rs | 27 ++++++++--- src/backends/xlib/mod.rs | 86 ++++++++++++++++++++++++++++++++++-- src/state.rs | 12 +++-- 3 files changed, 111 insertions(+), 14 deletions(-) diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index c99beba..507f0af 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -265,18 +265,31 @@ impl ConfigureEvent { } } +#[derive(Debug)] +pub enum FullscreenState { + On, + Off, + Toggle, +} + +impl From for FullscreenState { + fn from(value: bool) -> Self { + match value { + true => Self::On, + false => Self::Off, + } + } +} + #[derive(Debug)] pub struct FullscreenEvent { - window: Window, - new_fullscreen: bool, + pub window: Window, + pub state: FullscreenState, } impl FullscreenEvent { - pub fn new(window: Window, new_fullscreen: bool) -> Self { - Self { - window, - new_fullscreen, - } + pub fn new(window: Window, state: FullscreenState) -> Self { + Self { window, state } } } diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 87d4f85..22ee3de 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -1,5 +1,5 @@ use log::{error, warn}; -use std::{ffi::CString, rc::Rc}; +use std::{ffi::CString, mem::MaybeUninit, rc::Rc}; use thiserror::Error; @@ -17,9 +17,9 @@ use self::keysym::{ use super::{ keycodes::VirtualKeyCode, window_event::{ - ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, KeyEvent, - KeyOrMouseBind, KeyState, MapEvent, ModifierState, MotionEvent, Point, - UnmapEvent, WindowEvent, + ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, FullscreenEvent, + FullscreenState, KeyEvent, KeyOrMouseBind, KeyState, MapEvent, + ModifierState, MotionEvent, Point, UnmapEvent, WindowEvent, }, WindowServerBackend, }; @@ -285,6 +285,53 @@ impl XLib { )) }) } + xlib::PropertyNotify => { + let ev = unsafe { &event.property }; + + (ev.atom == self.atoms.net_wm_window_type) + .then(|| { + (self.get_atom_property( + ev.window, + self.atoms.net_wm_state, + ) == Some(self.atoms.net_wm_state_fullscreen)) + .then(|| { + XLibWindowEvent::FullscreenEvent( + FullscreenEvent::new( + ev.window, + FullscreenState::On, + ), + ) + }) + }) + .flatten() + } + xlib::ClientMessage => { + let ev = unsafe { &event.client_message }; + + (ev.message_type == self.atoms.net_wm_state) + .then(|| { + let data = ev.data.as_longs(); + (data[1] as u64 == self.atoms.net_wm_state_fullscreen + || data[2] as u64 + == self.atoms.net_wm_state_fullscreen) + .then(|| { + XLibWindowEvent::FullscreenEvent( + FullscreenEvent::new( + ev.window, + match data[0] /* as u64 */ { + 0 => FullscreenState::Off, + 1 => FullscreenState::On, + 2 => FullscreenState::Toggle, + _ => { + unreachable!() + } + }, + ), + ) + }) + }) + .flatten() + } _ => None, } } @@ -308,6 +355,37 @@ impl XLib { } } + fn get_atom_property( + &self, + window: xlib::Window, + atom: xlib::Atom, + ) -> Option { + let mut di = 0; + let mut dl0 = 0; + let mut dl1 = 0; + let mut da = 0; + + let mut atom_out = MaybeUninit::::zeroed(); + + unsafe { + (xlib::XGetWindowProperty( + self.dpy(), + window, + atom, + 0, + std::mem::size_of::() as i64, + 0, + xlib::XA_ATOM, + &mut da, + &mut di, + &mut dl0, + &mut dl1, + atom_out.as_mut_ptr() as *mut _, + ) != 0) + .then(|| atom_out.assume_init()) + } + } + fn check_for_protocol( &self, window: xlib::Window, diff --git a/src/state.rs b/src/state.rs index 6e545f3..4e1bdd0 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,9 +8,9 @@ use crate::{ backends::{ keycodes::{MouseButton, VirtualKeyCode}, window_event::{ - ButtonEvent, ConfigureEvent, KeyBind, KeyEvent, KeyState, MapEvent, - ModifierKey, ModifierState, MotionEvent, MouseBind, Point, - WindowEvent, + ButtonEvent, ConfigureEvent, FullscreenEvent, KeyBind, KeyEvent, + KeyState, MapEvent, ModifierKey, ModifierState, MotionEvent, + MouseBind, Point, WindowEvent, }, xlib::XLib, WindowServerBackend, @@ -464,6 +464,12 @@ where // None => self.xlib.configure_window(event), // } } + WindowEvent::FullscreenEvent(FullscreenEvent { + window, + state, + }) => { + info!("FullscreenEvent for window {}: {:?}", window, state); + } // i dont think i actually have to handle destroy notify events. // every window should be unmapped regardless