aboutsummaryrefslogtreecommitdiff
path: root/src/safe_x11
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-11-29 11:57:19 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-11-29 11:57:48 -0300
commitd5e55aab6499a89e9dfaf5b976938bfe3e2f6aee (patch)
tree52efc28076c31fdd2522ed8b7871a7dd99ad0c87 /src/safe_x11
parente1ec354306742a5804a20e2651cf49945cd17287 (diff)
downloaddotwm-d5e55aab6499a89e9dfaf5b976938bfe3e2f6aee.tar.gz
Begin ef EWMH support and sticky movement
The implementationn of the EWMH and ICCCM support is incomplete. I need to check how to implement on the right way.
Diffstat (limited to 'src/safe_x11')
-rw-r--r--src/safe_x11/mod.rs17
-rw-r--r--src/safe_x11/window.rs68
2 files changed, 84 insertions, 1 deletions
diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs
index 0283966..9cd14fd 100644
--- a/src/safe_x11/mod.rs
+++ b/src/safe_x11/mod.rs
@@ -6,6 +6,8 @@
use x11::xlib;
use x11::xlib::{
Display,
+ XDisplayWidth, XDisplayHeight,
+ XDefaultScreen,
XConnectionNumber,
Screen,
Cursor,
@@ -17,6 +19,8 @@ use x11::xlib::{
// Windows
Window,
+
+ Atom, XInternAtom,
};
use x11::xlib::XKeyEvent;
@@ -110,6 +114,12 @@ pub fn next_xevent(display: *mut Display) -> XEvent {
}
}
+pub fn screen_size(display: *mut Display) -> (u32, u32) {
+ let screen = unsafe { XDefaultScreen(display) };
+ let dw: u32 = unsafe { XDisplayWidth(display, screen) as u32 };
+ let dh: u32 = unsafe { XDisplayHeight(display, screen) as u32 };
+ (dw, dh)
+}
/// Grab pointer buttons.
///
@@ -210,3 +220,10 @@ fn get_color<T: Into<Vec<u8>>>(display: *mut Display, color: T) -> u64{
pub fn lookup_keysym(ev: &mut XKeyEvent) -> xlib::KeySym {
unsafe { xlib::XLookupKeysym(ev, 0) }
}
+
+pub fn atom<T: Into<Vec<u8>>>(display: *mut Display, name: T) -> Atom {
+ unsafe {
+ let cstr = CString::new(name).unwrap();
+ XInternAtom(display, cstr.as_ptr(), 0)
+ }
+}
diff --git a/src/safe_x11/window.rs b/src/safe_x11/window.rs
index 0e8ab10..6c8e48b 100644
--- a/src/safe_x11/window.rs
+++ b/src/safe_x11/window.rs
@@ -6,16 +6,25 @@ use x11::xlib::{
XWindowAttributes,
XGetWindowAttributes,
XDefaultScreenOfDisplay,
- XMoveWindow,
+ XMoveWindow, XMoveResizeWindow,
+
+ XDisplayHeight, XDisplayWidth, XDefaultScreen,
+ XA_ATOM, Atom, PropModeReplace,
XSetInputFocus,
XSetWindowBorder,
IsViewable, RevertToParent, CurrentTime,
+
+ XEvent, XSendEvent, XClientMessageEvent,
+ ClientMessage,ClientMessageData, NoEventMask,
+
+ XChangeProperty,
};
use std::ptr;
use std::mem::uninitialized;
+use std::mem::transmute;
use std::cmp::{max};
use safe_x11::{screen_ratio,get_color};
@@ -25,6 +34,7 @@ pub struct XWindow {
display: *mut xlib::Display,
/// xlib::Window that wraps this struct.
pub inner: Window,
+ fullscreen: bool,
}
fn fixed_with_ratio(x: i32, ratio: f32) -> i32 {
@@ -41,6 +51,7 @@ impl XWindow {
Some(XWindow {
display: d,
inner: w,
+ fullscreen: false,
})
} else {
None
@@ -52,6 +63,25 @@ impl XWindow {
unsafe { xlib::XSetWindowBorderWidth(self.display, self.inner, size) };
}
+ /// clients receiving a WM_DELETE_WINDOW message should behave as if
+ /// the user selected "delete window" from a hypothetical menu and
+ /// also perform any confirmation dialog with the user.
+ pub fn delete(&self) {
+ let mut ev: XClientMessageEvent = unsafe { uninitialized() };
+ ev.type_ = ClientMessage;
+ ev.window = self.inner;
+ ev.format = 32;
+ ev.message_type = 0; // WM_PROTOCOLS
+ ev.data = ClientMessageData::new();
+ ev.data.set_long(0, 0); // WM_DELETE_WINDOW
+ ev.data.set_long(1, CurrentTime as i64);
+
+ let mut event = XEvent::from(ev);
+
+ unsafe { XSendEvent(self.display, self.inner, 0, NoEventMask, &mut event); }
+ }
+
+ /// Sets the border color to the selected window
pub fn set_border_color<T: Into<Vec<u8>>>(&self, color: T) {
let c = get_color(self.display, color);
unsafe { XSetWindowBorder(self.display, self.inner, c); }
@@ -116,6 +146,13 @@ impl XWindow {
Ok(())
}
}
+
+ /// 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);
+ }
+ }
/// Resizes the window a fixed amount within the height and width.
pub fn resize(&self, w: i32, h: i32) {
@@ -148,4 +185,33 @@ impl XWindow {
self.set_border_width(1);
self.set_border_color("black");
}
+
+ /// Fullscreen toggle
+ pub fn toggle_fullscreen(&mut self, wm_state_atom: Atom,
+ fs_atom: Atom, fullscreen: bool) {
+ let screen = unsafe { XDefaultScreen(self.display) };
+ let dh: u32 = unsafe { XDisplayHeight(self.display, screen) as u32 };
+ let dw: u32 = unsafe { XDisplayWidth(self.display, screen) as u32 };
+
+ if fullscreen != self.fullscreen {
+ self.fullscreen = fullscreen;
+ let fs_atom_slice: &[Atom; 1] = &[fs_atom];
+ let fs_atom_ptr: *const u8 = unsafe { transmute(fs_atom_slice) };
+
+ println!("Changing property!");
+ unsafe {
+ XChangeProperty(self.display, self.inner, wm_state_atom,
+ XA_ATOM, 32, PropModeReplace, fs_atom_ptr,
+ fullscreen as i32);
+ }
+ }
+
+ if fullscreen {
+ println!("resizing!");
+ self.move_resize(0, 0, dw, dh);
+ self.set_border_width(0);
+ } else {
+ self.set_border_width(1);
+ }
+ }
}