aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.rs41
-rw-r--r--src/desktop.rs2
-rw-r--r--src/event.rs4
-rw-r--r--src/main.rs3
-rw-r--r--src/safe_x11/mod.rs7
-rw-r--r--src/safe_x11/window.rs97
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<T: Into<Vec<u8>>>(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<XWindow> {
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<T: Into<Vec<u8>>>(&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); }
}