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