more advanced logging, fixed floating windows not being on top

This commit is contained in:
NoOneBtw 2021-05-01 22:17:43 +02:00
parent 46e2c7448c
commit 09548522ff
5 changed files with 176 additions and 20 deletions

View file

@ -10,3 +10,5 @@ edition = "2018"
x11 = {version = "2.18.2", features = ["xlib"] }
log = "0.4.13"
simple_logger = "1.11.0"
dirs = "3.0.2"
log4rs = "1.0.0"

View file

@ -146,12 +146,14 @@ mod tests {
window: 1,
size: (1, 1),
position: (1, 1),
transient_for: None,
});
clients.insert(Client {
window: 2,
size: (1, 1),
position: (1, 1),
transient_for: None,
});
clients.arrange_virtual_screen(600, 400, None);
@ -174,6 +176,7 @@ mod tests {
window: 3,
size: (1, 1),
position: (1, 1),
transient_for: None,
});
clients.arrange_virtual_screen(600, 400, None);
@ -326,6 +329,12 @@ impl ClientState {
where
K: ClientKey,
{
if let Some(focused_client) = self.focused {
if focused_client == key.key() {
self.focused = None;
}
}
self.remove_from_virtual_screens(key);
self.clients.remove(&key.key());
@ -354,6 +363,10 @@ impl ClientState {
.filter(move |&(k, _)| !self.is_client_visible(k))
}
pub fn iter_transient(&self) -> impl Iterator<Item = (&u64, &Client)> {
self.iter_floating().filter(|&(_, c)| c.is_transient())
}
pub fn iter_visible(&self) -> impl Iterator<Item = (&u64, &Client)> {
self.iter_all_clients()
.filter(move |&(k, _)| self.is_client_visible(k))
@ -527,11 +540,16 @@ impl ClientState {
{
if self.contains(key) {
match self.focused {
// focus the new client and return reference to it and the previously focused client.
Some(focused) => {
// If we are trying to focus the focused client, do nothing
if focused == key.key() {
(ClientEntry::Vacant, ClientEntry::Vacant)
} else {
// focus the new client and return reference to it and the previously focused client.
self.focused = Some(key.key());
(self.get(key), self.get(&focused))
}
}
/*
not currently focusing any client
focus the new client and return reference to it.

View file

@ -1,5 +1,10 @@
use log::info;
use std::io::Result;
use log::{debug, error, info, trace, warn};
use log4rs::{
append::{console::ConsoleAppender, file::FileAppender},
config::{Appender, Root},
encode::pattern::PatternEncoder,
Config,
};
mod clients;
mod state;
@ -20,7 +25,7 @@ unsafe extern "C" fn xlib_error_handler(
{
0
} else {
eprintln!(
error!(
"wm: fatal error:\nrequest_code: {}\nerror_code: {}",
err.request_code, err.error_code
);
@ -28,9 +33,59 @@ unsafe extern "C" fn xlib_error_handler(
}
}
fn main() -> Result<()> {
simple_logger::SimpleLogger::new().init().unwrap();
info!("Hello, World!");
fn init_logger() {
let encoder = Box::new(PatternEncoder::new(
"{d(%Y-%m-%d %H:%M:%S %Z)(utc)} │ {({M}::{f}:{L}):>25} │ {h({l:>5})} │ {m}{n}",
));
let stdout = ConsoleAppender::builder().encoder(encoder.clone()).build();
let home = dirs::home_dir().expect("Failed to get $HOME env var.");
let logfile = FileAppender::builder()
//.encoder(Box::new(PatternEncoder::default()))
.encoder(encoder)
.build(home.join(".local/portlights.log"))
.unwrap();
let config = Config::builder()
.appender(Appender::builder().build("stdout", Box::new(stdout)))
.appender(Appender::builder().build("logfile", Box::new(logfile)))
.build(
Root::builder()
.appender("stdout")
.appender("logfile")
.build(log::LevelFilter::Info),
)
.unwrap();
log4rs::init_config(config).unwrap();
}
fn main() {
init_logger();
log_prologue();
state::WindowManager::new().init().run();
}
fn log_prologue() {
info!("========================================================================");
info!("Portlights Window Manager");
info!("Version: {}", env!("CARGO_PKG_VERSION"));
info!("Warning levels:");
info!("Info!");
warn!("Warning!");
debug!("Debug!");
error!("Error!");
trace!("Trace!");
info!("========================================================================");
}
#[test]
fn test_logger() {
init_logger();
log_prologue();
}

View file

@ -70,6 +70,29 @@ impl WindowManager {
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("P", Mod1Mask),
|wm, _| {
wm.spawn(
"dmenu_run",
&[
"-m",
"0",
"-fn",
"'New York:size=13'",
"-nb",
"#222222",
"-nf",
"#bbbbbb",
"-sb",
"#dddddd",
"-sf",
"#eeeeee",
],
)
},
));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("M", Mod1Mask),
Self::handle_switch_stack,
@ -182,6 +205,8 @@ impl WindowManager {
}
fn handle_switch_stack(&mut self, event: &XKeyEvent) {
info!("Switching stack for window{:?}", event.subwindow);
self.clients.switch_stack_for_client(&event.subwindow);
self.arrange_clients();
@ -221,6 +246,7 @@ impl WindowManager {
}
xlib::MotionNotify => {
//let event = self.xlib.squash_event(xlib::MotionNotify);
let event: &XMotionEvent = event.as_ref();
if let Some(move_window) = &mut self.move_window {
@ -271,6 +297,7 @@ impl WindowManager {
};
self.xlib.move_cursor(client.window, position);
self.xlib.grab_cursor();
self.resize_window = Some(MoveWindow {
key: event.subwindow,
@ -285,13 +312,16 @@ impl WindowManager {
if event.button == 3 && self.resize_window.is_some() {
self.resize_window = None;
self.xlib.release_cursor();
}
}
xlib::MotionNotify => {
let event = self.xlib.squash_event(xlib::MotionNotify);
let event: &XMotionEvent = event.as_ref();
if let Some(resize_window) = &mut self.resize_window {
info!("MotionNotify-resize");
let (x, y) = (
event.x - resize_window.cached_cursor_position.0,
event.y - resize_window.cached_cursor_position.1,
@ -337,6 +367,16 @@ impl WindowManager {
.for_each(|(_, c)| self.xlib.hide_client(c));
}
fn raise_floating_clients(&self) {
self.clients
.iter_floating()
.for_each(|(_, c)| self.xlib.raise_client(c));
self.clients
.iter_transient()
.for_each(|(_, c)| self.xlib.raise_client(c));
}
fn arrange_clients(&mut self) {
let (width, height) = self.xlib.dimensions();
self.clients.arrange_virtual_screen(width, height, Some(2));
@ -347,9 +387,7 @@ impl WindowManager {
.iter_visible()
.for_each(|(_, c)| self.xlib.move_resize_client(c));
self.clients
.iter_floating()
.for_each(|(_, c)| self.xlib.raise_client(c));
self.raise_floating_clients();
}
fn focus_client<K>(&mut self, key: &K)
@ -364,10 +402,13 @@ impl WindowManager {
if let Some(new) = new.into_option() {
self.xlib.focus_client(new);
}
self.xlib.raise_client(new);
}
#[allow(dead_code)]
self.raise_floating_clients();
}
#[deprecated]
fn unfocus_client(&mut self) {
if let Some(client) = self.clients.unfocus().into_option() {
self.xlib.unfocus_client(client);
@ -375,6 +416,7 @@ impl WindowManager {
}
fn new_client(&mut self, window: Window) {
info!("new client: {:?}", window);
let client = if let Some(transient_window) = self.xlib.get_transient_for_window(window) {
Client::new_transient(
window,
@ -405,6 +447,7 @@ impl WindowManager {
fn unmap_notify(&mut self, event: &XEvent) {
let event: &XUnmapEvent = event.as_ref();
info!("unmap_notify: {:?}", event.window);
self.clients.remove(&event.window);
@ -413,6 +456,7 @@ impl WindowManager {
fn destroy_notify(&mut self, event: &XEvent) {
let event: &XDestroyWindowEvent = event.as_ref();
info!("destroy_notify: {:?}", event.window);
self.clients.remove(&event.window);

View file

@ -1,13 +1,15 @@
use log::info;
use std::ptr::{null, null_mut};
use std::{ffi::CString, rc::Rc};
use x11::xlib::{
self, Atom, ButtonPressMask, CWEventMask, ControlMask, EnterWindowMask, FocusChangeMask,
LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, PointerMotionMask,
PropertyChangeMask, ShiftMask, Status, StructureNotifyMask, SubstructureNotifyMask,
SubstructureRedirectMask, Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen,
XEvent, XGetTransientForHint, XInternAtom, XKillClient, XMapWindow, XOpenDisplay, XRaiseWindow,
XRootWindow, XSync, XWarpPointer,
self, Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask, CurrentTime,
EnterWindowMask, FocusChangeMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask,
PointerMotionMask, PropertyChangeMask, ShiftMask, Status, StructureNotifyMask,
SubstructureNotifyMask, SubstructureRedirectMask, Window, XCloseDisplay,
XConfigureRequestEvent, XDefaultScreen, XEvent, XGetTransientForHint, XGrabPointer,
XInternAtom, XKillClient, XMapWindow, XOpenDisplay, XRaiseWindow, XRootWindow, XSync,
XUngrabPointer, XWarpPointer,
};
use xlib::GrabModeAsync;
@ -118,6 +120,16 @@ impl XLib {
self.display.get()
}
pub fn squash_event(&self, event_type: i32) -> XEvent {
unsafe {
let mut event = std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init();
while xlib::XCheckTypedEvent(self.dpy(), event_type, &mut event) != 0 {}
event
}
}
pub fn next_event(&self) -> XEvent {
unsafe {
let mut event = std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init();
@ -188,9 +200,12 @@ impl XLib {
}
self.send_event(client, self.atoms.take_focus);
self.raise_client(client);
}
pub fn unfocus_client(&self, client: &Client) {
info!("unfocusing client: {:?}", client);
unsafe {
xlib::XSetInputFocus(
self.dpy(),
@ -423,6 +438,28 @@ impl XLib {
}
}
pub fn grab_cursor(&self) {
unsafe {
XGrabPointer(
self.dpy(),
self.root,
0,
(ButtonPressMask | ButtonReleaseMask | PointerMotionMask) as u32,
GrabModeAsync,
GrabModeAsync,
0,
0,
CurrentTime,
);
}
}
pub fn release_cursor(&self) {
unsafe {
XUngrabPointer(self.dpy(), CurrentTime);
}
}
pub fn move_cursor(&self, window: Window, position: (i32, i32)) {
unsafe {
XWarpPointer(self.dpy(), 0, window, 0, 0, 0, 0, position.0, position.1);