From 7be3d97d7b9fd4c96790c3c0ebde056bdc34c1c5 Mon Sep 17 00:00:00 2001 From: "Ospald, Julian" Date: Fri, 30 Jun 2017 17:24:26 +0200 Subject: [PATCH] Broken crap --- Cargo.toml | 1 + src/app_state.rs | 61 +++++++++- src/audio.rs | 173 ++++++++++++++++++-------- src/errors.rs | 43 +++++++ src/main.rs | 16 +-- src/myalsa.rs | 8 +- src/ui_entry.rs | 21 +++- src/ui_popup_window.rs | 270 ++++++++++++++++++++++++++--------------- src/ui_tray_icon.rs | 29 +++-- 9 files changed, 436 insertions(+), 186 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8b7504d6f..62e1b499d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ gdk-sys = { git = "https://github.com/gtk-rs/sys" } gtk-sys = { git = "https://github.com/gtk-rs/sys" } glib = { git = "https://github.com/gtk-rs/glib.git" } glib-sys = { git = "https://github.com/gtk-rs/sys" } +gobject-sys = { git = "https://github.com/gtk-rs/sys" } ffi = "^0.0.2" flexi_logger = "^0.5.1" log = "^0.3.8" diff --git a/src/app_state.rs b/src/app_state.rs index 113afaedb..07ae0da61 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -1,11 +1,64 @@ use gtk; +use audio::AlsaCard; +use std::cell::RefCell; +use std::rc::Rc; +// TODO: destructors // TODO: glade stuff, config, alsacard pub struct AppS { - /* we keep this to ensure the lifetime is across the whole application */ - pub status_icon: gtk::StatusIcon, - - pub builder_popup: gtk::Builder, + pub gui: Gui, + pub acard: Rc>, +} + + +impl AppS { + pub fn new() -> AppS { + let builder_popup = gtk::Builder::new_from_string(include_str!( + "../data/ui/popup-window-vertical.glade" + )); + return AppS { + gui: Gui::new(builder_popup), + acard: Rc::new(RefCell::new( + AlsaCard::new(None, Some(String::from("Master"))).unwrap(), + )), + }; + } +} + + +pub struct Gui { + pub status_icon: gtk::StatusIcon, + pub popup_window: PopupWindow, +} + + +impl Gui { + pub fn new(builder: gtk::Builder) -> Gui { + return Gui { + status_icon: gtk::StatusIcon::new_from_icon_name("pnmixer"), + popup_window: PopupWindow::new(builder), + }; + } +} + + +pub struct PopupWindow { + pub window: gtk::Window, + pub vol_scale_adj: gtk::Adjustment, + pub vol_scale: gtk::Scale, + pub mute_check: gtk::CheckButton, +} + + +impl PopupWindow { + pub fn new(builder: gtk::Builder) -> PopupWindow { + return PopupWindow { + window: builder.get_object("popup_window").unwrap(), + vol_scale_adj: builder.get_object("vol_scale_adj").unwrap(), + vol_scale: builder.get_object("vol_scale").unwrap(), + mute_check: builder.get_object("mute_check").unwrap(), + }; + } } diff --git a/src/audio.rs b/src/audio.rs index 7feb71a43..40e722223 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -11,6 +11,7 @@ use libc::size_t; use myalsa::*; use std::mem; use std::cell::RefCell; +use std::cell::Ref; use std::ptr; use std::u8; @@ -23,15 +24,17 @@ pub struct AlsaCard { pub mixer: Mixer, pub selem_id: SelemId, pub watch_ids: Vec, - last_action_timestamp: RefCell, + pub last_action_timestamp: RefCell, + pub handlers: RefCell>>, } /* TODO: AlsaCard cleanup */ impl AlsaCard { - pub fn new(card_name: Option, - elem_name: Option) - -> Result { + pub fn new( + card_name: Option, + elem_name: Option, + ) -> Result { let card = { match card_name { Some(name) => get_alsa_card_by_name(name)?, @@ -39,33 +42,41 @@ impl AlsaCard { } }; let mixer = get_mixer(&card)?; - let selem_id = - get_selem_by_name(&mixer, - elem_name.unwrap_or(String::from("Master"))) - .unwrap() - .get_id(); + let selem_id = get_selem_by_name( + &mixer, + elem_name.unwrap_or(String::from("Master")), + ).unwrap() + .get_id(); let vec_pollfd = PollDescriptors::get(&mixer)?; + let mut acard = AlsaCard { + _cannot_construct: (), + card: card, + mixer: mixer, + selem_id: selem_id, + watch_ids: vec![], + last_action_timestamp: RefCell::new(0), + handlers: RefCell::new(vec![]), + }; + /* TODO: callback is registered here, which must be unregistered * when the mixer is destroyed!! * poll descriptors must be unwatched too */ - let watch_ids = watch_poll_descriptors(vec_pollfd, &mixer); + let watch_ids = watch_poll_descriptors(vec_pollfd, &acard); + // acard.watch_ids = watch_ids; - return Ok(AlsaCard { - _cannot_construct: (), - card: card, - mixer: mixer, - selem_id: selem_id, - watch_ids: watch_ids, - last_action_timestamp: RefCell::new(0), - }); + // println!("Watch IDs: {:?}", acard.watch_ids); + println!("Last_Timestamp: {}", acard.last_action_timestamp.borrow()); + + + return Ok(acard); } pub fn selem(&self) -> Selem { return get_selems(&self.mixer) - .nth(self.selem_id.get_index() as usize) - .unwrap(); + .nth(self.selem_id.get_index() as usize) + .unwrap(); } @@ -75,8 +86,12 @@ impl AlsaCard { pub fn set_vol(&self, new_vol: f64, user: AudioUser) -> Result<()> { - let mut rc = self.last_action_timestamp.borrow_mut(); - *rc = glib::get_real_time(); + { + let mut rc = self.last_action_timestamp.borrow_mut(); + *rc = glib::get_monotonic_time(); + println!("glib::get_monotonic_time: {}", glib::get_real_time()); + } + println!("Now timestamp: {}", self.last_action_timestamp.borrow()); // TODO invoke handlers, make use of user return set_vol(&self.selem(), new_vol); } @@ -94,32 +109,76 @@ impl AlsaCard { pub fn set_mute(&self, mute: bool, user: AudioUser) -> Result<()> { let mut rc = self.last_action_timestamp.borrow_mut(); - *rc = glib::get_real_time(); + *rc = glib::get_monotonic_time(); // TODO invoke handlers, make use of user return set_mute(&self.selem(), mute); } fn on_alsa_event(&self, alsa_event: AlsaEvent) { - let last: i64 = *self.last_action_timestamp.borrow(); - let now: i64 = glib::get_monotonic_time(); - let delay = now - last; - if delay < 1000000 { - return; - } + // let last: i64 = *Ref::clone(&self.last_action_timestamp.borrow()); + + // if last != 0 { + // let now: i64 = glib::get_monotonic_time(); + // let delay: i64 = now - last; + // if delay < 1000000 { + // println!("Too short: {} and {}", now, last); + // println!("Delay: {}", delay); + // return; + // } + // *self.last_action_timestamp.borrow_mut() = 0; + // } + /* external change */ match alsa_event { // TODO: invoke handlers with AudioUserUnknown AlsaEvent::AlsaCardError => println!("AlsaCardError"), AlsaEvent::AlsaCardDiconnected => println!("AlsaCardDiconnected"), - AlsaEvent::AlsaCardValuesChanged => println!("AlsaCardValuesChanged"), + AlsaEvent::AlsaCardValuesChanged => { + println!("AlsaCardValuesChanged"); + self.invoke_handlers( + self::AudioSignal::AudioValuesChanged, + self::AudioUser::AudioUserUnknown, + ); + } } } + + + fn invoke_handlers(&self, signal: AudioSignal, user: AudioUser) { + + let mut vec = vec![1,2,3]; + + for v in &vec { + println!("Elem: {}", v); + } + + let handlers = self.handlers.borrow(); + let x: &Vec> = &*handlers; + println!("Vec size: {}", handlers.capacity()); + // for handler in x { + // // let unboxed = handler.as_ref(); + // // unboxed(&self, signal, user); + // println!("Gogo"); + // } + } + + + pub fn connect_handler( + &self, + cb: Box, + ) { + println!("Vec size before: {}", self.handlers.borrow().capacity()); + + self.handlers.borrow_mut().push(cb); + println!("Vec size after: {}", self.handlers.borrow().capacity()); + } } +#[derive(Clone, Copy)] pub enum AudioUser { AudioUserUnknown, AudioUserPopup, @@ -128,7 +187,8 @@ pub enum AudioUser { } -enum AudioSignal { +#[derive(Clone, Copy)] +pub enum AudioSignal { AudioNoCard, AudioCardInitialized, AudioCardCleanedUp, @@ -137,17 +197,19 @@ enum AudioSignal { AudioValuesChanged, } -enum AlsaEvent { + +#[derive(Clone, Copy)] +pub enum AlsaEvent { AlsaCardError, AlsaCardDiconnected, AlsaCardValuesChanged, } -fn watch_poll_descriptors(polls: Vec, mixer: &Mixer) -> Vec { +fn watch_poll_descriptors(polls: Vec, acard: &AlsaCard) -> Vec { let mut watch_ids: Vec = vec![]; - let mixer_ptr = - unsafe { mem::transmute::<&Mixer, &*mut alsa_sys::snd_mixer_t>(mixer) }; + let acard_ptr = + unsafe { mem::transmute::<&AlsaCard, &glib_sys::gpointer>(acard) }; for poll in polls { unsafe { let gioc: *mut glib_sys::GIOChannel = @@ -158,24 +220,31 @@ fn watch_poll_descriptors(polls: Vec, mixer: &Mixer) -> Vec { glib_sys::G_IO_IN.bits() | glib_sys::G_IO_ERR.bits(), ).unwrap(), Some(watch_cb), - *mixer_ptr as glib_sys::gpointer, + *acard_ptr, )); } } + println!("Handler size in watch_poll_descriptors: {}", acard.handlers.borrow().capacity()); return watch_ids; } -extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel, - cond: glib_sys::GIOCondition, - data: glib_sys::gpointer) - -> glib_sys::gboolean { +extern "C" fn watch_cb( + chan: *mut glib_sys::GIOChannel, + cond: glib_sys::GIOCondition, + data: glib_sys::gpointer, +) -> glib_sys::gboolean { - let mixer = data as *mut alsa_sys::snd_mixer_t; + let acard = + unsafe { mem::transmute::<&glib_sys::gpointer, &AlsaCard>(&data) }; + println!("Handler size in watch_cb: {}", acard.handlers.borrow().capacity()); + let mixer = unsafe { + mem::transmute::<&Mixer, &*mut alsa_sys::snd_mixer_t>(&acard.mixer) + }; unsafe { - alsa_sys::snd_mixer_handle_events(mixer); + alsa_sys::snd_mixer_handle_events(*mixer); } if cond == glib_sys::G_IO_ERR { @@ -186,14 +255,15 @@ extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel, let mut buf: Vec = vec![0; 256]; while sread > 0 { - let stat: glib_sys::GIOStatus = - unsafe { - glib_sys::g_io_channel_read_chars(chan, - buf.as_mut_ptr() as *mut u8, - 256, - &mut sread as *mut size_t, - ptr::null_mut()) - }; + let stat: glib_sys::GIOStatus = unsafe { + glib_sys::g_io_channel_read_chars( + chan, + buf.as_mut_ptr() as *mut u8, + 256, + &mut sread as *mut size_t, + ptr::null_mut(), + ) + }; match stat { glib_sys::G_IO_STATUS_AGAIN => { @@ -209,5 +279,8 @@ extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel, // TODO: handle alsa events, pass to 'on_alsa_event' + println!("on_alsa_event triggering"); + acard.on_alsa_event(AlsaEvent::AlsaCardValuesChanged); + return true as glib_sys::gboolean; } diff --git a/src/errors.rs b/src/errors.rs index 160153f54..ac4127720 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -79,3 +79,46 @@ macro_rules! try_r { }, }); } + + + +#[macro_export] +macro_rules! try_e { + ($expr:expr) => { + try_er!($expr, ()) + }; + ($expr:expr, $fmt:expr, $($arg:tt)+) => { + try_er!($expr, (), $fmt, $(arg)+) + }; + ($expr:expr, $fmt:expr) => { + try_er!($expr, (), $fmt) + } +} + + +#[macro_export] +macro_rules! try_er { + ($expr:expr, $ret:expr) => (match $expr { + ::std::result::Result::Ok(val) => val, + ::std::result::Result::Err(err) => { + err!("{:?}", err); + return $ret; + }, + }); + ($expr:expr, $ret:expr, $fmt:expr) => (match $expr { + std::result::Result::Ok(val) => val, + std::result::Result::Err(err) => { + err!("Original error: {:?}", err); + err!($fmt); + return $ret; + }, + }); + ($expr:expr, $ret:expr, $fmt:expr, $($arg:tt)+) => (match $expr { + std::result::Result::Ok(val) => val, + std::result::Result::Err(err) => { + err!("Original error: {:?}", err); + err!(format!($fmt, $(arg)+)); + return $ret; + }, + }) +} diff --git a/src/main.rs b/src/main.rs index 7b46c4cf9..e23e46b60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,12 +15,11 @@ extern crate gdk; extern crate gdk_sys; extern crate glib; extern crate glib_sys; +extern crate gobject_sys; extern crate gtk; extern crate gtk_sys; extern crate libc; -use app_state::*; -use std::cell::RefCell; use std::rc::Rc; #[macro_use] @@ -33,21 +32,14 @@ mod ui_entry; mod ui_popup_window; mod ui_tray_icon; -use audio::AlsaCard; +use app_state::*; fn main() { gtk::init().unwrap(); - let ref apps = AppS { - status_icon: gtk::StatusIcon::new_from_icon_name("pnmixer"), - builder_popup: gtk::Builder::new_from_string(include_str!("../data/ui/popup-window-vertical.glade")), - }; - - let acard = Rc::new(RefCell::new(AlsaCard::new(None, - Some(String::from("Master"))) - .unwrap())); + let apps = Rc::new(AppS::new()); flexi_logger::LogOptions::new() .log_to_file(false) @@ -55,7 +47,7 @@ fn main() { .init(Some("info".to_string())) .unwrap_or_else(|e| panic!("Logger initialization failed with {}", e)); - ui_entry::init(apps, acard); + ui_entry::init(apps); gtk::main(); } diff --git a/src/myalsa.rs b/src/myalsa.rs index af5f0e718..19e639131 100644 --- a/src/myalsa.rs +++ b/src/myalsa.rs @@ -56,9 +56,7 @@ pub fn get_selems(mixer: &Mixer) -> Map Selem> { pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result { for selem in get_selems(mixer) { - let n = selem.get_id() - .get_name() - .map(|y| String::from(y))?; + let n = selem.get_id().get_name().map(|y| String::from(y))?; if n == name { return Ok(selem); @@ -99,7 +97,9 @@ pub fn set_vol(selem: &Selem, new_vol: f64) -> Result<()> { } let range = selem.get_playback_volume_range(); - selem.set_playback_volume_all(percent_to_vol(new_vol, range))?; + selem.set_playback_volume_all( + percent_to_vol(new_vol, range), + )?; return Ok(()); } diff --git a/src/ui_entry.rs b/src/ui_entry.rs index 7aa4707a7..9659c75be 100644 --- a/src/ui_entry.rs +++ b/src/ui_entry.rs @@ -1,5 +1,5 @@ use app_state::*; -use audio::AlsaCard; +use audio::{AlsaCard, AudioSignal, AudioUser}; use std::cell::RefCell; use std::rc::Rc; use ui_popup_window::*; @@ -7,8 +7,21 @@ use ui_tray_icon::*; -pub fn init<'a>(appstate: &'a AppS, rc_acard: Rc>) { +pub fn init(appstate: Rc) { + let s1 = appstate.clone(); + let s2 = appstate.clone(); - init_tray_icon(&appstate); - init_popup_window(&appstate, rc_acard); + appstate.acard.borrow().connect_handler( + Box::new(|_, s, u| { + println!("In der closure"); + match (s, u) { + (AudioSignal::AudioValuesChanged, AudioUser::AudioUserUnknown) => { + println!("Gaga"); + } + _ => println!("Nix"), + }}), + ); + + init_tray_icon(s1); + init_popup_window(s2); } diff --git a/src/ui_popup_window.rs b/src/ui_popup_window.rs index b4dde5559..6a540aafb 100644 --- a/src/ui_popup_window.rs +++ b/src/ui_popup_window.rs @@ -1,113 +1,161 @@ use app_state::*; -use audio::AlsaCard; use audio::AudioUser::*; use errors::*; use gdk::DeviceExt; use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK}; use gdk; use gdk_sys::{GDK_KEY_Escape, GDK_CURRENT_TIME}; +use glib; +use glib_sys; +use gobject_sys::{G_SIGNAL_MATCH_ID, G_SIGNAL_MATCH_DATA}; +use gobject_sys; use gtk::prelude::*; use gtk; -use std::cell::RefCell; +use std::mem; +use std::ptr; use std::rc::Rc; -pub fn init_popup_window(appstate: &AppS, rc_acard: Rc>) { +pub fn init_popup_window(appstate: Rc) { + let mut toggle_signal = 0; + + /* mute_check.connect_toggled */ + { + let _appstate = appstate.clone(); + let mute_check = &appstate.clone().gui.popup_window.mute_check; + toggle_signal = mute_check.connect_toggled( + move |_| on_mute_check_toggled(&_appstate), + ); + } + /* popup_window.connect_show */ { - let popup_window: gtk::Window = - appstate.builder_popup.get_object("popup_window").unwrap(); - let vol_scale_adj: gtk::Adjustment = - appstate.builder_popup.get_object("vol_scale_adj").unwrap(); - let mute_check: gtk::CheckButton = - appstate.builder_popup.get_object("mute_check").unwrap(); - let vol_scale: gtk::Scale = - appstate.builder_popup.get_object("vol_scale").unwrap(); - - let card = rc_acard.clone(); - popup_window.connect_show(move |w| { - let acard = card.borrow(); - - let cur_vol = try_w!(acard.vol()); - println!("Cur vol: {}", cur_vol); - set_slider(&vol_scale_adj, cur_vol); - - let muted = acard.get_mute(); - update_mute_check(&mute_check, muted); - - vol_scale.grab_focus(); - try_w!(grab_devices(w)); - }); + let _appstate = appstate.clone(); + let popup_window = &appstate.clone().gui.popup_window.window; + popup_window.connect_show( + move |w| on_popup_window_show(w, &_appstate, toggle_signal), + ); } /* vol_scale_adj.connect_value_changed */ { - let vol_scale_adj: Rc = - Rc::new(appstate.builder_popup - .get_object("vol_scale_adj") - .unwrap()); - - let card = rc_acard.clone(); - let vol_scale = vol_scale_adj.clone(); - vol_scale_adj.connect_value_changed(move |_| { - let acard = card.borrow(); - let val = vol_scale.get_value(); - - try_w!(acard.set_vol(val, AudioUserPopup)); - }); - } - - /* mute_check.connect_toggled */ - { - let mute_check: gtk::CheckButton = - appstate.builder_popup.get_object("mute_check").unwrap(); - - let card = rc_acard.clone(); - mute_check.connect_toggled(move |_| { - let acard = card.borrow(); - - let muted = try_w!(acard.get_mute()); - let _ = try_w!(acard.set_mute(!muted, AudioUserPopup)); - }); + let _appstate = appstate.clone(); + let vol_scale_adj = &appstate.clone().gui.popup_window.vol_scale_adj; + vol_scale_adj.connect_value_changed( + move |_| on_vol_scale_value_changed(&_appstate), + ); } /* popup_window.connect_event */ { - let popup_window: gtk::Window = - appstate.builder_popup.get_object("popup_window").unwrap(); + let _appstate = appstate.clone(); + let popup_window = &appstate.clone().gui.popup_window.window; popup_window.connect_event(move |w, e| { - match gdk::Event::get_event_type(e) { - gdk::EventType::GrabBroken => w.hide(), - gdk::EventType::KeyPress => { - let key: gdk::EventKey = e.clone().downcast().unwrap(); - if key.get_keyval() == (GDK_KEY_Escape as u32) { - w.hide(); - } - } - gdk::EventType::ButtonPress => { - let device = try_wr!( - gtk::get_current_event_device().ok_or( - "No current event device!", - ), - Inhibit(false) - ); - let (window, _, _) = - gdk::DeviceExt::get_window_at_position(&device); - if window.is_none() { - w.hide(); - } - } - _ => (), - } - - return Inhibit(false); + on_popup_window_event(w, e, &_appstate) }); } } -fn update_mute_check(check_button: >k::CheckButton, muted: Result) { +fn on_popup_window_show( + window: >k::Window, + appstate: &AppS, + toggle_signal: u64, +) { + let acard = appstate.acard.borrow(); + let popup_window = &appstate.gui.popup_window; + + let cur_vol = try_w!(acard.vol()); + println!("Cur vol: {}", cur_vol); + set_slider(&popup_window.vol_scale_adj, cur_vol); + + let muted = acard.get_mute(); + update_mute_check(&appstate, toggle_signal, muted); + + popup_window.vol_scale.grab_focus(); + // try_w!(grab_devices(window)); + + println!("Handler size in on_popup_window_show: {}", acard.handlers.borrow().capacity()); +} + + +fn on_popup_window_event( + w: >k::Window, + e: &gdk::Event, + appstate: &AppS, +) -> gtk::Inhibit { + match gdk::Event::get_event_type(e) { + gdk::EventType::GrabBroken => w.hide(), + gdk::EventType::KeyPress => { + let key: gdk::EventKey = e.clone().downcast().unwrap(); + if key.get_keyval() == (GDK_KEY_Escape as u32) { + w.hide(); + } + } + gdk::EventType::ButtonPress => { + let device = try_wr!( + gtk::get_current_event_device().ok_or( + "No current event device!", + ), + Inhibit(false) + ); + let (window, _, _) = + gdk::DeviceExt::get_window_at_position(&device); + if window.is_none() { + w.hide(); + } + } + _ => (), + } + + return Inhibit(false); +} + + +fn on_vol_scale_value_changed(appstate: &AppS) { + let acard = appstate.acard.borrow(); + + let val = appstate.gui.popup_window.vol_scale.get_value(); + + try_w!(acard.set_vol(val, AudioUserPopup)); +} + + +fn on_mute_check_toggled(appstate: &AppS) { + let acard = appstate.acard.borrow(); + + let muted = try_w!(acard.get_mute()); + let _ = try_w!(acard.set_mute(!muted, AudioUserPopup)); +} + + +fn update_mute_check(appstate: &AppS, toggle_signal: u64, muted: Result) { + let check_button = &appstate.gui.popup_window.mute_check; + // let check_button_ptr = unsafe { + // mem::transmute::<>k::CheckButton, &*mut gobject_sys::GObject>( + // check_button, + // ) + // }; + + // g_signal_handlers_block_matched() doesn't work in gtk-rs + glib::signal_handler_block(check_button, toggle_signal); + // let n_blocked = unsafe { + // gobject_sys::g_signal_handlers_block_matched( + // *check_button_ptr, + // G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA, + // toggle_signal as u32, + // 0, + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ) + // }; + + // if n_blocked != 1 { + // error!("Wrong number of blocked handlers: {}", n_blocked); + // } + match muted { Ok(val) => { check_button.set_active(val); @@ -120,6 +168,20 @@ fn update_mute_check(check_button: >k::CheckButton, muted: Result) { check_button.set_tooltip_text("Soundcard has no mute switch"); } } + + glib::signal_handler_unblock(check_button, toggle_signal); + + // unsafe { + // gobject_sys::g_signal_handlers_unblock_matched( + // *check_button_ptr, + // G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA, + // toggle_signal as u32, + // 0, + // ptr::null_mut(), + // ptr::null_mut(), + // ptr::null_mut(), + // ); + // } } @@ -134,32 +196,40 @@ fn grab_devices(window: >k::Window) -> Result<()> { let gdk_window = window.get_window().ok_or("No window?!")?; /* Grab the mouse */ - let m_grab_status = - device.grab(&gdk_window, - GrabOwnership::None, - true, - BUTTON_PRESS_MASK, - None, - GDK_CURRENT_TIME as u32); + let m_grab_status = device.grab( + &gdk_window, + GrabOwnership::None, + true, + BUTTON_PRESS_MASK, + None, + GDK_CURRENT_TIME as u32, + ); if m_grab_status != GrabStatus::Success { - warn!("Could not grab {}", - device.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))); + warn!( + "Could not grab {}", + device.get_name().unwrap_or(String::from("UNKNOWN DEVICE")) + ); } /* Grab the keyboard */ - let k_dev = device.get_associated_device() - .ok_or("Couldn't get associated device")?; + let k_dev = device.get_associated_device().ok_or( + "Couldn't get associated device", + )?; - let k_grab_status = k_dev.grab(&gdk_window, - GrabOwnership::None, - true, - KEY_PRESS_MASK, - None, - GDK_CURRENT_TIME as u32); + let k_grab_status = k_dev.grab( + &gdk_window, + GrabOwnership::None, + true, + KEY_PRESS_MASK, + None, + GDK_CURRENT_TIME as u32, + ); if k_grab_status != GrabStatus::Success { - warn!("Could not grab {}", - k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))); + warn!( + "Could not grab {}", + k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE")) + ); } return Ok(()); diff --git a/src/ui_tray_icon.rs b/src/ui_tray_icon.rs index 5f3d64b0e..c68e1fe82 100644 --- a/src/ui_tray_icon.rs +++ b/src/ui_tray_icon.rs @@ -1,20 +1,25 @@ use app_state::*; use gtk::prelude::*; -use gtk; +use std::rc::Rc; -pub fn init_tray_icon(appstate: &AppS) { +pub fn init_tray_icon(appstate: Rc) { - let ref tray_icon = appstate.status_icon; - - let popup_window: gtk::Window = - appstate.builder_popup.get_object("popup_window").unwrap(); - - tray_icon.connect_activate(move |_| if popup_window.get_visible() { - popup_window.hide(); - } else { - popup_window.show_now(); - }); + let tray_icon = &appstate.clone().gui.status_icon; + tray_icon.connect_activate( + move |_| on_tray_icon_activate(&appstate.clone()), + ); tray_icon.set_visible(true); } + + +fn on_tray_icon_activate(appstate: &AppS) { + let popup_window = &appstate.gui.popup_window.window; + + if popup_window.get_visible() { + popup_window.hide(); + } else { + popup_window.show_now(); + } +}