123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- #[macro_use]
- extern crate chan;
- extern crate chan_signal;
- extern crate getopts;
- extern crate xcb;
- mod atom;
- mod tray;
- use std::env;
- use std::process;
- use std::thread;
- use std::sync::Arc;
- const PROGRAM: &'static str = "rustray";
- const EXIT_WRONG_ARGS: i32 = 1;
- const EXIT_FAILED_CONNECT: i32 = 10;
- const EXIT_FAILED_SELECT: i32 = 11;
- fn main() {
- process::exit(real_main());
- }
- fn real_main() -> i32 {
- let signal = chan_signal::notify(&[chan_signal::Signal::INT, chan_signal::Signal::TERM]);
- let args: Vec<String> = env::args().collect();
- let mut opts = getopts::Options::new();
- opts.optopt("i", "icon-size", "size of the tray icons, default 20", "<size>");
- opts.optopt("p", "position", "position of the tray, one of: top-left, top-right, bottom-left, bottom-right", "<pos>");
- opts.optflag("h", "help", "print this help menu");
- let matches = match opts.parse(&args[1..]) {
- Ok(m) => m,
- Err(f) => panic!(f.to_string())
- };
- if matches.opt_present("h") {
- let brief = format!("Usage: {} [options]", PROGRAM);
- print!("{}", opts.usage(&brief));
- return 0
- }
- let pos = matches.opt_str("p").unwrap_or("top-left".to_string());
- let pos = match pos.as_ref() {
- "top-left" => tray::TOP_LEFT,
- "top-right" => tray::TOP_RIGHT,
- "bottom-left" => tray::BOTTOM_LEFT,
- "bottom-right" => tray::BOTTOM_RIGHT,
- _ => {
- println!("Invalid position specified.");
- return EXIT_WRONG_ARGS
- }
- };
- let size = matches.opt_str("i");
- let size = match size {
- Some(string) => match string.parse::<u16>() {
- Ok(size) => size,
- Err(e) => {
- println!("Invalid size specified, {}.", e.to_string());
- return EXIT_WRONG_ARGS
- }
- },
- None => 20
- };
- if let Ok((conn, preferred)) = xcb::Connection::connect(None) {
- let conn = Arc::new(conn);
- let atoms = atom::Atoms::new(&conn);
- let mut tray = tray::Tray::new(&conn, &atoms, preferred as usize, size, pos);
- if !tray.is_selection_available() {
- println!("Another system tray is already running");
- return EXIT_FAILED_SELECT
- }
- let (tx, rx) = chan::sync(0);
- {
- let conn = conn.clone();
- thread::spawn(move || {
- loop {
- match conn.wait_for_event() {
- Some(event) => { tx.send(event); },
- None => { break; }
- }
- }
- });
- }
- tray.create();
- loop {
- chan_select!(
- rx.recv() -> event => {
- if let Some(code) = tray.handle_event(event.unwrap()) {
- return code
- }
- },
- signal.recv() => {
- tray.finish();
- }
- );
- }
- }
- else {
- println!("Could not connect to X server!");
- return EXIT_FAILED_CONNECT
- }
- }
|