Dynamic widget configuration and layout
1. Implement new layout API, replacing previous hard-coded layout. 2. Make the widgets (previously modules) configurable. 3. Split some widgets into smaller modules. 4. Configuration file (reluctantly JSON at time of writing). 5. More correct damage handling, copying damage to next buffer.
This commit is contained in:
+65
-27
@@ -3,6 +3,8 @@ use std::io::{BufRead, BufReader, Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::fs::File;
|
||||
use std::default::Default;
|
||||
|
||||
use nix::poll::{poll, PollFd, PollFlags};
|
||||
use os_pipe::pipe;
|
||||
@@ -11,9 +13,12 @@ mod app;
|
||||
mod buffer;
|
||||
mod cmd;
|
||||
mod color;
|
||||
mod draw;
|
||||
mod modules;
|
||||
mod config;
|
||||
mod desktop;
|
||||
mod doublemempool;
|
||||
mod draw;
|
||||
mod widget;
|
||||
mod widgets;
|
||||
|
||||
use app::{App, OutputMode};
|
||||
use cmd::Cmd;
|
||||
@@ -22,6 +27,7 @@ enum Mode {
|
||||
Start,
|
||||
StartOrKill,
|
||||
ToggleVisible,
|
||||
PrintConfig,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -29,11 +35,24 @@ fn main() {
|
||||
Ok(dir) => dir + "/wldash",
|
||||
Err(_) => "/tmp/wldash".to_string(),
|
||||
};
|
||||
let scale = match env::var("WLDASH_SCALE") {
|
||||
Ok(s) => s.parse().unwrap(),
|
||||
Err(_) => 1,
|
||||
let config_home = match env::var("XDG_CONFIG_HOME") {
|
||||
Ok(dir) => dir + "/wldash",
|
||||
Err(_) => match env::var("HOME") {
|
||||
Ok(home) => home + "/.config/wldash",
|
||||
Err(_) => panic!("unable to find user folder"),
|
||||
}
|
||||
};
|
||||
|
||||
let config: config::Config = match File::open(config_home + "/config.json") {
|
||||
Ok(f) => {
|
||||
let reader = BufReader::new(f);
|
||||
serde_json::from_reader(reader).unwrap()
|
||||
},
|
||||
Err(_) => Default::default(),
|
||||
};
|
||||
|
||||
let scale = config.scale;
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mode = match args.len() {
|
||||
1 => Mode::Start,
|
||||
@@ -41,6 +60,7 @@ fn main() {
|
||||
"start" => Mode::Start,
|
||||
"start-or-kill" => Mode::StartOrKill,
|
||||
"toggle-visible" => Mode::ToggleVisible,
|
||||
"print-config" => Mode::PrintConfig,
|
||||
s => {
|
||||
eprintln!("unsupported sub-command {}", s);
|
||||
std::process::exit(1);
|
||||
@@ -73,23 +93,37 @@ fn main() {
|
||||
std::process::exit(1);
|
||||
};
|
||||
}
|
||||
Mode::PrintConfig => {
|
||||
println!("{}", serde_json::to_string_pretty(&config).unwrap());
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = std::fs::remove_file(socket_path.clone());
|
||||
|
||||
let listener = UnixListener::bind(socket_path.clone()).unwrap();
|
||||
|
||||
let output_mode = match config.output_mode {
|
||||
config::OutputMode::All => OutputMode::All,
|
||||
config::OutputMode::Active => OutputMode::Active,
|
||||
};
|
||||
|
||||
let (tx_draw, rx_draw) = channel();
|
||||
let tx_draw_mod = tx_draw.clone();
|
||||
let (mod_tx, mod_rx) = channel();
|
||||
std::thread::spawn(move || {
|
||||
// Print, write to a file, or send to an HTTP server.
|
||||
match config.widget.construct(tx_draw_mod) {
|
||||
Some(w) => mod_tx.send(w).unwrap(),
|
||||
None => panic!("no widget configured"),
|
||||
}
|
||||
});
|
||||
|
||||
let mut app = App::new(tx_draw, output_mode, scale);
|
||||
let widget = mod_rx.recv().unwrap();
|
||||
app.set_widget(widget).unwrap();
|
||||
|
||||
let (mut rx_pipe, mut tx_pipe) = pipe().unwrap();
|
||||
let ipc_pipe = tx_pipe.try_clone().unwrap();
|
||||
let (tx_draw, rx_draw) = channel();
|
||||
|
||||
let output_mode = match env::var("WLDASH_ALL_OUTPUTS") {
|
||||
Ok(_) => OutputMode::All,
|
||||
Err(_) => OutputMode::Active,
|
||||
};
|
||||
|
||||
let mut app = App::new(tx_draw, output_mode, scale);
|
||||
app.wipe();
|
||||
|
||||
let worker_queue = app.cmd_queue();
|
||||
let _ = std::thread::Builder::new()
|
||||
@@ -156,18 +190,22 @@ fn main() {
|
||||
app.redraw(true).expect("Failed to draw");
|
||||
app.flush_display();
|
||||
}
|
||||
Cmd::MouseInput { pos, input } => {
|
||||
if let Some(m) = app.get_module(pos) {
|
||||
let bounds = m.get_bounds();
|
||||
let input = input.offset((bounds.0, bounds.1));
|
||||
m.input(input);
|
||||
q.lock().unwrap().push_back(Cmd::Draw);
|
||||
}
|
||||
Cmd::MouseClick { btn, pos } => {
|
||||
app.get_widget().mouse_click(btn, pos);
|
||||
q.lock().unwrap().push_back(Cmd::Draw);
|
||||
}
|
||||
Cmd::KeyboardInput { input } => {
|
||||
app.with_modules(|m| {
|
||||
m.input(input.clone());
|
||||
});
|
||||
Cmd::MouseScroll { scroll, pos } => {
|
||||
app.get_widget().mouse_scroll(scroll, pos);
|
||||
q.lock().unwrap().push_back(Cmd::Draw);
|
||||
}
|
||||
Cmd::Keyboard {
|
||||
key,
|
||||
key_state,
|
||||
modifiers_state,
|
||||
interpreted,
|
||||
} => {
|
||||
app.get_widget()
|
||||
.keyboard_input(key, modifiers_state, key_state, interpreted);
|
||||
q.lock().unwrap().push_back(Cmd::Draw);
|
||||
}
|
||||
Cmd::ToggleVisible => {
|
||||
@@ -201,7 +239,7 @@ fn main() {
|
||||
}
|
||||
|
||||
if fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||
let mut v: Vec<u8> = vec![0x00];
|
||||
let mut v = [0x00];
|
||||
rx_pipe.read_exact(&mut v).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user