Skip to content

Commit

Permalink
Implement the pertag patch for dwm (#23)
Browse files Browse the repository at this point in the history
* add Pertag and allocate one when creating a Monitor

* update focusstack and setlayout

* update togglebar, setmfact, and toggleview

* update view

* actually capture the chained assignment semantics

* realize that I had two separate view functions, clippy for mem::swap

* fix off-by-one

this was clear in the patch, but I just didn't include the +1. symptom was a
crash when trying to access tag 9
  • Loading branch information
ntBre authored Aug 31, 2024
1 parent c0d03ca commit 0eb122f
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 22 deletions.
90 changes: 84 additions & 6 deletions src/key_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ use rwm::{Arg, Client, Layout, Monitor};

pub(crate) unsafe extern "C" fn togglebar(_arg: *const Arg) {
unsafe {
(*SELMON).showbar = ((*SELMON).showbar == 0) as c_int;
(*(*SELMON).pertag).showbars[(*(*SELMON).pertag).curtag as usize] =
((*SELMON).showbar == 0) as c_int;
(*SELMON).showbar =
(*(*SELMON).pertag).showbars[(*(*SELMON).pertag).curtag as usize];
updatebarpos(SELMON);
resizebarwin(SELMON);
if SHOWSYSTRAY != 0 {
Expand Down Expand Up @@ -92,7 +95,10 @@ pub(crate) unsafe extern "C" fn focusstack(arg: *const Arg) {
/// Increase the number of windows in the master area.
pub(crate) unsafe extern "C" fn incnmaster(arg: *const Arg) {
unsafe {
(*SELMON).nmaster = std::cmp::max((*SELMON).nmaster + (*arg).i, 0);
(*(*SELMON).pertag).nmasters[(*(*SELMON).pertag).curtag as usize] =
std::cmp::max((*SELMON).nmaster + (*arg).i, 0);
(*SELMON).nmaster =
(*(*SELMON).pertag).nmasters[(*(*SELMON).pertag).curtag as usize];
arrange(SELMON);
}
}
Expand All @@ -116,7 +122,9 @@ pub(crate) unsafe extern "C" fn setmfact(arg: *const Arg) {
if !(0.05..=0.95).contains(&f) {
return;
}
(*SELMON).mfact = f;
(*(*SELMON).pertag).mfacts[(*(*SELMON).pertag).curtag as usize] = f;
(*SELMON).mfact =
(*(*SELMON).pertag).mfacts[(*(*SELMON).pertag).curtag as usize];
arrange(SELMON);
}
}
Expand Down Expand Up @@ -144,14 +152,42 @@ pub(crate) unsafe extern "C" fn zoom(_arg: *const Arg) {

/// View the tag identified by `arg.ui`.
pub(crate) unsafe extern "C" fn view(arg: *const Arg) {
log::trace!("view");
unsafe {
if (*arg).ui & TAGMASK == (*SELMON).tagset[(*SELMON).seltags as usize] {
return;
}
(*SELMON).seltags ^= 1; // toggle sel tagset
if (*arg).ui & TAGMASK != 0 {

// Safety: we were gonna dereference it anyway
let pertag = &mut *(*SELMON).pertag;
if ((*arg).ui & TAGMASK) != 0 {
(*SELMON).tagset[(*SELMON).seltags as usize] = (*arg).ui & TAGMASK;
pertag.prevtag = pertag.curtag;

if (*arg).ui == !0 {
pertag.curtag = 0;
} else {
let mut i;
cfor!((i = 0; ((*arg).ui & 1 << i) == 0; i += 1) {});
pertag.curtag = i + 1;
}
} else {
std::mem::swap(&mut pertag.prevtag, &mut pertag.curtag);
}

(*SELMON).nmaster = pertag.nmasters[pertag.curtag as usize];
(*SELMON).mfact = pertag.mfacts[pertag.curtag as usize];
(*SELMON).sellt = pertag.sellts[pertag.curtag as usize];
(*SELMON).lt[(*SELMON).sellt as usize] =
pertag.ltidxs[pertag.curtag as usize][(*SELMON).sellt as usize];
(*SELMON).lt[((*SELMON).sellt ^ 1) as usize] = pertag.ltidxs
[pertag.curtag as usize][((*SELMON).sellt ^ 1) as usize];

if (*SELMON).showbar != pertag.showbars[pertag.curtag as usize] {
togglebar(null_mut());
}

focus(null_mut());
arrange(SELMON);
}
Expand Down Expand Up @@ -191,10 +227,17 @@ pub(crate) unsafe extern "C" fn setlayout(arg: *const Arg) {
|| (*arg).v.is_null()
|| (*arg).v.cast() != (*SELMON).lt[(*SELMON).sellt as usize]
{
(*SELMON).sellt ^= 1;
(*(*SELMON).pertag).sellts[(*(*SELMON).pertag).curtag as usize] ^=
1;
(*SELMON).sellt =
(*(*SELMON).pertag).sellts[(*(*SELMON).pertag).curtag as usize];
}
if !arg.is_null() && !(*arg).v.is_null() {
(*SELMON).lt[(*SELMON).sellt as usize] = (*arg).v as *mut Layout;
(*(*SELMON).pertag).ltidxs[(*(*SELMON).pertag).curtag as usize]
[(*SELMON).sellt as usize] = (*arg).v as *mut Layout;
(*SELMON).lt[(*SELMON).sellt as usize] = (*(*SELMON).pertag).ltidxs
[(*(*SELMON).pertag).curtag as usize]
[(*SELMON).sellt as usize];
}
libc::strncpy(
(*SELMON).ltsymbol.as_mut_ptr(),
Expand Down Expand Up @@ -307,6 +350,41 @@ pub(crate) unsafe extern "C" fn toggleview(arg: *const Arg) {

if newtagset != 0 {
(*SELMON).tagset[(*SELMON).seltags as usize] = newtagset;

if newtagset == !0 {
(*(*SELMON).pertag).prevtag = (*(*SELMON).pertag).curtag;
(*(*SELMON).pertag).curtag = 0;
}

// test if the user did not select the same tag
if (newtagset & 1 << ((*(*SELMON).pertag).curtag - 1)) == 0 {
(*(*SELMON).pertag).prevtag = (*(*SELMON).pertag).curtag;
let mut i;
cfor!((i = 0; (newtagset & 1 << i) == 0; i += 1) {});
(*(*SELMON).pertag).curtag = i + 1;
}

// apply settings for this view
(*SELMON).nmaster = (*(*SELMON).pertag).nmasters
[(*(*SELMON).pertag).curtag as usize];
(*SELMON).mfact =
(*(*SELMON).pertag).mfacts[(*(*SELMON).pertag).curtag as usize];
(*SELMON).sellt =
(*(*SELMON).pertag).sellts[(*(*SELMON).pertag).curtag as usize];
(*SELMON).lt[(*SELMON).sellt as usize] = (*(*SELMON).pertag).ltidxs
[(*(*SELMON).pertag).curtag as usize]
[(*SELMON).sellt as usize];
(*SELMON).lt[((*SELMON).sellt ^ 1) as usize] = (*(*SELMON).pertag)
.ltidxs[(*(*SELMON).pertag).curtag as usize]
[((*SELMON).sellt ^ 1) as usize];

if (*SELMON).showbar
!= (*(*SELMON).pertag).showbars
[(*(*SELMON).pertag).curtag as usize]
{
togglebar(null_mut());
}

focus(null_mut());
arrange(SELMON);
}
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,23 @@ pub struct Layout {
pub arrange: Option<unsafe extern "C" fn(arg1: *mut Monitor)>,
}

pub struct Pertag {
/// Current tag
pub curtag: c_uint,
/// Previous tag
pub prevtag: c_uint,
/// Number of windows in master area
pub nmasters: Vec<c_int>,
/// Proportion of monitor for master area
pub mfacts: Vec<f32>,
/// Selected layouts
pub sellts: Vec<c_uint>,
/// Matrix of tag and layout indices
pub ltidxs: Vec<[*const Layout; 2]>,
/// Whether to display the bar
pub showbars: Vec<c_int>,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Monitor {
Expand Down Expand Up @@ -137,6 +154,7 @@ pub struct Monitor {
pub next: *mut Monitor,
pub barwin: Window,
pub lt: [*const Layout; 2usize],
pub pertag: *mut Pertag,
}

#[repr(C)]
Expand Down
32 changes: 16 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::mem::{size_of, MaybeUninit};
use std::ptr::{addr_of, addr_of_mut, null_mut};
use std::sync::LazyLock;

use key_handlers::view;
use libc::{c_long, c_uchar, sigaction};
use rwm::enums::XEmbed;
use x11::keysym::XK_Num_Lock;
Expand All @@ -33,7 +34,7 @@ use x11::xlib::{
XA_WINDOW, XA_WM_NAME,
};

use rwm::{Arg, Client, Cursor, Layout, Monitor, Systray, Window};
use rwm::{Arg, Client, Cursor, Layout, Monitor, Pertag, Systray, Window};

use config::{
BUTTONS, COLORS, FONTS, KEYS, LAYOUTS, RESIZE_HINTS, RULES, SHOWSYSTRAY,
Expand Down Expand Up @@ -203,6 +204,20 @@ fn createmon() -> *mut Monitor {
LAYOUTS[0].symbol,
size_of_val(&(*m).ltsymbol),
);

// NOTE: using this instead of ecalloc because it feels weird to
// allocate a Vec that way, even though it worked in a separate test
// program. remember to free with Box::from_raw instead of libc::free
let pertag = Pertag {
curtag: 1,
prevtag: 1,
nmasters: vec![(*m).nmaster; TAGS.len() + 1],
mfacts: vec![(*m).mfact; TAGS.len() + 1],
sellts: vec![(*m).sellt; TAGS.len() + 1],
ltidxs: vec![(*m).lt; TAGS.len() + 1],
showbars: vec![(*m).showbar; TAGS.len() + 1],
};
(*m).pertag = Box::into_raw(Box::new(pertag));
}

m
Expand Down Expand Up @@ -984,21 +999,6 @@ fn nexttiled(mut c: *mut Client) -> *mut Client {
}
}

fn view(arg: *const Arg) {
log::trace!("view");
unsafe {
if (*arg).ui & TAGMASK == (*SELMON).tagset[(*SELMON).seltags as usize] {
return;
}
(*SELMON).seltags ^= 1; // toggle sel tagset
if ((*arg).ui & TAGMASK) != 0 {
(*SELMON).tagset[(*SELMON).seltags as usize] = (*arg).ui & TAGMASK;
}
focus(null_mut());
arrange(SELMON);
}
}

fn grabkeys() {
log::trace!("grabkeys");
unsafe {
Expand Down

0 comments on commit 0eb122f

Please sign in to comment.