Compare commits
26 commits
get_atom_p
...
feature_cu
Author | SHA1 | Date | |
---|---|---|---|
|
1d15ef6336 | ||
|
ae89404de3 | ||
|
fdf81d8d6a | ||
|
1aab741b49 | ||
|
c826556e83 | ||
|
30867df46c | ||
|
364d621b72 | ||
|
bae880c5e1 | ||
|
449b4cccd8 | ||
|
6c4f0d54bd | ||
|
4eb1cb4555 | ||
|
f9afdc990d | ||
|
ac433847c5 | ||
|
0dd42a7039 | ||
|
85d3c3ce79 | ||
|
fb011ea23f | ||
|
2f805dab21 | ||
|
56fff2698b | ||
|
db6ffb9416 | ||
|
ba047217a6 | ||
|
bc13bf43d6 | ||
|
590af3a06c | ||
|
702004d2d2 | ||
|
daf9f72a89 | ||
|
71ddeb6af1 | ||
|
b1895bdd07 |
24
Cargo.toml
24
Cargo.toml
|
@ -1,25 +1,27 @@
|
|||
[package]
|
||||
name = "wm"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["noonebtw <noonebtw@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "nowm"
|
||||
name = "nirgendwm"
|
||||
path = "src/main.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
x11 = {version = "2.18.2", features = ["xlib", "xft"] }
|
||||
log = "0.4.13"
|
||||
simple_logger = "1.11.0"
|
||||
dirs = "3.0.2"
|
||||
log4rs = "1.0.0"
|
||||
indexmap = "1.6.2"
|
||||
thiserror = "1.0.30"
|
||||
bitflags = "1.3.2"
|
||||
x11 = {version = "2.19", features = ["xlib", "xft"] }
|
||||
log = "0.4"
|
||||
simple_logger = "2.0"
|
||||
dirs = "3.0.0"
|
||||
log4rs = "1.0"
|
||||
indexmap = "1.0"
|
||||
thiserror = "1.0"
|
||||
bitflags = "1.3"
|
||||
derivative = "2.2.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
num-traits = "0.2.14"
|
||||
num-traits = "0.2"
|
||||
strum = {version = "0.24.0", features = ["derive"]}
|
||||
bytemuck = "1.0"
|
||||
|
|
8
nirgendwm.toml
Normal file
8
nirgendwm.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
num_virtualscreens = 10
|
||||
mod_key = "Super"
|
||||
gap = 10
|
||||
border_width = 5
|
||||
active_window_border_color = "#6E0AC4"
|
||||
inactive_window_border_color = "#CE9CFA"
|
||||
kill_clients_on_exit = false
|
||||
terminal_command = ["alacritty", []]
|
|
@ -4,3 +4,25 @@ pub mod window_event;
|
|||
pub mod xlib;
|
||||
|
||||
pub use traits::*;
|
||||
|
||||
pub mod structs {
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
pub enum WindowType {
|
||||
Splash,
|
||||
Dialog,
|
||||
Normal,
|
||||
Utility,
|
||||
Menu,
|
||||
Toolbar,
|
||||
Dock,
|
||||
Desktop,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub enum Cursor {
|
||||
Normal,
|
||||
Resize,
|
||||
Move,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use super::window_event::{self, KeyOrMouseBind};
|
||||
use super::{
|
||||
structs::WindowType,
|
||||
window_event::{self, KeyOrMouseBind},
|
||||
};
|
||||
use crate::util::{Point, Size};
|
||||
|
||||
pub trait WindowServerBackend {
|
||||
|
@ -18,6 +21,11 @@ pub trait WindowServerBackend {
|
|||
fn focus_window(&self, window: Self::Window);
|
||||
fn unfocus_window(&self, window: Self::Window);
|
||||
fn raise_window(&self, window: Self::Window);
|
||||
fn set_window_fullscreen_state(
|
||||
&self,
|
||||
window: Self::Window,
|
||||
fullscreen: bool,
|
||||
);
|
||||
fn hide_window(&self, window: Self::Window);
|
||||
fn kill_window(&self, window: Self::Window);
|
||||
fn get_parent_window(&self, window: Self::Window) -> Option<Self::Window>;
|
||||
|
@ -31,6 +39,8 @@ pub trait WindowServerBackend {
|
|||
|
||||
fn screen_size(&self) -> Size<i32>;
|
||||
fn get_window_size(&self, window: Self::Window) -> Option<Size<i32>>;
|
||||
fn get_window_name(&self, window: Self::Window) -> Option<String>;
|
||||
fn get_window_type(&self, window: Self::Window) -> WindowType;
|
||||
|
||||
fn grab_cursor(&self);
|
||||
fn ungrab_cursor(&self);
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use super::keycodes::{KeyOrButton, MouseButton, VirtualKeyCode};
|
||||
use super::{
|
||||
keycodes::{KeyOrButton, MouseButton, VirtualKeyCode},
|
||||
structs::WindowType,
|
||||
};
|
||||
use crate::util::{Point, Size};
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum WindowEvent<Window> {
|
||||
KeyEvent(KeyEvent<Window>),
|
||||
ButtonEvent(ButtonEvent<Window>),
|
||||
|
@ -17,6 +20,8 @@ pub enum WindowEvent<Window> {
|
|||
EnterEvent(EnterEvent<Window>),
|
||||
ConfigureEvent(ConfigureEvent<Window>),
|
||||
FullscreenEvent(FullscreenEvent<Window>), //1 { window: Window, event: 1 },
|
||||
WindowNameEvent(WindowNameEvent<Window>),
|
||||
WindowTypeChangedEvent(WindowTypeChangedEvent<Window>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
|
@ -106,7 +111,7 @@ impl Into<u8> for ModifierKey {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyEvent<Window> {
|
||||
pub window: Window,
|
||||
pub state: KeyState,
|
||||
|
@ -130,7 +135,7 @@ impl<Window> KeyEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ButtonEvent<Window> {
|
||||
pub window: Window,
|
||||
pub state: KeyState,
|
||||
|
@ -157,7 +162,7 @@ impl<Window> ButtonEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MotionEvent<Window> {
|
||||
pub position: Point<i32>,
|
||||
pub window: Window,
|
||||
|
@ -169,22 +174,22 @@ impl<Window> MotionEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MapEvent<Window> {
|
||||
pub window: Window,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UnmapEvent<Window> {
|
||||
pub window: Window,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EnterEvent<Window> {
|
||||
pub window: Window,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DestroyEvent<Window> {
|
||||
pub window: Window,
|
||||
}
|
||||
|
@ -195,7 +200,7 @@ impl<Window> DestroyEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CreateEvent<Window> {
|
||||
pub window: Window,
|
||||
pub position: Point<i32>,
|
||||
|
@ -212,7 +217,7 @@ impl<Window> CreateEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConfigureEvent<Window> {
|
||||
pub window: Window,
|
||||
pub position: Point<i32>,
|
||||
|
@ -229,7 +234,7 @@ impl<Window> ConfigureEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FullscreenState {
|
||||
On,
|
||||
Off,
|
||||
|
@ -245,7 +250,7 @@ impl From<bool> for FullscreenState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FullscreenEvent<Window> {
|
||||
pub window: Window,
|
||||
pub state: FullscreenState,
|
||||
|
@ -257,6 +262,33 @@ impl<Window> FullscreenEvent<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WindowNameEvent<Window> {
|
||||
pub window: Window,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl<Window> WindowNameEvent<Window> {
|
||||
pub fn new(window: Window, name: String) -> Self {
|
||||
Self { window, name }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WindowTypeChangedEvent<Window> {
|
||||
pub window: Window,
|
||||
pub window_type: WindowType,
|
||||
}
|
||||
|
||||
impl<Window> WindowTypeChangedEvent<Window> {
|
||||
pub fn new(window: Window, window_type: WindowType) -> Self {
|
||||
Self {
|
||||
window,
|
||||
window_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct KeyBind {
|
||||
pub key: VirtualKeyCode,
|
||||
|
|
File diff suppressed because it is too large
Load diff
172
src/clients.rs
172
src/clients.rs
|
@ -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,26 +264,41 @@ 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())
|
||||
{
|
||||
let transient = self.get(&client.transient_for.unwrap()).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())
|
||||
{
|
||||
client.position = {
|
||||
(
|
||||
parent.position.x
|
||||
+ (parent.size.width - client.size.width) / 2,
|
||||
parent.position.y
|
||||
+ (parent.size.height - client.size.height) / 2,
|
||||
)
|
||||
.into()
|
||||
};
|
||||
}
|
||||
|
||||
client.position = {
|
||||
(
|
||||
transient.position.x
|
||||
+ (transient.size.width - client.size.width) / 2,
|
||||
transient.position.y
|
||||
+ (transient.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 {
|
||||
self.clients.insert(key, client);
|
||||
|
||||
self.virtual_screens.get_mut_current().insert(&key);
|
||||
self.floating_clients.insert(key, client);
|
||||
}
|
||||
WindowType::Normal => {
|
||||
self.clients.insert(key, client);
|
||||
self.virtual_screens.get_mut_current().insert(&key);
|
||||
}
|
||||
}
|
||||
|
||||
// adding a client changes the liling layout, rearrange
|
||||
|
@ -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
|
||||
|
@ -442,11 +489,12 @@ impl ClientState {
|
|||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// returns `true` if window layout changed
|
||||
pub fn toggle_fullscreen<K>(&mut self, key: &K) -> bool
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
if self.inner_toggle_fullscreen(key) {
|
||||
if let Some(_new_fullscreen_state) = self.inner_toggle_fullscreen(key) {
|
||||
self.arrange_virtual_screen();
|
||||
true
|
||||
} else {
|
||||
|
@ -454,24 +502,22 @@ impl ClientState {
|
|||
}
|
||||
}
|
||||
|
||||
fn inner_toggle_fullscreen<K>(&mut self, key: &K) -> bool
|
||||
fn inner_toggle_fullscreen<K>(&mut self, key: &K) -> Option<bool>
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
let fullscreen_size = self.screen_size
|
||||
- Size::new(self.border_size * 2, self.border_size * 2);
|
||||
let fullscreen_size = self.screen_size;
|
||||
|
||||
match self.get_mut(key).into_option() {
|
||||
Some(client) => {
|
||||
if client.toggle_fullscreen() {
|
||||
client.size = fullscreen_size;
|
||||
client.position = Point::zero();
|
||||
}
|
||||
self.get_mut(key).into_option().map(|client| {
|
||||
if client.toggle_fullscreen() {
|
||||
client.size = fullscreen_size;
|
||||
client.position = Point::zero();
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -491,6 +537,23 @@ impl ClientState {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Sets a floating client to tiled and returns true, does nothing for a tiled client and
|
||||
returns false. If this function returns `true` you have to call `arrange_clients` after.
|
||||
*/
|
||||
pub fn set_tiled<K>(&mut self, key: &K) -> bool
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
if self.get(key).is_floating() {
|
||||
self.toggle_floating(key);
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function invalidates the tiling, call `arrange_clients` to fix it again (it doesn't do it
|
||||
automatically since xlib has to move and resize all windows anyways).
|
||||
|
@ -520,15 +583,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -543,6 +606,20 @@ impl ClientState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_window_type<K>(&mut self, key: &K, window_type: WindowType)
|
||||
where
|
||||
K: ClientKey,
|
||||
{
|
||||
if let Some(client) = self.get_mut(key).into_option() {
|
||||
client.window_type = window_type;
|
||||
|
||||
match window_type {
|
||||
WindowType::Normal => self.set_floating(key),
|
||||
_ => self.set_tiled(key),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_from_virtual_screens<K>(&mut self, key: &K)
|
||||
where
|
||||
K: ClientKey,
|
||||
|
@ -760,10 +837,7 @@ impl ClientState {
|
|||
border: i32,
|
||||
) -> (Size<i32>, Point<i32>) {
|
||||
if fullscreen {
|
||||
let size = Size::new(
|
||||
screen_size.width - border * 2,
|
||||
screen_size.height - border * 2,
|
||||
);
|
||||
let size = Size::new(screen_size.width, screen_size.height);
|
||||
let pos = Point::new(0, 0);
|
||||
(size, pos)
|
||||
} else {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod backends;
|
||||
pub mod clients;
|
||||
pub mod state;
|
||||
|
|
|
@ -21,7 +21,7 @@ fn init_logger() {
|
|||
|
||||
let _logfile = FileAppender::builder()
|
||||
.encoder(encoder)
|
||||
.build(home.join(".local/portlights.log"))
|
||||
.build(home.join(".local/nirgendwm.log"))
|
||||
.unwrap();
|
||||
|
||||
let config = Config::builder()
|
||||
|
@ -31,7 +31,7 @@ fn init_logger() {
|
|||
Root::builder()
|
||||
.appender("stdout")
|
||||
//.appender("logfile")
|
||||
.build(log::LevelFilter::Info),
|
||||
.build(log::LevelFilter::Debug),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -44,7 +44,7 @@ fn main() {
|
|||
log_prologue();
|
||||
|
||||
let mut config_path = std::path::PathBuf::from(env!("HOME"));
|
||||
config_path.push(".config/nowm.toml");
|
||||
config_path.push(".config/nirgendwm.toml");
|
||||
|
||||
let config = std::fs::File::open(config_path)
|
||||
.and_then(|mut file| {
|
||||
|
|
127
src/state.rs
127
src/state.rs
|
@ -4,7 +4,10 @@ use log::{error, info};
|
|||
|
||||
use x11::xlib::{self, Window};
|
||||
|
||||
use crate::backends::window_event::{FullscreenEvent, FullscreenState};
|
||||
use crate::backends::structs::WindowType;
|
||||
use crate::backends::window_event::{
|
||||
FullscreenEvent, FullscreenState, WindowNameEvent, WindowTypeChangedEvent,
|
||||
};
|
||||
use crate::util::{Point, Size};
|
||||
use crate::{
|
||||
backends::{
|
||||
|
@ -37,6 +40,7 @@ pub struct WMConfig {
|
|||
inactive_window_border_color: String,
|
||||
#[serde(default = "WMConfig::default_terminal")]
|
||||
terminal_command: (String, Vec<String>),
|
||||
border_width: Option<i32>,
|
||||
}
|
||||
|
||||
impl WMConfig {
|
||||
|
@ -49,7 +53,7 @@ impl WMConfig {
|
|||
}
|
||||
|
||||
fn default_terminal() -> (String, Vec<String>) {
|
||||
("alacritty".to_string(), vec![])
|
||||
("xterm".to_string(), vec![])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +69,7 @@ impl Default for WMConfig {
|
|||
inactive_window_border_color:
|
||||
Self::default_inactive_window_border_color(),
|
||||
terminal_command: Self::default_terminal(),
|
||||
border_width: Some(1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +150,7 @@ where
|
|||
let clients = ClientState::new()
|
||||
.with_virtualscreens(config.num_virtualscreens)
|
||||
.with_gap(config.gap.unwrap_or(1))
|
||||
.with_border(1)
|
||||
.with_border(config.border_width.unwrap_or(1))
|
||||
.with_screen_size(backend.screen_size());
|
||||
|
||||
Self {
|
||||
|
@ -198,16 +203,6 @@ where
|
|||
},
|
||||
));
|
||||
|
||||
// self.add_keybind(KeyBinding::new(
|
||||
// KeyBind::new(VirtualKeyCode::Print),
|
||||
// |wm, _| wm.spawn("screenshot.sh", &[]),
|
||||
// ));
|
||||
|
||||
// self.add_keybind(KeyBinding::new(
|
||||
// KeyBind::new(VirtualKeyCode::Print).with_mod(ModifierKey::Shift),
|
||||
// |wm, _| wm.spawn("screenshot.sh", &["-edit"]),
|
||||
// ));
|
||||
|
||||
self.add_keybind(KeyBinding::new(
|
||||
KeyBind::new(VirtualKeyCode::M).with_mod(self.config.mod_key),
|
||||
|wm, _| wm.handle_switch_stack(),
|
||||
|
@ -301,13 +296,6 @@ where
|
|||
&self.config.inactive_window_border_color,
|
||||
);
|
||||
|
||||
// add all already existing windows to the WM
|
||||
if let Some(windows) = self.backend.all_windows() {
|
||||
windows
|
||||
.into_iter()
|
||||
.for_each(|window| self.new_client(window));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -426,8 +414,6 @@ where
|
|||
self.button_event(&event);
|
||||
}
|
||||
WindowEvent::MapRequestEvent(MapEvent { window }) => {
|
||||
self.backend.handle_event(event);
|
||||
|
||||
if !self.clients.contains(&window) {
|
||||
self.new_client(window);
|
||||
}
|
||||
|
@ -443,28 +429,27 @@ where
|
|||
self.do_move_resize_window(&event);
|
||||
}
|
||||
WindowEvent::ConfigureEvent(ConfigureEvent {
|
||||
window, ..
|
||||
}) => {
|
||||
match self.clients.get(&window) {
|
||||
ClientEntry::Tiled(client)
|
||||
| ClientEntry::Floating(client) => {
|
||||
self.backend.configure_window(
|
||||
window,
|
||||
Some(client.size),
|
||||
Some(client.position),
|
||||
None,
|
||||
)
|
||||
}
|
||||
ClientEntry::Vacant => self.backend.handle_event(event),
|
||||
window,
|
||||
size,
|
||||
position,
|
||||
..
|
||||
}) => match self.clients.get(&window) {
|
||||
ClientEntry::Tiled(client)
|
||||
| ClientEntry::Floating(client) => {
|
||||
self.backend.configure_window(
|
||||
window,
|
||||
Some(client.size),
|
||||
Some(client.position),
|
||||
None,
|
||||
)
|
||||
}
|
||||
// TODO
|
||||
// match self.clients.get(&event.window).into_option() {
|
||||
// Some(client) => self
|
||||
// .xlib
|
||||
// .configure_client(client, self.clients.get_border()),
|
||||
// None => self.xlib.configure_window(event),
|
||||
// }
|
||||
}
|
||||
ClientEntry::Vacant => self.backend.configure_window(
|
||||
window,
|
||||
Some(size),
|
||||
Some(position),
|
||||
None,
|
||||
),
|
||||
},
|
||||
WindowEvent::FullscreenEvent(FullscreenEvent {
|
||||
window,
|
||||
state,
|
||||
|
@ -480,9 +465,40 @@ where
|
|||
self.clients.toggle_fullscreen(&window)
|
||||
}
|
||||
} {
|
||||
if let Some(client) =
|
||||
self.clients.get(&window).into_option()
|
||||
{
|
||||
self.backend.configure_window(
|
||||
window,
|
||||
None,
|
||||
None,
|
||||
if client.is_fullscreen() {
|
||||
Some(0)
|
||||
} else {
|
||||
Some(self.clients.get_border())
|
||||
},
|
||||
);
|
||||
|
||||
self.backend.set_window_fullscreen_state(
|
||||
client.window,
|
||||
client.is_fullscreen(),
|
||||
);
|
||||
};
|
||||
|
||||
self.arrange_clients();
|
||||
}
|
||||
}
|
||||
WindowEvent::WindowNameEvent(WindowNameEvent { .. }) => {
|
||||
info!("{:#?}", event);
|
||||
}
|
||||
WindowEvent::WindowTypeChangedEvent(
|
||||
WindowTypeChangedEvent {
|
||||
window,
|
||||
window_type,
|
||||
},
|
||||
) => {
|
||||
self.clients.update_window_type(&window, window_type);
|
||||
}
|
||||
|
||||
// i dont think i actually have to handle destroy notify events.
|
||||
// every window should be unmapped regardless
|
||||
|
@ -726,19 +742,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,
|
||||
self.backend
|
||||
.get_window_size(window)
|
||||
.unwrap_or((100, 100).into()),
|
||||
transient_window,
|
||||
)
|
||||
} else {
|
||||
Client::new_default(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()),
|
||||
)
|
||||
.with_parent_window(self.backend.get_parent_window(window)),
|
||||
};
|
||||
|
||||
self.backend.configure_window(
|
||||
|
@ -748,6 +761,8 @@ where
|
|||
Some(self.clients.get_border()),
|
||||
);
|
||||
|
||||
info!("new client: {:#?}", client);
|
||||
|
||||
self.clients.insert(client).unwrap();
|
||||
self.arrange_clients();
|
||||
|
||||
|
|
|
@ -123,6 +123,13 @@ mod size {
|
|||
(self.width, self.height)
|
||||
}
|
||||
|
||||
pub fn clamp(self, other: Self) -> Self {
|
||||
Self::new(
|
||||
self.width.min(other.width),
|
||||
self.height.min(other.height),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn map<F>(self, f: F) -> Self
|
||||
where
|
||||
F: FnOnce(I, I) -> Self,
|
||||
|
|
Loading…
Reference in a new issue