added fullscreen mechanics
This commit is contained in:
parent
c9b926f5ba
commit
5dbfa6fbcf
173
src/clients.rs
173
src/clients.rs
|
@ -1,4 +1,3 @@
|
|||
use std::num::NonZeroI32;
|
||||
use std::{ops::Rem, usize};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
@ -20,6 +19,7 @@ mod client {
|
|||
pub(crate) size: Point<i32>,
|
||||
pub(crate) position: Point<i32>,
|
||||
pub(crate) transient_for: Option<Window>,
|
||||
pub(crate) fullscreen: bool,
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
|
@ -29,6 +29,7 @@ mod client {
|
|||
size: (100, 100).into(),
|
||||
position: (0, 0).into(),
|
||||
transient_for: None,
|
||||
fullscreen: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +45,7 @@ mod client {
|
|||
window,
|
||||
size,
|
||||
position,
|
||||
transient_for: None,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,6 +69,27 @@ mod client {
|
|||
}
|
||||
}
|
||||
|
||||
/// toggles the clients fullscreen flag.
|
||||
/// returns `true` if the client is now fullscreen.
|
||||
pub fn toggle_fullscreen(&mut self) -> bool {
|
||||
self.fullscreen = !self.fullscreen;
|
||||
|
||||
self.is_fullscreen()
|
||||
}
|
||||
|
||||
pub fn set_fullscreen(&mut self, fullscreen: bool) -> bool {
|
||||
if self.fullscreen == fullscreen {
|
||||
false
|
||||
} else {
|
||||
self.fullscreen = fullscreen;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_fullscreen(&self) -> bool {
|
||||
self.fullscreen
|
||||
}
|
||||
|
||||
pub fn is_transient(&self) -> bool {
|
||||
self.transient_for.is_some()
|
||||
}
|
||||
|
@ -408,6 +430,43 @@ impl ClientState {
|
|||
self.arrange_virtual_screen();
|
||||
}
|
||||
|
||||
pub fn set_fullscreen<K>(&mut self, key: &K, fullscreen: bool) -> bool
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
self.get(key)
|
||||
.into_option()
|
||||
.map(|client| client.is_fullscreen() != fullscreen)
|
||||
.unwrap_or(false)
|
||||
.then(|| self.toggle_fullscreen(key))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn toggle_fullscreen<K>(&mut self, key: &K) -> bool
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
if self.inner_toggle_fullscreen(key) {
|
||||
self.arrange_virtual_screen();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_toggle_fullscreen<K>(&mut self, key: &K) -> bool
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
self.get_mut(key)
|
||||
.into_option()
|
||||
.map(|client| {
|
||||
client.toggle_fullscreen();
|
||||
true
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/**
|
||||
Sets a tiled client to floating and returns true, does nothing for a floating client and
|
||||
returns false. If this function returns `true` you have to call `arrange_clients` after.
|
||||
|
@ -635,49 +694,87 @@ impl ClientState {
|
|||
let vs = self.virtual_screens.get_mut_current();
|
||||
// if aux is empty -> width : width / 2
|
||||
|
||||
let (master_width, aux_width) = {
|
||||
let effective_width = width - gap * 2;
|
||||
let vs_width = width - gap * 2;
|
||||
|
||||
let master_size = if vs.aux.is_empty() {
|
||||
let master_position = Point::new(0, 0);
|
||||
let master_window_size = {
|
||||
let factor = if vs.aux.is_empty() {
|
||||
1.0
|
||||
} else {
|
||||
self.master_size / 2.0
|
||||
};
|
||||
|
||||
let master_width = (effective_width as f32 * master_size) as i32;
|
||||
let aux_width = effective_width - master_width;
|
||||
let width = (vs_width as f32 * factor) as i32;
|
||||
|
||||
(master_width, aux_width)
|
||||
// make sure we dont devide by 0
|
||||
// height is max height / number of clients in the stack
|
||||
let height = match vs.master.len() as i32 {
|
||||
0 => 1,
|
||||
n => (height - gap * 2) / n,
|
||||
};
|
||||
|
||||
Size::new(width, height)
|
||||
};
|
||||
|
||||
// make sure we dont devide by 0
|
||||
// height is max height / number of clients in the stack
|
||||
let master_height = (height - gap * 2)
|
||||
/ match NonZeroI32::new(vs.master.len() as i32) {
|
||||
Some(i) => i.get(),
|
||||
None => 1,
|
||||
let aux_position = Point::new(master_window_size.width, 0);
|
||||
let aux_window_size = {
|
||||
let width = vs_width - master_window_size.width;
|
||||
|
||||
// make sure we dont devide by 0
|
||||
// height is max height / number of clients in the stack
|
||||
let height = match vs.aux.len() as i32 {
|
||||
0 => 1,
|
||||
n => (height - gap * 2) / n,
|
||||
};
|
||||
|
||||
// height is max height / number of clients in the stack
|
||||
let aux_height = (height - gap * 2)
|
||||
/ match NonZeroI32::new(vs.aux.len() as i32) {
|
||||
Some(i) => i.get(),
|
||||
None => 1,
|
||||
};
|
||||
Size::new(width, height)
|
||||
};
|
||||
|
||||
fn calculate_window_dimensions(
|
||||
screen_size: Size<i32>,
|
||||
stack_size: Size<i32>,
|
||||
stack_position: Point<i32>,
|
||||
fullscreen: bool,
|
||||
nth: i32,
|
||||
gap: i32,
|
||||
border: i32,
|
||||
) -> (Size<i32>, Point<i32>) {
|
||||
if fullscreen {
|
||||
let size = Size::new(
|
||||
screen_size.width - border * 2,
|
||||
screen_size.height - border * 2,
|
||||
);
|
||||
let pos = Point::new(0, 0);
|
||||
(size, pos)
|
||||
} else {
|
||||
let size = Size::new(
|
||||
stack_size.width - gap * 2 - border * 2,
|
||||
stack_size.height - gap * 2 - border * 2,
|
||||
);
|
||||
let pos = Point::new(
|
||||
stack_position.x + gap * 2,
|
||||
stack_position.y + stack_size.height * nth + gap * 2,
|
||||
);
|
||||
(size, pos)
|
||||
}
|
||||
}
|
||||
|
||||
// Master
|
||||
for (i, key) in vs.master.iter().enumerate() {
|
||||
let size = (
|
||||
master_width - gap * 2 - self.border_size * 2,
|
||||
master_height - gap * 2 - self.border_size * 2,
|
||||
);
|
||||
|
||||
let position = (gap * 2, master_height * i as i32 + gap * 2);
|
||||
|
||||
if let Some(client) = self.clients.get_mut(key) {
|
||||
let (size, position) = calculate_window_dimensions(
|
||||
self.screen_size.into(),
|
||||
master_window_size,
|
||||
master_position,
|
||||
client.is_fullscreen(),
|
||||
i as i32,
|
||||
gap,
|
||||
self.border_size,
|
||||
);
|
||||
|
||||
*client = Client {
|
||||
size: size.into(),
|
||||
position: position.into(),
|
||||
position,
|
||||
..*client
|
||||
};
|
||||
}
|
||||
|
@ -685,18 +782,20 @@ impl ClientState {
|
|||
|
||||
// Aux
|
||||
for (i, key) in vs.aux.iter().enumerate() {
|
||||
let size = (
|
||||
aux_width - gap * 2 - self.border_size * 2,
|
||||
aux_height - gap * 2 - self.border_size * 2,
|
||||
);
|
||||
|
||||
let position =
|
||||
(master_width + gap * 2, aux_height * i as i32 + gap * 2);
|
||||
|
||||
if let Some(client) = self.clients.get_mut(key) {
|
||||
let (size, position) = calculate_window_dimensions(
|
||||
self.screen_size.into(),
|
||||
aux_window_size,
|
||||
aux_position,
|
||||
client.is_fullscreen(),
|
||||
i as i32,
|
||||
gap,
|
||||
self.border_size,
|
||||
);
|
||||
|
||||
*client = Client {
|
||||
size: size.into(),
|
||||
position: position.into(),
|
||||
position,
|
||||
..*client
|
||||
};
|
||||
}
|
||||
|
|
26
src/state.rs
26
src/state.rs
|
@ -8,9 +8,9 @@ use crate::{
|
|||
backends::{
|
||||
keycodes::{MouseButton, VirtualKeyCode},
|
||||
window_event::{
|
||||
ButtonEvent, ConfigureEvent, FullscreenEvent, KeyBind, KeyEvent,
|
||||
KeyState, MapEvent, ModifierKey, ModifierState, MotionEvent,
|
||||
MouseBind, Point, WindowEvent,
|
||||
ButtonEvent, ConfigureEvent, FullscreenEvent, FullscreenState,
|
||||
KeyBind, KeyEvent, KeyState, MapEvent, ModifierKey, ModifierState,
|
||||
MotionEvent, MouseBind, Point, WindowEvent,
|
||||
},
|
||||
xlib::XLib,
|
||||
WindowServerBackend,
|
||||
|
@ -469,6 +469,20 @@ where
|
|||
state,
|
||||
}) => {
|
||||
info!("FullscreenEvent for window {}: {:?}", window, state);
|
||||
|
||||
if match state {
|
||||
FullscreenState::On => {
|
||||
self.clients.set_fullscreen(&window, true)
|
||||
}
|
||||
FullscreenState::Off => {
|
||||
self.clients.set_fullscreen(&window, false)
|
||||
}
|
||||
FullscreenState::Toggle => {
|
||||
self.clients.toggle_fullscreen(&window)
|
||||
}
|
||||
} {
|
||||
self.arrange_clients();
|
||||
}
|
||||
}
|
||||
|
||||
// i dont think i actually have to handle destroy notify events.
|
||||
|
@ -658,6 +672,12 @@ where
|
|||
self.clients
|
||||
.iter_transient()
|
||||
.for_each(|(_, c)| self.backend.raise_window(c.window));
|
||||
|
||||
//raise fullscreen windows
|
||||
self.clients
|
||||
.iter_current_screen()
|
||||
.filter(|(_, c)| c.is_fullscreen())
|
||||
.for_each(|(_, c)| self.backend.raise_window(c.window));
|
||||
}
|
||||
|
||||
fn arrange_clients(&mut self) {
|
||||
|
|
Loading…
Reference in a new issue