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 std::{ops::Rem, usize};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -20,6 +19,7 @@ mod client {
|
||||||
pub(crate) size: Point<i32>,
|
pub(crate) size: Point<i32>,
|
||||||
pub(crate) position: Point<i32>,
|
pub(crate) position: Point<i32>,
|
||||||
pub(crate) transient_for: Option<Window>,
|
pub(crate) transient_for: Option<Window>,
|
||||||
|
pub(crate) fullscreen: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Client {
|
impl Default for Client {
|
||||||
|
@ -29,6 +29,7 @@ mod client {
|
||||||
size: (100, 100).into(),
|
size: (100, 100).into(),
|
||||||
position: (0, 0).into(),
|
position: (0, 0).into(),
|
||||||
transient_for: None,
|
transient_for: None,
|
||||||
|
fullscreen: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +45,7 @@ mod client {
|
||||||
window,
|
window,
|
||||||
size,
|
size,
|
||||||
position,
|
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 {
|
pub fn is_transient(&self) -> bool {
|
||||||
self.transient_for.is_some()
|
self.transient_for.is_some()
|
||||||
}
|
}
|
||||||
|
@ -408,6 +430,43 @@ impl ClientState {
|
||||||
self.arrange_virtual_screen();
|
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
|
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.
|
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();
|
let vs = self.virtual_screens.get_mut_current();
|
||||||
// if aux is empty -> width : width / 2
|
// if aux is empty -> width : width / 2
|
||||||
|
|
||||||
let (master_width, aux_width) = {
|
let vs_width = width - gap * 2;
|
||||||
let effective_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
|
1.0
|
||||||
} else {
|
} else {
|
||||||
self.master_size / 2.0
|
self.master_size / 2.0
|
||||||
};
|
};
|
||||||
|
|
||||||
let master_width = (effective_width as f32 * master_size) as i32;
|
let width = (vs_width as f32 * factor) as i32;
|
||||||
let aux_width = effective_width - master_width;
|
|
||||||
|
|
||||||
(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
|
let aux_position = Point::new(master_window_size.width, 0);
|
||||||
// height is max height / number of clients in the stack
|
let aux_window_size = {
|
||||||
let master_height = (height - gap * 2)
|
let width = vs_width - master_window_size.width;
|
||||||
/ match NonZeroI32::new(vs.master.len() as i32) {
|
|
||||||
Some(i) => i.get(),
|
// make sure we dont devide by 0
|
||||||
None => 1,
|
// 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
|
Size::new(width, height)
|
||||||
let aux_height = (height - gap * 2)
|
};
|
||||||
/ match NonZeroI32::new(vs.aux.len() as i32) {
|
|
||||||
Some(i) => i.get(),
|
fn calculate_window_dimensions(
|
||||||
None => 1,
|
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
|
// Master
|
||||||
for (i, key) in vs.master.iter().enumerate() {
|
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) {
|
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 {
|
*client = Client {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
position: position.into(),
|
position,
|
||||||
..*client
|
..*client
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -685,18 +782,20 @@ impl ClientState {
|
||||||
|
|
||||||
// Aux
|
// Aux
|
||||||
for (i, key) in vs.aux.iter().enumerate() {
|
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) {
|
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 {
|
*client = Client {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
position: position.into(),
|
position,
|
||||||
..*client
|
..*client
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
26
src/state.rs
26
src/state.rs
|
@ -8,9 +8,9 @@ use crate::{
|
||||||
backends::{
|
backends::{
|
||||||
keycodes::{MouseButton, VirtualKeyCode},
|
keycodes::{MouseButton, VirtualKeyCode},
|
||||||
window_event::{
|
window_event::{
|
||||||
ButtonEvent, ConfigureEvent, FullscreenEvent, KeyBind, KeyEvent,
|
ButtonEvent, ConfigureEvent, FullscreenEvent, FullscreenState,
|
||||||
KeyState, MapEvent, ModifierKey, ModifierState, MotionEvent,
|
KeyBind, KeyEvent, KeyState, MapEvent, ModifierKey, ModifierState,
|
||||||
MouseBind, Point, WindowEvent,
|
MotionEvent, MouseBind, Point, WindowEvent,
|
||||||
},
|
},
|
||||||
xlib::XLib,
|
xlib::XLib,
|
||||||
WindowServerBackend,
|
WindowServerBackend,
|
||||||
|
@ -469,6 +469,20 @@ where
|
||||||
state,
|
state,
|
||||||
}) => {
|
}) => {
|
||||||
info!("FullscreenEvent for window {}: {:?}", window, 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.
|
// i dont think i actually have to handle destroy notify events.
|
||||||
|
@ -658,6 +672,12 @@ where
|
||||||
self.clients
|
self.clients
|
||||||
.iter_transient()
|
.iter_transient()
|
||||||
.for_each(|(_, c)| self.backend.raise_window(c.window));
|
.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) {
|
fn arrange_clients(&mut self) {
|
||||||
|
|
Loading…
Reference in a new issue