From 5d7d8a19f6364dfb6e6583125ced3103d069f2b3 Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Wed, 27 Jan 2016 12:27:34 -0300 Subject: Refactor move sticky. --- src/command.rs | 41 ++++++--------------- src/desktop.rs | 2 +- src/event.rs | 4 +++ src/main.rs | 3 ++ src/safe_x11/mod.rs | 7 ++++ src/safe_x11/window.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 112 insertions(+), 42 deletions(-) diff --git a/src/command.rs b/src/command.rs index 21760a8..74a7255 100644 --- a/src/command.rs +++ b/src/command.rs @@ -106,46 +106,25 @@ pub fn move_win_to(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool { pub fn move_win_sticky(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool { if let Some(ref win) = wm.current_window() { - let attrs = win.attributes(); + let mut xgeometries = wm.x_geometries(); + let mut ygeometries = wm.y_geometries(); match &*args[0] { "left" => { - let mut xgeo = wm.x_geometries(); - xgeo.sort_by(|a,b| b.cmp(a)); - - let val = xgeo.iter().skip_while(|&a| *a >= attrs.x).next(); - if let Some(v) = val { - let _ = win.move_to(*v, attrs.y); - } + xgeometries.sort_by(|a,b| b.cmp(a)); + win.move_sticky_left(&xgeometries); }, "right" => { - let mut xgeo = wm.x_geometries(); - let win_right = attrs.x + attrs.width; - xgeo.sort_by(|a,b| a.cmp(b)); - - let val = xgeo.iter().skip_while(|&a| *a <= win_right).next(); - if let Some(v) = val { - let _ = win.move_to(*v - attrs.width, attrs.y); - } + xgeometries.sort_by(|a,b| a.cmp(b)); + win.move_sticky_right(&xgeometries); }, "up" => { - let mut ygeo = wm.y_geometries(); - ygeo.sort_by(|a,b| b.cmp(a)); - - let val = ygeo.iter().skip_while(|&a| *a >= attrs.y).next(); - if let Some(v) = val { - let _ = win.move_to(attrs.x, *v); - } + ygeometries.sort_by(|a,b| b.cmp(a)); + win.move_sticky_up(&ygeometries); }, "down" => { - let mut ygeo = wm.y_geometries(); - let win_bot = attrs.y + attrs.height; - ygeo.sort_by(|a,b| a.cmp(b)); - - let val = ygeo.iter().skip_while(|&a| *a <= win_bot).next(); - if let Some(v) = val { - let _ = win.move_to(attrs.x, *v - attrs.height); - } + ygeometries.sort_by(|a,b| a.cmp(b)); + win.move_sticky_down(&ygeometries); }, _ => (), } diff --git a/src/desktop.rs b/src/desktop.rs index 8bd4a4c..afe6a28 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -58,7 +58,7 @@ impl Desktop { } self.unfocus_current_window(); if let Some(w) = XWindow::new(self.display, w) { - w.select_input(xlib::EnterWindowMask); + w.select_input(xlib::EnterWindowMask | xlib::ExposureMask); self.window_list.push(w); // Last windows get focus. self.focus_current_window(); diff --git a/src/event.rs b/src/event.rs index 3832a36..b97686f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -11,6 +11,7 @@ use x11::xlib::{ XUnmapEvent, XMapEvent, XConfigureEvent, + XExposeEvent, XPending, }; @@ -48,6 +49,7 @@ pub enum Event { Unmap(XUnmapEvent), Map(XMapEvent), Configure(XConfigureEvent), + Expose(XExposeEvent), Socket(UnixStream), NoEvent } @@ -66,6 +68,7 @@ impl fmt::Debug for Event { &Event::Unmap(ev) => format!("Unmap({})", XEvent::from(ev).get_type()), &Event::Map(ev) => format!("Map({})", XEvent::from(ev).get_type()), &Event::Configure(ev) => format!("Configure({})", XEvent::from(ev).get_type()), + &Event::Expose(ev) => format!("Expose({})", XEvent::from(ev).get_type()), &Event::Socket(_) => format!("Socket()"), &Event::NoEvent => format!("NoEvent"), }; @@ -116,6 +119,7 @@ pub fn next_event(display: *mut Display) -> Event { 6 => Event::Drag(XMotionEvent::from(ev)), 7 => Event::Enter(XCrossingEvent::from(ev)), 8 => Event::Leave(XCrossingEvent::from(ev)), + 12 => Event::Expose(XExposeEvent::from(ev)), 16 => Event::Create(XCreateWindowEvent::from(ev)), 17 => Event::Destroy(XDestroyWindowEvent::from(ev)), 18 => Event::Unmap(XUnmapEvent::from(ev)), diff --git a/src/main.rs b/src/main.rs index 2a00ff5..90126a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,7 @@ fn main() { // Main loop while !dotwm.finish { let event = unsafe { select_event(dotwm.display, x11_fd, &listener) }; + println!("Event: {:?}", event); match event { Event::Key(mut e, true) => { let keysym = unsafe { xlib::XLookupKeysym(&mut e, 0) as u32 }; @@ -68,6 +69,8 @@ fn main() { dotwm.change_focus_of(idx); } }, + Event::Expose(_) => { + }, Event::Socket(stream) => { let mut s = stream.try_clone().unwrap(); let mut buf = String::new(); diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs index 9e5859a..03c54d8 100644 --- a/src/safe_x11/mod.rs +++ b/src/safe_x11/mod.rs @@ -16,9 +16,11 @@ use x11::xlib::{ XEvent, XNextEvent, + XDefaultGC, // Windows Window, + GC, Atom, XInternAtom, }; @@ -226,6 +228,11 @@ fn get_color>>(display: *mut Display, color: T) -> u64{ } } +fn default_gc(display: *mut Display) -> GC { + let screen_num = unsafe { xlib::XDefaultScreen(display) }; + unsafe { XDefaultGC(display, screen_num) } +} + /// Get the keysym for the given event. pub fn lookup_keysym(ev: &mut XKeyEvent) -> xlib::KeySym { unsafe { xlib::XLookupKeysym(ev, 0) } diff --git a/src/safe_x11/window.rs b/src/safe_x11/window.rs index 78b73f7..c889dfc 100644 --- a/src/safe_x11/window.rs +++ b/src/safe_x11/window.rs @@ -23,19 +23,22 @@ use x11::xlib::{ XChangeWindowAttributes, XSetWindowAttributes, XMapWindow, XUnmapWindow, + + XBlackPixel,XWhitePixel, XDrawString, }; use std::ptr; use std::mem::uninitialized; use std::mem::transmute; use std::cmp::{max}; +use std::ffi::CString; use safe_x11::{screen_ratio,get_color}; /// Representation of [`xlib::Window`](../../x11/xlib/type.Window.html) pub struct XWindow { display: *mut xlib::Display, - /// xlib::Window that wraps this struct. + // The Application window. pub inner: Window, fullscreen: bool, prev_attribs: XWindowAttributes, @@ -47,12 +50,21 @@ fn fixed_with_ratio(x: i32, ratio: f32) -> i32 { fixed as i32 } +fn window_attribs(display: *mut xlib::Display, w: Window) -> XWindowAttributes { + unsafe { + let mut attrptr: XWindowAttributes = uninitialized(); + XGetWindowAttributes(display, w, &mut attrptr); + attrptr + } +} + impl XWindow { /// Generate a reference to the window in certain display. This will return /// `None` if the window is the root window. pub fn new(d: *mut xlib::Display, w: Window) -> Option { if w != 0 { let attrs: XWindowAttributes = unsafe { uninitialized() }; + println!("Window created!"); Some(XWindow { display: d, inner: w, @@ -73,6 +85,7 @@ impl XWindow { /// the user selected "delete window" from a hypothetical menu and /// also perform any confirmation dialog with the user. pub fn delete(&self) { + // First delete the border window and then the main window. let mut ev: XClientMessageEvent = unsafe { uninitialized() }; ev.type_ = ClientMessage; ev.window = self.inner; @@ -95,7 +108,9 @@ impl XWindow { /// Raises a window. pub fn raise(&self) { - unsafe { xlib::XRaiseWindow(self.display, self.inner); } + unsafe { + xlib::XRaiseWindow(self.display, self.inner); + } } /// Register input events on some [`xlib::Window`](../../x11/xlib/type.Window.html) @@ -120,11 +135,7 @@ impl XWindow { /// Returns the window attributes from certain window. pub fn attributes(&self) -> XWindowAttributes { - unsafe { - let mut attrptr: XWindowAttributes = uninitialized(); - XGetWindowAttributes(self.display, self.inner, &mut attrptr); - attrptr - } + window_attribs(self.display, self.inner) } /// Moves the window given an offset from where it is. @@ -148,15 +159,64 @@ impl XWindow { if 0 > x && x <= screen.width || 0 > y && y <= screen.height { Err("Cannot move the window outside the screen!") } else { - unsafe { XMoveWindow(self.display, self.inner, x, y) }; + unsafe { + XMoveWindow(self.display, self.inner, x, y); + }; Ok(()) } } + // Some functions for moving within some boundaries. + + /// Move sticky to the left. + pub fn move_sticky_left(&self, boundaries: &[i32]) { + let attrs = self.attributes(); + if let Some(v) = boundaries.iter() + .skip_while(|&a| *a >= attrs.x) + .next() { + let _ = self.move_to(*v, attrs.y); + } + } + + /// Move sticky to the right. + pub fn move_sticky_right(&self, boundaries: &[i32]) { + let attrs = self.attributes(); + let win_bound = attrs.x + attrs.width; + + if let Some(v) = boundaries.iter() + .skip_while(|&a| *a <= win_bound) + .next() { + let _ = self.move_to(*v - attrs.width, attrs.y); + } + } + + /// Move up sticky. + pub fn move_sticky_up(&self, boundaries: &[i32]) { + let attrs = self.attributes(); + + if let Some(v) = boundaries.iter() + .skip_while(|&a| *a >= attrs.y) + .next() { + let _ = self.move_to(attrs.x, *v); + } + } + + /// Move down sticky. + pub fn move_sticky_down(&self, boundaries: &[i32]) { + let attrs = self.attributes(); + let win_bound = attrs.y + attrs.height; + + if let Some(v) = boundaries.iter() + .skip_while(|&a| *a <= win_bound) + .next() { + let _ = self.move_to(attrs.x, *v - attrs.height); + } + } + /// Move and resize the window in one step pub fn move_resize(&self, x:i32, y: i32, w: u32, h: u32) { unsafe { - XMoveResizeWindow(self.display, self.inner, x, y, w, h); + XMoveResizeWindow(self.display, self.inner, x, y, w, h as u32); } } @@ -168,7 +228,7 @@ impl XWindow { let ww: u32 = max(1, (attrs.width + fixed_with_ratio(w, ratio)) as u32); let wh: u32 = max(1, (attrs.height + fixed_with_ratio(h, ratio)) as u32); xlib::XResizeWindow(self.display, self.inner, - ww, wh); + ww, wh as u32); } } @@ -245,6 +305,23 @@ impl XWindow { } } + pub fn draw_string>>(&self, s: T) { + // Title :D + println!("Drawing string for {}", self.inner); + let cstr = CString::new(s).unwrap(); + unsafe { + let gc = xlib::XCreateGC(self.display, self.inner, 0, ptr::null_mut()); + xlib::XSetForeground(self.display, gc, XWhitePixel(self.display, 0)); + xlib::XSetBackground(self.display, gc, XBlackPixel(self.display, 0)); + println!("Loading fixed"); + let font: xlib::XFontStruct = ptr::read(xlib::XLoadQueryFont(self.display, CString::new("fixed").unwrap().as_ptr())); + xlib::XSetFont(self.display, gc, font.fid); + xlib::XClearWindow(self.display, self.inner); + XDrawString(self.display, self.inner, gc, + 3, 10, cstr.as_ptr(), cstr.to_bytes().len() as i32); + } + } + pub fn map(&self) { unsafe { XMapWindow(self.display, self.inner); } } -- cgit v1.2.3-70-g09d2