diff --git a/src/drw.rs b/src/drw.rs index fafb2da..456b7c1 100644 --- a/src/drw.rs +++ b/src/drw.rs @@ -42,7 +42,7 @@ pub struct Fnt { } #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct Drw { pub w: c_uint, pub h: c_uint, @@ -119,45 +119,42 @@ pub(crate) fn create( root: Window, w: c_uint, h: c_uint, -) -> *mut Drw { +) -> Drw { unsafe { - let drw: *mut Drw = crate::util::ecalloc(1, size_of::()).cast(); - (*drw).dpy = dpy; - (*drw).screen = screen; - (*drw).root = root; - (*drw).w = w; - (*drw).h = h; - (*drw).drawable = xlib::XCreatePixmap( - dpy, - root, + let drw = Drw { + drawable: xlib::XCreatePixmap( + dpy, + root, + w, + h, + xlib::XDefaultDepth(dpy, screen) as u32, + ), w, h, - xlib::XDefaultDepth(dpy, screen) as u32, - ); - (*drw).gc = xlib::XCreateGC(dpy, root, 0, std::ptr::null_mut()); - xlib::XSetLineAttributes( dpy, - (*drw).gc, - 1, - LineSolid, - CapButt, - JoinMiter, - ); + screen, + root, + gc: xlib::XCreateGC(dpy, root, 0, null_mut()), + scheme: null_mut(), + fonts: null_mut(), + }; + xlib::XSetLineAttributes(dpy, drw.gc, 1, LineSolid, CapButt, JoinMiter); drw } } -pub(crate) fn free(drw: *mut Drw) { - unsafe { - xlib::XFreePixmap((*drw).dpy, (*drw).drawable); - xlib::XFreeGC((*drw).dpy, (*drw).gc); - fontset_free((*drw).fonts); - libc::free(drw.cast()); +impl Drop for Drw { + fn drop(&mut self) { + unsafe { + xlib::XFreePixmap(self.dpy, self.drawable); + xlib::XFreeGC(self.dpy, self.gc); + fontset_free(self.fonts); + } } } pub(crate) fn rect( - drw: *mut Drw, + drw: Option<&mut Drw>, x: c_int, y: c_int, w: c_uint, @@ -166,33 +163,28 @@ pub(crate) fn rect( invert: c_int, ) { unsafe { - if drw.is_null() || (*drw).scheme.is_null() { + let Some(drw) = drw else { + return; + }; + if drw.scheme.is_null() { return; } xlib::XSetForeground( - (*drw).dpy, - (*drw).gc, + drw.dpy, + drw.gc, if invert != 0 { - (*(*drw).scheme.offset(Col::Bg as isize)).pixel + (*drw.scheme.offset(Col::Bg as isize)).pixel } else { - (*(*drw).scheme.offset(Col::Fg as isize)).pixel + (*drw.scheme.offset(Col::Fg as isize)).pixel }, ); if filled != 0 { - xlib::XFillRectangle( - (*drw).dpy, - (*drw).drawable, - (*drw).gc, - x, - y, - w, - h, - ); + xlib::XFillRectangle(drw.dpy, drw.drawable, drw.gc, x, y, w, h); } else { xlib::XDrawRectangle( - (*drw).dpy, - (*drw).drawable, - (*drw).gc, + drw.dpy, + drw.drawable, + drw.gc, x, y, w - 1, @@ -202,58 +194,58 @@ pub(crate) fn rect( } } -pub(crate) fn cur_create(drw: *mut Drw, shape: c_int) -> *mut Cur { - if drw.is_null() { +pub(crate) fn cur_create(drw: Option<&mut Drw>, shape: c_int) -> *mut Cur { + let Some(drw) = drw else { return std::ptr::null_mut(); - } + }; + unsafe { let cur: *mut Cur = crate::util::ecalloc(1, size_of::()).cast(); if cur.is_null() { return std::ptr::null_mut(); } - (*cur).cursor = xlib::XCreateFontCursor((*drw).dpy, shape as c_uint); + (*cur).cursor = xlib::XCreateFontCursor(drw.dpy, shape as c_uint); cur } } -pub(crate) fn cur_free(drw: *mut Drw, cursor: *mut Cur) { +pub(crate) fn cur_free(drw: &mut Drw, cursor: *mut Cur) { if cursor.is_null() { return; } unsafe { - xlib::XFreeCursor((*drw).dpy, (*cursor).cursor); + xlib::XFreeCursor(drw.dpy, (*cursor).cursor); libc::free(cursor.cast()); } } -pub(crate) fn setscheme(drw: *mut Drw, scm: *mut Clr) { - if !drw.is_null() { - unsafe { - (*drw).scheme = scm; - } +pub(crate) fn setscheme(drw: Option<&mut Drw>, scm: *mut Clr) { + if let Some(drw) = drw { + drw.scheme = scm; } } -pub(crate) fn fontset_create(drw: *mut Drw, fonts: &[CString]) -> *mut Fnt { - log::trace!("fontset_create"); - unsafe { - let mut ret: *mut Fnt = null_mut(); +impl Drw { + pub(crate) fn fontset_create(&mut self, fonts: &[CString]) -> *mut Fnt { + log::trace!("fontset_create"); + unsafe { + let mut ret: *mut Fnt = null_mut(); - // since fonts is a & not a *, it can't be null, but it could be empty - if drw.is_null() || fonts.is_empty() { - return null_mut(); - } + if fonts.is_empty() { + return null_mut(); + } - for font in fonts.iter().rev() { - let cur = xfont_create(drw, font.as_ptr(), null_mut()); - if !cur.is_null() { - (*cur).next = ret; - ret = cur; + for font in fonts.iter().rev() { + let cur = xfont_create(self, font.as_ptr(), null_mut()); + if !cur.is_null() { + (*cur).next = ret; + ret = cur; + } } + self.fonts = ret; + ret } - (*drw).fonts = ret; - ret } } @@ -366,13 +358,14 @@ fn clr_create(drw: *mut Drw, dest: *mut Clr, clrname: *const c_char) { } pub(crate) fn scm_create( - drw: *mut Drw, + drw: Option<&mut Drw>, clrnames: &[CString], clrcount: usize, ) -> *mut Clr { - if drw.is_null() || clrnames.is_empty() || clrcount < 2 { + if drw.is_none() || clrnames.is_empty() || clrcount < 2 { return null_mut(); } + let drw = drw.unwrap(); let ret: *mut Clr = ecalloc(clrcount, size_of::()).cast(); if ret.is_null() { return null_mut(); @@ -385,18 +378,22 @@ pub(crate) fn scm_create( ret } -pub(crate) fn fontset_getwidth(drw: *mut Drw, text: *const c_char) -> c_uint { - unsafe { - if drw.is_null() || (*drw).fonts.is_null() || text.is_null() { - return 0; - } +pub(crate) fn fontset_getwidth( + drw: Option<&mut Drw>, + text: *const c_char, +) -> c_uint { + let Some(drw) = drw else { + return 0; + }; + if drw.fonts.is_null() || text.is_null() { + return 0; } - self::text(drw, 0, 0, 0, 0, 0, text, 0) as c_uint + self::text(Some(drw), 0, 0, 0, 0, 0, text, 0) as c_uint } #[allow(clippy::too_many_arguments)] pub(crate) fn text( - drw: *mut Drw, + drw: Option<&mut Drw>, mut x: c_int, y: c_int, mut w: c_uint, @@ -454,10 +451,13 @@ pub(crate) fn text( NoMatches { codepoint: [0; NOMATCHES_LEN], idx: 0 }; static mut ELLIPSIS_WIDTH: c_uint = 0; - if drw.is_null() - || (render != 0 && ((*drw).scheme.is_null() || w == 0)) + let Some(drw) = drw else { + return 0; + }; + + if (render != 0 && (drw.scheme.is_null() || w == 0)) || text.is_null() - || (*drw).fonts.is_null() + || drw.fonts.is_null() { return 0; } @@ -490,7 +490,7 @@ pub(crate) fn text( usedfont = drw.fonts; if ELLIPSIS_WIDTH == 0 && render != 0 { - ELLIPSIS_WIDTH = fontset_getwidth(drw, c"...".as_ptr()); + ELLIPSIS_WIDTH = fontset_getwidth(Some(drw), c"...".as_ptr()); } log::trace!("text: entering loop"); 'no_match: loop { @@ -592,7 +592,7 @@ pub(crate) fn text( } if render != 0 && overflow != 0 { self::text( - drw, + Some(drw), ellipsis_x, y, ellipsis_w, @@ -734,49 +734,38 @@ fn font_getexts( } pub(crate) fn map( - drw: *mut Drw, + drw: Option<&mut Drw>, win: Window, x: c_int, y: c_int, w: c_uint, h: c_uint, ) { - if drw.is_null() { + let Some(drw) = drw else { return; - } + }; unsafe { - xlib::XCopyArea( - (*drw).dpy, - (*drw).drawable, - win, - (*drw).gc, - x, - y, - w, - h, - x, - y, - ); - xlib::XSync((*drw).dpy, False); + xlib::XCopyArea(drw.dpy, drw.drawable, win, drw.gc, x, y, w, h, x, y); + xlib::XSync(drw.dpy, False); } } -pub(crate) fn resize(drw: *mut Drw, w: c_uint, h: c_uint) { +pub(crate) fn resize(drw: Option<&mut Drw>, w: c_uint, h: c_uint) { unsafe { - if drw.is_null() { + let Some(drw) = drw else { return; + }; + drw.w = w; + drw.h = h; + if drw.drawable != 0 { + xlib::XFreePixmap(drw.dpy, drw.drawable); } - (*drw).w = w; - (*drw).h = h; - if (*drw).drawable != 0 { - xlib::XFreePixmap((*drw).dpy, (*drw).drawable); - } - (*drw).drawable = xlib::XCreatePixmap( - (*drw).dpy, - (*drw).root, + drw.drawable = xlib::XCreatePixmap( + drw.dpy, + drw.root, w, h, - xlib::XDefaultDepth((*drw).dpy, (*drw).screen) as c_uint, + xlib::XDefaultDepth(drw.dpy, drw.screen) as c_uint, ); } } diff --git a/src/handlers.rs b/src/handlers.rs index 778035e..0ed48e9 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -360,7 +360,7 @@ pub(crate) fn configurenotify(e: *mut XEvent) { SW = ev.width; SH = ev.height; if updategeom() != 0 || dirty { - drw::resize(DRW, SW as c_uint, BH as c_uint); + drw::resize(DRW.as_mut(), SW as c_uint, BH as c_uint); updatebars(); let mut m = MONS; while !m.is_null() { diff --git a/src/main.rs b/src/main.rs index 987d4a1..29839a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,7 +137,7 @@ static mut XATOM: [Atom; XEmbed::Last as usize] = [0; XEmbed::Last as usize]; static mut DPY: *mut Display = null_mut(); -static mut DRW: *mut Drw = std::ptr::null_mut(); +static mut DRW: Option = None; static mut SELMON: *mut Monitor = std::ptr::null_mut(); static mut MONS: *mut Monitor = null_mut(); @@ -276,12 +276,17 @@ fn setup() { SW = xlib::XDisplayWidth(DPY, SCREEN); SH = xlib::XDisplayHeight(DPY, SCREEN); ROOT = xlib::XRootWindow(DPY, SCREEN); - DRW = drw::create(DPY, SCREEN, ROOT, SW as u32, SH as u32); - if drw::fontset_create(DRW, &CONFIG.fonts).is_null() { + DRW = Some(drw::create(DPY, SCREEN, ROOT, SW as u32, SH as u32)); + if DRW + .as_mut() + .unwrap() + .fontset_create(&CONFIG.fonts) + .is_null() + { panic!("no fonts could be loaded"); } - LRPAD = (*(*DRW).fonts).h as i32; - BH = (*(*DRW).fonts).h as i32 + 2; + LRPAD = (*DRW.as_mut().unwrap().fonts).h as i32; + BH = (*DRW.as_mut().unwrap().fonts).h as i32 + 2; updategeom(); /* init atoms */ @@ -335,15 +340,19 @@ fn setup() { XInternAtom(DPY, c"_XEMBED_INFO".as_ptr(), False); /* init cursors */ - CURSOR[Cur::Normal as usize] = drw::cur_create(DRW, XC_LEFT_PTR as i32); - CURSOR[Cur::Resize as usize] = drw::cur_create(DRW, XC_SIZING as i32); - CURSOR[Cur::Move as usize] = drw::cur_create(DRW, XC_FLEUR as i32); + CURSOR[Cur::Normal as usize] = + drw::cur_create(DRW.as_mut(), XC_LEFT_PTR as i32); + CURSOR[Cur::Resize as usize] = + drw::cur_create(DRW.as_mut(), XC_SIZING as i32); + CURSOR[Cur::Move as usize] = + drw::cur_create(DRW.as_mut(), XC_FLEUR as i32); /* init appearance */ SCHEME = util::ecalloc(CONFIG.colors.len(), size_of::<*mut Clr>()).cast(); for i in 0..CONFIG.colors.len() { - *SCHEME.add(i) = drw::scm_create(DRW, &CONFIG.colors[i], 3); + *SCHEME.add(i) = + drw::scm_create(DRW.as_mut(), &CONFIG.colors[i], 3); } // init system tray @@ -1340,11 +1349,19 @@ fn updatesystray() { // redraw background XSetForeground( DPY, - (*DRW).gc, + DRW.as_mut().unwrap().gc, get_scheme_color(SCHEME, Scheme::Norm as usize, Col::Bg as usize) .pixel, ); - XFillRectangle(DPY, (*SYSTRAY).win, (*DRW).gc, 0, 0, w, BH as u32); + XFillRectangle( + DPY, + (*SYSTRAY).win, + DRW.as_mut().unwrap().gc, + 0, + 0, + w, + BH as u32, + ); XSync(DPY, False); } // end unsafe } @@ -1393,7 +1410,7 @@ fn systraytomon(m: *mut Monitor) -> *mut Monitor { fn textw(x: *const c_char) -> c_int { log::trace!("textw"); - unsafe { drw::fontset_getwidth(DRW, x) as c_int + LRPAD } + unsafe { drw::fontset_getwidth(DRW.as_mut(), x) as c_int + LRPAD } } fn drawbar(m: *mut Monitor) { @@ -1401,8 +1418,8 @@ fn drawbar(m: *mut Monitor) { unsafe { let mut tw = 0; let mut stw = 0; - let boxs = (*(*DRW).fonts).h / 9; - let boxw = (*(*DRW).fonts).h / 6 + 2; + let boxs = (*DRW.as_ref().unwrap().fonts).h / 9; + let boxw = (*DRW.as_ref().unwrap().fonts).h / 6 + 2; let (mut occ, mut urg) = (0, 0); if CONFIG.showsystray && m == systraytomon(m) && !CONFIG.systrayonleft { @@ -1416,10 +1433,10 @@ fn drawbar(m: *mut Monitor) { // draw status first so it can be overdrawn by tags later if m == SELMON { // status is only drawn on selected monitor - drw::setscheme(DRW, *SCHEME.add(Scheme::Norm as usize)); + drw::setscheme(DRW.as_mut(), *SCHEME.add(Scheme::Norm as usize)); tw = textw(addr_of!(STEXT) as *const _) - LRPAD / 2 + 2; // 2px right padding drw::text( - DRW, + DRW.as_mut(), (*m).ww - tw - stw as i32, 0, tw as u32, @@ -1446,7 +1463,7 @@ fn drawbar(m: *mut Monitor) { let text = tag.to_owned(); let w = textw(text.as_ptr()); drw::setscheme( - DRW, + DRW.as_mut(), *SCHEME.add( if ((*m).tagset[(*m).seltags as usize] & 1 << i) != 0 { Scheme::Sel as usize @@ -1456,7 +1473,7 @@ fn drawbar(m: *mut Monitor) { ), ); drw::text( - DRW, + DRW.as_mut(), x, 0, w as u32, @@ -1468,7 +1485,7 @@ fn drawbar(m: *mut Monitor) { if (occ & 1 << i) != 0 { drw::rect( - DRW, + DRW.as_mut(), x + boxs as i32, boxs as i32, boxw, @@ -1484,9 +1501,9 @@ fn drawbar(m: *mut Monitor) { } let w = textw((*m).ltsymbol.as_ptr()); - drw::setscheme(DRW, *SCHEME.add(Scheme::Norm as usize)); + drw::setscheme(DRW.as_mut(), *SCHEME.add(Scheme::Norm as usize)); x = drw::text( - DRW, + DRW.as_mut(), x, 0, w as u32, @@ -1500,7 +1517,7 @@ fn drawbar(m: *mut Monitor) { if w > BH { if !(*m).sel.is_null() { drw::setscheme( - DRW, + DRW.as_mut(), *SCHEME.offset(if m == SELMON { Scheme::Sel as isize } else { @@ -1508,7 +1525,7 @@ fn drawbar(m: *mut Monitor) { }), ); drw::text( - DRW, + DRW.as_mut(), x, 0, w as u32, @@ -1519,7 +1536,7 @@ fn drawbar(m: *mut Monitor) { ); if (*(*m).sel).isfloating { drw::rect( - DRW, + DRW.as_mut(), x + boxs as i32, boxs as i32, boxw, @@ -1529,11 +1546,21 @@ fn drawbar(m: *mut Monitor) { ); } } else { - drw::setscheme(DRW, *SCHEME.add(Scheme::Norm as usize)); - drw::rect(DRW, x, 0, w as u32, BH as u32, 1, 1); + drw::setscheme( + DRW.as_mut(), + *SCHEME.add(Scheme::Norm as usize), + ); + drw::rect(DRW.as_mut(), x, 0, w as u32, BH as u32, 1, 1); } } - drw::map(DRW, (*m).barwin, 0, 0, (*m).ww as u32 - stw, BH as u32); + drw::map( + DRW.as_mut(), + (*m).barwin, + 0, + 0, + (*m).ww as u32 - stw, + BH as u32, + ); } } @@ -2035,7 +2062,7 @@ fn cleanup() { } for cur in CURSOR { - drw::cur_free(DRW, cur); + drw::cur_free(DRW.as_mut().unwrap(), cur); } // free each element in scheme (*mut *mut Clr), then free scheme itself @@ -2046,7 +2073,6 @@ fn cleanup() { libc::free(SCHEME.cast()); xlib::XDestroyWindow(DPY, WMCHECKWIN); - drw::free(DRW); xlib::XSync(DPY, False); xlib::XSetInputFocus( DPY,