diff --git a/src/config.rs b/src/config.rs index 44c6acd..d0ba538 100644 --- a/src/config.rs +++ b/src/config.rs @@ -137,13 +137,23 @@ pub static DMENUCMD: DmenuCmd = DmenuCmd([ ]); pub const TERMCMD: [*const c_char; 2] = [c"st".as_ptr(), null_mut()]; +pub const SCRATCHPADNAME: *const c_char = c"scratchpad".as_ptr(); +pub const SCRATCHPADCMD: [*const c_char; 6] = [ + c"st".as_ptr(), + c"-t".as_ptr(), + SCRATCHPADNAME, + c"-g".as_ptr(), + c"120x34".as_ptr(), + null_mut(), +]; + use x11::keysym::{ - XK_Return, XK_Tab, XK_b, XK_c, XK_comma, XK_d, XK_f, XK_h, XK_i, XK_j, - XK_k, XK_l, XK_m, XK_p, XK_period, XK_q, XK_space, XK_t, XK_0, XK_1, XK_2, - XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9, + XK_Return, XK_Tab, XK_b, XK_c, XK_comma, XK_d, XK_f, XK_grave, XK_h, XK_i, + XK_j, XK_k, XK_l, XK_m, XK_p, XK_period, XK_q, XK_space, XK_t, XK_0, XK_1, + XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, XK_8, XK_9, }; -pub static KEYS: [Key; 60] = [ +pub static KEYS: [Key; 61] = [ Key::new(MODKEY, XK_p, spawn, Arg { v: DMENUCMD.0.as_ptr().cast() }), Key::new( MODKEY | ShiftMask, @@ -151,6 +161,12 @@ pub static KEYS: [Key; 60] = [ spawn, Arg { v: TERMCMD.as_ptr().cast() }, ), + Key::new( + MODKEY, + XK_grave, + togglescratch, + Arg { v: SCRATCHPADCMD.as_ptr().cast() }, + ), Key::new(MODKEY, XK_b, togglebar, Arg { i: 0 }), Key::new(MODKEY, XK_j, focusstack, Arg { i: 1 }), Key::new(MODKEY, XK_k, focusstack, Arg { i: -1 }), diff --git a/src/key_handlers.rs b/src/key_handlers.rs index aec0063..219c8e5 100644 --- a/src/key_handlers.rs +++ b/src/key_handlers.rs @@ -19,8 +19,8 @@ use crate::{ arrange, attach, attachstack, detach, detachstack, drawbar, focus, getrootptr, height, is_visible, nexttiled, pop, recttomon, resize, resizebarwin, restack, sendevent, unfocus, updatebarpos, width, xerror, - xerrordummy, BH, CURSOR, DPY, HANDLER, MONS, MOUSEMASK, ROOT, SELMON, - SYSTRAY, TAGMASK, WMATOM, XNONE, + xerrordummy, BH, CURSOR, DPY, HANDLER, MONS, MOUSEMASK, ROOT, SCRATCHTAG, + SELMON, SYSTRAY, TAGMASK, WMATOM, XNONE, }; use rwm::{Arg, Client, Layout, Monitor}; @@ -623,6 +623,7 @@ pub(crate) unsafe extern "C" fn spawn(arg: *const Arg) { log::trace!("spawn: dmenucmd on monitor {}", (*SELMON).num); DMENUMON[0] = '0' as c_char + (*SELMON).num as c_char; } + (*SELMON).tagset[(*SELMON).seltags as usize] &= !SCRATCHTAG; if libc::fork() == 0 { if !DPY.is_null() { libc::close(XConnectionNumber(DPY)); @@ -668,3 +669,34 @@ pub(crate) unsafe extern "C" fn toggletag(arg: *const Arg) { } } } + +pub(crate) unsafe extern "C" fn togglescratch(arg: *const Arg) { + unsafe { + let mut c: *mut Client; + let mut found = false; + cfor!(( + c = (*SELMON).clients; + !c.is_null(); + c = (*c).next) { + found = ((*c).tags & SCRATCHTAG) != 0; + if found { + break; + } + }); + if found { + let newtagset = + (*SELMON).tagset[(*SELMON).seltags as usize] ^ SCRATCHTAG; + if newtagset != 0 { + (*SELMON).tagset[(*SELMON).seltags as usize] = newtagset; + focus(null_mut()); + arrange(SELMON); + } + if is_visible(c) { + focus(c); + restack(SELMON); + } + } else { + spawn(arg); + } + } +} diff --git a/src/main.rs b/src/main.rs index 648d85b..25a82e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2421,6 +2421,22 @@ fn manage(w: Window, wa: *mut xlib::XWindowAttributes) { (*c).y = max((*c).y, (*(*c).mon).wy as i32); (*c).bw = config::BORDERPX as i32; + // TODO pretty sure this doesn't work with pertags, which explains some + // behavior I saw before in dwm. probably need to operate on + // selmon.pertag.tags[selmon.pertag.curtag]. + // + // TODO I'm also pretty sure this is _not_ the right way to be handling + // this. checking the name of the window and applying these rules seems + // like something meant to be handled by RULES + (*SELMON).tagset[(*SELMON).seltags as usize] &= !SCRATCHTAG; + if libc::strcmp((*c).name.as_ptr(), config::SCRATCHPADNAME) == 0 { + (*c).tags = SCRATCHTAG; + (*(*c).mon).tagset[(*(*c).mon).seltags as usize] |= (*c).tags; + (*c).isfloating = true; + (*c).x = (*(*c).mon).wx + (*(*c).mon).ww / 2 - width(c) / 2; + (*c).y = (*(*c).mon).wy + (*(*c).mon).wh / 2 - height(c) / 2; + } + log::trace!("manage: XWindowChanges"); let mut wc = xlib::XWindowChanges { x: 0, @@ -2758,6 +2774,8 @@ const TAGMASK: u32 = (1 << TAGS.len()) - 1; const BUTTONMASK: i64 = ButtonPressMask | ButtonReleaseMask; const MOUSEMASK: i64 = BUTTONMASK | PointerMotionMask; +static SCRATCHTAG: u32 = 1 << TAGS.len(); + fn updatetitle(c: *mut Client) { log::trace!("updatetitle"); unsafe {