refactor Client to better reflect different window types
This commit is contained in:
parent
449b4cccd8
commit
bae880c5e1
|
@ -1,6 +1,6 @@
|
|||
use log::{debug, error, warn};
|
||||
use num_traits::Zero;
|
||||
use std::{ptr::NonNull, rc::Rc};
|
||||
use std::{convert::TryFrom, ptr::NonNull, rc::Rc};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -193,7 +193,7 @@ pub mod wmh {
|
|||
pub mod ewmh {
|
||||
use std::{borrow::Borrow, ffi::CString, ops::Index, os::raw::c_long};
|
||||
|
||||
use strum::{EnumCount, EnumIter};
|
||||
use strum::{EnumCount, EnumIter, FromRepr};
|
||||
use x11::xlib::{Atom, XA_ATOM};
|
||||
|
||||
use super::{
|
||||
|
@ -201,7 +201,9 @@ pub mod ewmh {
|
|||
Display,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy, FromRepr,
|
||||
)]
|
||||
pub enum EWMHAtom {
|
||||
NetSupported,
|
||||
NetClientList,
|
||||
|
@ -914,8 +916,6 @@ impl XLib {
|
|||
) == i32::from(Success)
|
||||
});
|
||||
|
||||
debug!("get_atom_property: {} {:?}", success, atom_out);
|
||||
|
||||
success.then(|| atom_out).flatten()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,17 @@ use indexmap::IndexMap;
|
|||
use log::error;
|
||||
use num_traits::Zero;
|
||||
|
||||
use crate::backends::structs::WindowType;
|
||||
use crate::util::BuildIdentityHasher;
|
||||
use crate::util::{Point, Size};
|
||||
|
||||
mod client {
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use crate::util::{Point, Size};
|
||||
use crate::{
|
||||
backends::structs::WindowType,
|
||||
util::{Point, Size},
|
||||
};
|
||||
use x11::xlib::Window;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -18,7 +22,8 @@ mod client {
|
|||
pub(crate) window: Window,
|
||||
pub(crate) size: Size<i32>,
|
||||
pub(crate) position: Point<i32>,
|
||||
pub(crate) transient_for: Option<Window>,
|
||||
pub(crate) parent_window: Option<Window>,
|
||||
pub(crate) window_type: WindowType,
|
||||
pub(crate) fullscreen: bool,
|
||||
}
|
||||
|
||||
|
@ -28,8 +33,9 @@ mod client {
|
|||
window: 0,
|
||||
size: (100, 100).into(),
|
||||
position: (0, 0).into(),
|
||||
transient_for: None,
|
||||
parent_window: None,
|
||||
fullscreen: false,
|
||||
window_type: WindowType::Normal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +55,7 @@ mod client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_transient(
|
||||
pub fn new_dialog(
|
||||
window: Window,
|
||||
size: Size<i32>,
|
||||
transient: Window,
|
||||
|
@ -57,7 +63,7 @@ mod client {
|
|||
Self {
|
||||
window,
|
||||
size,
|
||||
transient_for: Some(transient),
|
||||
parent_window: Some(transient),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +75,24 @@ mod client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_window_type(self, window_type: WindowType) -> Self {
|
||||
Self {
|
||||
window_type,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_parent_window(self, parent_window: Option<Window>) -> Self {
|
||||
Self {
|
||||
parent_window,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_size(self, size: Size<i32>) -> Self {
|
||||
Self { size, ..self }
|
||||
}
|
||||
|
||||
/// toggles the clients fullscreen flag.
|
||||
/// returns `true` if the client is now fullscreen.
|
||||
pub fn toggle_fullscreen(&mut self) -> bool {
|
||||
|
@ -90,8 +114,8 @@ mod client {
|
|||
self.fullscreen
|
||||
}
|
||||
|
||||
pub fn is_transient(&self) -> bool {
|
||||
self.transient_for.is_some()
|
||||
pub fn has_parent_window(&self) -> bool {
|
||||
self.parent_window.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,27 +264,42 @@ impl ClientState {
|
|||
pub fn insert(&mut self, mut client: Client) -> Option<&Client> {
|
||||
let key = client.key();
|
||||
|
||||
if client.is_transient()
|
||||
&& self.contains(&client.transient_for.unwrap())
|
||||
match client.window_type {
|
||||
// idk how to handle docks and desktops, for now they float innit
|
||||
WindowType::Splash
|
||||
| WindowType::Dialog
|
||||
| WindowType::Utility
|
||||
| WindowType::Menu
|
||||
| WindowType::Toolbar
|
||||
| WindowType::Dock
|
||||
| WindowType::Desktop => {
|
||||
if let Some(parent) = client
|
||||
.parent_window
|
||||
.and_then(|window| self.get(&window).into_option())
|
||||
{
|
||||
let transient = self.get(&client.transient_for.unwrap()).unwrap();
|
||||
|
||||
client.position = {
|
||||
(
|
||||
transient.position.x
|
||||
+ (transient.size.width - client.size.width) / 2,
|
||||
transient.position.y
|
||||
+ (transient.size.height - client.size.height) / 2,
|
||||
parent.position.x
|
||||
+ (parent.size.width - client.size.width) / 2,
|
||||
parent.position.y
|
||||
+ (parent.size.height - client.size.height) / 2,
|
||||
)
|
||||
.into()
|
||||
};
|
||||
}
|
||||
|
||||
client.size = client.size.clamp(
|
||||
self.screen_size
|
||||
- Size::new(self.border_size * 2, self.border_size * 2),
|
||||
);
|
||||
|
||||
self.floating_clients.insert(key, client);
|
||||
} else {
|
||||
}
|
||||
WindowType::Normal => {
|
||||
self.clients.insert(key, client);
|
||||
|
||||
self.virtual_screens.get_mut_current().insert(&key);
|
||||
}
|
||||
}
|
||||
|
||||
// adding a client changes the liling layout, rearrange
|
||||
self.arrange_virtual_screen();
|
||||
|
@ -320,7 +359,15 @@ impl ClientState {
|
|||
}
|
||||
|
||||
pub fn iter_transient(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||
self.iter_floating().filter(|&(_, c)| c.is_transient())
|
||||
self.iter_floating().filter(|&(_, c)| c.has_parent_window())
|
||||
}
|
||||
|
||||
pub fn iter_by_window_type(
|
||||
&self,
|
||||
window_type: WindowType,
|
||||
) -> impl Iterator<Item = (&u64, &Client)> {
|
||||
self.iter_floating()
|
||||
.filter(move |&(_, c)| c.window_type == window_type)
|
||||
}
|
||||
|
||||
pub fn iter_visible(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||
|
@ -357,7 +404,7 @@ impl ClientState {
|
|||
{
|
||||
match self.get(key) {
|
||||
ClientEntry::Floating(c) => {
|
||||
if let Some(transient_for) = c.transient_for {
|
||||
if let Some(transient_for) = c.parent_window {
|
||||
self.is_client_visible(&transient_for)
|
||||
} else {
|
||||
true
|
||||
|
@ -519,15 +566,15 @@ impl ClientState {
|
|||
}
|
||||
(None, Some(floating_client)) => {
|
||||
// transient clients cannot be tiled
|
||||
match floating_client.is_transient() {
|
||||
true => {
|
||||
self.floating_clients.insert(key, floating_client);
|
||||
}
|
||||
|
||||
false => {
|
||||
// only normal windows can be tiled
|
||||
match floating_client.window_type {
|
||||
WindowType::Normal => {
|
||||
self.clients.insert(key, floating_client);
|
||||
self.virtual_screens.get_mut_current().insert(&key);
|
||||
}
|
||||
_ => {
|
||||
self.floating_clients.insert(key, floating_client);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
18
src/state.rs
18
src/state.rs
|
@ -4,6 +4,7 @@ use log::{error, info};
|
|||
|
||||
use x11::xlib::{self, Window};
|
||||
|
||||
use crate::backends::structs::WindowType;
|
||||
use crate::backends::window_event::{
|
||||
FullscreenEvent, FullscreenState, WindowNameEvent,
|
||||
};
|
||||
|
@ -748,19 +749,16 @@ where
|
|||
}
|
||||
|
||||
fn new_client(&mut self, window: Window) {
|
||||
info!("new client: {:?}", window);
|
||||
let client = if let Some(transient_window) =
|
||||
self.backend.get_parent_window(window)
|
||||
{
|
||||
Client::new_transient(
|
||||
window,
|
||||
let client = match self.backend.get_window_type(window) {
|
||||
WindowType::Normal => Client::new_default(window),
|
||||
window_type @ _ => Client::new_default(window)
|
||||
.with_window_type(window_type)
|
||||
.with_size(
|
||||
self.backend
|
||||
.get_window_size(window)
|
||||
.unwrap_or((100, 100).into()),
|
||||
transient_window,
|
||||
)
|
||||
} else {
|
||||
Client::new_default(window)
|
||||
.with_parent_window(self.backend.get_parent_window(window)),
|
||||
};
|
||||
|
||||
self.backend.configure_window(
|
||||
|
@ -770,6 +768,8 @@ where
|
|||
Some(self.clients.get_border()),
|
||||
);
|
||||
|
||||
info!("new client: {:#?}", client);
|
||||
|
||||
self.clients.insert(client).unwrap();
|
||||
self.arrange_clients();
|
||||
|
||||
|
|
Loading…
Reference in a new issue