aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-11-19 21:11:34 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-11-19 21:11:34 -0300
commita21473f60c6cfad6335db3b0b45cdff23f8b3a89 (patch)
treeb5e37b1cd9d2146c5930c75aca84c74a9fbcc57d
parent27d0eddd4c1cc275d90938c350a3563428ec5b4f (diff)
downloaddotwm-a21473f60c6cfad6335db3b0b45cdff23f8b3a89.tar.gz
Implemented socket handler.
First steps on the socket handling. Dotwm will use this for communication between different clients trying to modify the behaviour (just take a look into hlwm's herbstclient program). It's needed a parser for the configuration, make the protocol and get it working better. For now I'm checking if it's anything into the socket every time I've a XEvent. But it shouldn't be this way.
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock15
-rw-r--r--Cargo.toml1
-rwxr-xr-xautostart4
-rw-r--r--src/command.rs90
-rw-r--r--src/main.rs107
-rw-r--r--src/socket.rs63
7 files changed, 197 insertions, 84 deletions
diff --git a/.gitignore b/.gitignore
index eb5a316..44279aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
target
+dotwm.sock
diff --git a/Cargo.lock b/Cargo.lock
index b881a57..eabeb47 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,10 +3,16 @@ name = "dotwm"
version = "0.1.0"
dependencies = [
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unix_socket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "libc"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -22,6 +28,15 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "unix_socket"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "x11"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index a83691d..66e2b19 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,6 +5,7 @@ authors = ["Matias Linares <matiaslina@openmailbox.org>"]
[dependencies]
libc = "0.2.*"
+unix_socket = "*"
[dependencies.x11]
version = "*"
diff --git a/autostart b/autostart
new file mode 100755
index 0000000..82cc3f6
--- /dev/null
+++ b/autostart
@@ -0,0 +1,4 @@
+#!/bin/mksh
+
+echo -n "hola" | netcat -U ./dotwm.sock
+echo -n "done" | netcat -U ./dotwm.sock
diff --git a/src/command.rs b/src/command.rs
index b728776..3bebc52 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -2,13 +2,22 @@
//! Command execution module.
//!
+use std::collections::HashMap;
use std::ffi::OsStr;
-use std::process::{Command,Child};
use std::io::Result;
+use std::ops::Deref;
+use std::process::{Command,Child};
+use std::process;
+use std::ptr;
use libc::c_int;
use libc::pid_t;
-use std::ptr;
+
+use x11::xlib;
+use x11::xlib::{XEvent, GrabModeAsync};
+
+use dotwm::DotWM;
+use safe_x11::grab_key;
const WNOHANG: c_int = 0x00000001;
@@ -31,3 +40,80 @@ pub fn collect_zombies() {
while waitpid(-1, ptr::null_mut(), WNOHANG) > 0 {}
};
}
+
+/// Defines a callback to call no certains events.
+pub type ExecFn = fn(&mut DotWM, XEvent, &[String]) -> bool;
+
+/// Map for keys => functions
+pub type BindingHash = HashMap<(u32, u32), (ExecFn, Vec<String>)>;
+
+pub fn exec_func(wm: &mut DotWM, bindings: &mut BindingHash, key: u32, modifiers: u32, ev: xlib::XEvent) {
+ if let Some(&(func, ref args)) = bindings.get(&(key, modifiers)) {
+ let v = args.clone();
+ func(wm, ev, &v);
+ }
+}
+
+pub fn exec(_: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
+ if let Some(program) = args.first() {
+ let mut prog_args = vec![];
+ for arg in args[1..].iter() {
+ prog_args.push(arg);
+ }
+ exec_cmd(program, prog_args.deref()).unwrap();
+ }
+ true
+}
+
+pub fn move_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
+ let x = args[0].parse::<i32>().unwrap();
+ let y = args[1].parse::<i32>().unwrap();
+ if let Some(ref win) = wm.current_window() {
+ win.move_offset(x, y);
+ };
+ true
+}
+
+pub fn resize_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
+ let w = args[0].parse::<i32>().unwrap();
+ let h = args[1].parse::<i32>().unwrap();
+
+ if let Some(ref win) = wm.current_window() {
+ win.resize(w, h);
+ };
+
+ true
+}
+
+pub fn focus_next(wm: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
+ wm.focus_next();
+ true
+}
+
+pub fn quit_dotwm(_: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
+ process::exit(0);
+}
+
+/// Add a binding to the WM.
+///
+/// # Example
+///
+/// ```
+/// fn quit_dotwm(_: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
+/// process::exit(0);
+/// }
+///
+/// // ...
+///
+/// add_binding(keysym::XK_Return, xlib::Mod4Mask, exec,
+/// &["xterm"]);
+/// ```
+pub fn add_binding(wm: &mut DotWM, bindings: &mut BindingHash,
+ key: u32, modifiers: u32, func: ExecFn, args: &[&str]) {
+ grab_key(wm.display, key, modifiers, true, GrabModeAsync, GrabModeAsync);
+ let mut v = vec![];
+ for arg in args {
+ v.push(arg.to_string());
+ }
+ bindings.insert((key, modifiers), (func, v));
+}
diff --git a/src/main.rs b/src/main.rs
index f00523d..e652dca 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,103 +2,28 @@
extern crate libc;
extern crate x11;
+extern crate unix_socket;
pub mod safe_x11;
pub mod command;
pub mod dotwm;
pub mod event;
+pub mod socket;
use dotwm::DotWM;
-use command::{exec_cmd,collect_zombies};
+use command::*;
use event::{Event,next_event};
+use socket::{configure_wm, listen_socket};
-use safe_x11::grab_key;
-
-use std::ops::Deref;
-use std::process;
use std::collections::HashMap;
use x11::xlib;
-use x11::xlib::GrabModeAsync;
use x11::xlib::XEvent;
use x11::keysym;
-/// Defines a callback to call no certains events.
-pub type ExecFn = fn(&mut DotWM, XEvent, &[String]) -> bool;
-
-/// Map for keys => functions
-pub type BindingHash = HashMap<(u32, u32), (ExecFn, Vec<String>)>;
-
-fn exec_func(wm: &mut DotWM, bindings: &mut BindingHash, key: u32, modifiers: u32, ev: xlib::XEvent) {
- if let Some(&(func, ref args)) = bindings.get(&(key, modifiers)) {
- let v = args.clone();
- func(wm, ev, &v);
- }
-}
-
-fn exec(_: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
- if let Some(program) = args.first() {
- let mut prog_args = vec![];
- for arg in args[1..].iter() {
- prog_args.push(arg);
- }
- exec_cmd(program, prog_args.deref()).unwrap();
- }
- true
-}
-
-fn move_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
- let x = args[0].parse::<i32>().unwrap();
- let y = args[1].parse::<i32>().unwrap();
- if let Some(ref win) = wm.current_window() {
- win.move_offset(x, y);
- };
- true
-}
-
-fn resize_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
- let w = args[0].parse::<i32>().unwrap();
- let h = args[1].parse::<i32>().unwrap();
-
- if let Some(ref win) = wm.current_window() {
- win.resize(w, h);
- };
-
- true
-}
-
-fn focus_next(wm: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
- wm.focus_next();
- true
-}
-
-fn quit_dotwm(_: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
- process::exit(0);
-}
-
-/// Add a binding to the WM.
-///
-/// # Example
-///
-/// ```
-/// fn quit_dotwm(_: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool {
-/// process::exit(0);
-/// }
-///
-/// // ...
-///
-/// add_binding(keysym::XK_Return, xlib::Mod4Mask, exec,
-/// &["xterm"]);
-/// ```
-fn add_binding(wm: &mut DotWM, bindings: &mut BindingHash,
- key: u32, modifiers: u32, func: ExecFn, args: &[&str]) {
- grab_key(wm.display, key, modifiers, true, GrabModeAsync, GrabModeAsync);
- let mut v = vec![];
- for arg in args {
- v.push(arg.to_string());
- }
- bindings.insert((key, modifiers), (func, v));
-}
+use std::thread;
+use std::sync::mpsc::channel;
+use unix_socket::UnixListener;
fn main() {
println!("Creating dotwm");
@@ -127,8 +52,26 @@ fn main() {
add_binding(&mut dotwm, &mut bindings, keysym::XK_q, xlib::Mod4Mask | xlib::ShiftMask, quit_dotwm, &[]);
+ let (transmission, receiver) = channel();
+
+ thread::spawn(move || {
+ println!("Creating socket");
+ let listener = UnixListener::bind("./dotwm.sock").unwrap();
+
+ for stream in listener.incoming() {
+ match stream {
+ Ok(stream) => transmission.send(stream).unwrap() ,
+ Err(e) => println!("{}", e),
+ }
+ }
+ });
+
+ configure_wm(&mut dotwm, &receiver);
+
// Main loop
loop {
+ listen_socket(&mut dotwm, &receiver);
+ // Event handling.
let event = next_event(dotwm.display);
println!("Event {:?}", event);
match event {
diff --git a/src/socket.rs b/src/socket.rs
new file mode 100644
index 0000000..b3bb9cc
--- /dev/null
+++ b/src/socket.rs
@@ -0,0 +1,63 @@
+// See LICENSE file for copyright and license details.
+
+use std::io::{Read,Write};
+use std::sync::mpsc::{Receiver, TryRecvError};
+
+use unix_socket::UnixStream;
+
+use dotwm::DotWM;
+use command::*;
+
+#[allow(unused_variables)]
+fn handle_socket(dotwm: &mut DotWM, stream: UnixStream) {
+ let mut s = stream.try_clone().unwrap();
+ let mut buf = String::new();
+ s.read_to_string(&mut buf).unwrap();
+ println!("buf: {}", buf);
+
+ let _ = write!(s, "ok");
+}
+
+#[allow(unused_variables)]
+/// Handles the configuration and returns true when we're finished.
+fn handle_configure(dotwm: &mut DotWM, s: UnixStream) -> bool {
+ let mut stream = match s.try_clone() {
+ Ok(s) => s,
+ Err(_) => { println!("Error"); return true },
+ };
+
+ let mut input = String::new();
+ stream.read_to_string(&mut input).unwrap();
+
+ if input != "done" {
+ let _ = write!(stream, "ok");
+ false
+ } else {
+ let _ = write!(stream, "exit");
+ true
+ }
+}
+
+pub fn configure_wm(dotwm: &mut DotWM, rx: &Receiver<UnixStream>) {
+ exec_cmd("./autostart", &[]).unwrap();
+ loop {
+ match rx.recv() {
+ Ok(stream) => {
+ if handle_configure(dotwm, stream) {
+ break;
+ }
+ },
+ Err(e) => panic!("Socket: {}", e),
+ }
+ }
+}
+
+pub fn listen_socket(dotwm: &mut DotWM, rx: &Receiver<UnixStream>) {
+ loop {
+ match rx.try_recv() {
+ Ok(stream) => handle_socket(dotwm, stream) ,
+ Err(TryRecvError::Empty) => break,
+ Err(TryRecvError::Disconnected) => panic!("Socket disconnected"),
+ }
+ }
+}