Update
This commit is contained in:
parent
a3355f3b72
commit
bdee2f4b1c
@ -1,6 +1,7 @@
|
|||||||
use gtk;
|
use gtk;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct AppS {
|
pub struct AppS {
|
||||||
/* we keep this to ensure the lifetime is across the whole application */
|
/* we keep this to ensure the lifetime is across the whole application */
|
||||||
pub status_icon: gtk::StatusIcon,
|
pub status_icon: gtk::StatusIcon,
|
||||||
|
25
src/audio.rs
25
src/audio.rs
@ -1,22 +1,19 @@
|
|||||||
use alsa::card::Card;
|
use alsa::card::Card;
|
||||||
use alsa::mixer::{Mixer, Selem, Elem, SelemId};
|
use alsa::mixer::{Mixer, Selem, SelemId};
|
||||||
use alsa::poll::PollDescriptors;
|
use alsa::poll::PollDescriptors;
|
||||||
use alsa_sys;
|
use alsa_sys;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
use glib_sys;
|
use glib_sys;
|
||||||
use libc::c_int;
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use libc::c_void;
|
|
||||||
use libc::pollfd;
|
use libc::pollfd;
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
use myalsa::*;
|
use myalsa::*;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::u8;
|
use std::u8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: implement free/destructor
|
// TODO: implement free/destructor
|
||||||
pub struct AlsaCard {
|
pub struct AlsaCard {
|
||||||
_cannot_construct: (),
|
_cannot_construct: (),
|
||||||
@ -26,6 +23,8 @@ pub struct AlsaCard {
|
|||||||
pub watch_ids: Vec<u32>,
|
pub watch_ids: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: AlsaCard cleanup */
|
||||||
impl AlsaCard {
|
impl AlsaCard {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
card_name: Option<String>,
|
card_name: Option<String>,
|
||||||
@ -58,36 +57,40 @@ impl AlsaCard {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn selem(&self) -> Selem {
|
pub fn selem(&self) -> Selem {
|
||||||
return get_selems(&self.mixer)
|
return get_selems(&self.mixer)
|
||||||
.nth(self.selem_id.get_index() as usize)
|
.nth(self.selem_id.get_index() as usize)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn vol(&self) -> Result<f64> {
|
pub fn vol(&self) -> Result<f64> {
|
||||||
return get_vol(&self.selem());
|
return get_vol(&self.selem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn set_vol(&self, new_vol: f64) -> Result<()> {
|
pub fn set_vol(&self, new_vol: f64) -> Result<()> {
|
||||||
return set_vol(&self.selem(), new_vol);
|
return set_vol(&self.selem(), new_vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn has_mute(&self) -> bool {
|
pub fn has_mute(&self) -> bool {
|
||||||
return has_mute(&self.selem());
|
return has_mute(&self.selem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_mute(&self) -> Result<bool> {
|
pub fn get_mute(&self) -> Result<bool> {
|
||||||
return get_mute(&self.selem());
|
return get_mute(&self.selem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn set_mute(&self, mute: bool) -> Result<()> {
|
pub fn set_mute(&self, mute: bool) -> Result<()> {
|
||||||
return set_mute(&self.selem(), mute);
|
return set_mute(&self.selem(), mute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub enum AudioUser {
|
pub enum AudioUser {
|
||||||
AudioUserUnknown,
|
AudioUserUnknown,
|
||||||
AudioUserPopup,
|
AudioUserPopup,
|
||||||
@ -95,6 +98,7 @@ pub enum AudioUser {
|
|||||||
AudioUserHotkeys,
|
AudioUserHotkeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum AudioSignal {
|
enum AudioSignal {
|
||||||
AudioNoCard,
|
AudioNoCard,
|
||||||
AudioCardInitialized,
|
AudioCardInitialized,
|
||||||
@ -105,10 +109,6 @@ enum AudioSignal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn watch_poll_descriptors(
|
fn watch_poll_descriptors(
|
||||||
polls: Vec<pollfd>,
|
polls: Vec<pollfd>,
|
||||||
mixer: &Mixer,
|
mixer: &Mixer,
|
||||||
@ -135,6 +135,7 @@ fn watch_poll_descriptors(
|
|||||||
return watch_ids;
|
return watch_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern fn watch_cb(
|
extern fn watch_cb(
|
||||||
chan: *mut glib_sys::GIOChannel,
|
chan: *mut glib_sys::GIOChannel,
|
||||||
cond: glib_sys::GIOCondition,
|
cond: glib_sys::GIOCondition,
|
||||||
|
56
src/gui.rs
56
src/gui.rs
@ -1,56 +0,0 @@
|
|||||||
use errors::*;
|
|
||||||
use gdk::DeviceExt;
|
|
||||||
use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK};
|
|
||||||
use gdk_sys::GDK_CURRENT_TIME;
|
|
||||||
use gtk::prelude::*;
|
|
||||||
use gtk;
|
|
||||||
|
|
||||||
|
|
||||||
pub fn set_slider(vol_scale_adj: >k::Adjustment, scale: f64) {
|
|
||||||
vol_scale_adj.set_value(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn grab_devices(window: >k::Window) -> Result<()> {
|
|
||||||
let device = gtk::get_current_event_device().ok_or("No current device")?;
|
|
||||||
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
|
|
||||||
if m_grab_status != GrabStatus::Success {
|
|
||||||
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_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"))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ extern crate gtk_sys;
|
|||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
use app_state::*;
|
use app_state::*;
|
||||||
use gtk::prelude::*;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -28,13 +27,15 @@ mod errors;
|
|||||||
|
|
||||||
mod app_state;
|
mod app_state;
|
||||||
mod audio;
|
mod audio;
|
||||||
mod gui;
|
|
||||||
mod gui_callbacks;
|
|
||||||
mod myalsa;
|
mod myalsa;
|
||||||
|
mod ui_entry;
|
||||||
|
mod ui_popup_window;
|
||||||
|
mod ui_tray_icon;
|
||||||
|
|
||||||
use audio::AlsaCard;
|
use audio::AlsaCard;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
gtk::init().unwrap();
|
gtk::init().unwrap();
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ fn main() {
|
|||||||
.init(Some("info".to_string()))
|
.init(Some("info".to_string()))
|
||||||
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
|
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
|
||||||
|
|
||||||
gui_callbacks::init(apps, acard);
|
ui_entry::init(apps, acard);
|
||||||
|
|
||||||
gtk::main();
|
gtk::main();
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,17 @@ pub fn get_default_alsa_card() -> Card {
|
|||||||
return get_alsa_card_by_id(0);
|
return get_alsa_card_by_id(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_alsa_card_by_id(index: c_int) -> Card {
|
pub fn get_alsa_card_by_id(index: c_int) -> Card {
|
||||||
return Card::new(index);
|
return Card::new(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_alsa_cards() -> alsa::card::Iter {
|
pub fn get_alsa_cards() -> alsa::card::Iter {
|
||||||
return alsa::card::Iter::new();
|
return alsa::card::Iter::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_alsa_card_by_name(name: String) -> Result<Card> {
|
pub fn get_alsa_card_by_name(name: String) -> Result<Card> {
|
||||||
for r_card in get_alsa_cards() {
|
for r_card in get_alsa_cards() {
|
||||||
let card = r_card?;
|
let card = r_card?;
|
||||||
@ -32,10 +35,12 @@ pub fn get_alsa_card_by_name(name: String) -> Result<Card> {
|
|||||||
bail!("Not found a matching card named {}", name);
|
bail!("Not found a matching card named {}", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_mixer(card: &Card) -> Result<Mixer> {
|
pub fn get_mixer(card: &Card) -> Result<Mixer> {
|
||||||
return Mixer::new(&format!("hw:{}", card.get_index()), false).cherr();
|
return Mixer::new(&format!("hw:{}", card.get_index()), false).cherr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_selem(elem: Elem) -> Selem {
|
pub fn get_selem(elem: Elem) -> Selem {
|
||||||
/* in the ALSA API, there are currently only simple elements,
|
/* in the ALSA API, there are currently only simple elements,
|
||||||
* so this unwrap() should be safe.
|
* so this unwrap() should be safe.
|
||||||
@ -43,10 +48,12 @@ pub fn get_selem(elem: Elem) -> Selem {
|
|||||||
return Selem::new(elem).unwrap();
|
return Selem::new(elem).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_selems(mixer: &Mixer) -> Map<alsa::mixer::Iter, fn(Elem) -> Selem> {
|
pub fn get_selems(mixer: &Mixer) -> Map<alsa::mixer::Iter, fn(Elem) -> Selem> {
|
||||||
return mixer.iter().map(get_selem);
|
return mixer.iter().map(get_selem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
||||||
for selem in get_selems(mixer) {
|
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))?;
|
||||||
@ -58,11 +65,13 @@ pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
|||||||
bail!("Not found a matching selem named {}", name);
|
bail!("Not found a matching selem named {}", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn vol_to_percent(vol: i64, range: (i64, i64)) -> f64 {
|
pub fn vol_to_percent(vol: i64, range: (i64, i64)) -> f64 {
|
||||||
let (min, max) = range;
|
let (min, max) = range;
|
||||||
return ((vol - min) as f64) / ((max - min) as f64) * 100.0;
|
return ((vol - min) as f64) / ((max - min) as f64) * 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn percent_to_vol(vol: f64, range: (i64, i64)) -> i64 {
|
pub fn percent_to_vol(vol: f64, range: (i64, i64)) -> i64 {
|
||||||
let (min, max) = range;
|
let (min, max) = range;
|
||||||
let _v = vol / 100.0 * ((max - min) as f64) + (min as f64);
|
let _v = vol / 100.0 * ((max - min) as f64) + (min as f64);
|
||||||
@ -70,6 +79,7 @@ pub fn percent_to_vol(vol: f64, range: (i64, i64)) -> i64 {
|
|||||||
return _v as i64;
|
return _v as i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_vol(selem: &Selem) -> Result<f64> {
|
pub fn get_vol(selem: &Selem) -> Result<f64> {
|
||||||
let range = selem.get_playback_volume_range();
|
let range = selem.get_playback_volume_range();
|
||||||
let volume = selem.get_playback_volume(FrontRight).map(|v| {
|
let volume = selem.get_playback_volume(FrontRight).map(|v| {
|
||||||
@ -79,6 +89,7 @@ pub fn get_vol(selem: &Selem) -> Result<f64> {
|
|||||||
return volume.cherr();
|
return volume.cherr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn set_vol(selem: &Selem, new_vol: f64) -> Result<()> {
|
pub fn set_vol(selem: &Selem, new_vol: f64) -> Result<()> {
|
||||||
/* auto-unmute */
|
/* auto-unmute */
|
||||||
if get_mute(selem)? {
|
if get_mute(selem)? {
|
||||||
@ -93,19 +104,21 @@ pub fn set_vol(selem: &Selem, new_vol: f64) -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn has_mute(selem: &Selem) -> bool {
|
pub fn has_mute(selem: &Selem) -> bool {
|
||||||
return selem.has_playback_switch();
|
return selem.has_playback_switch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_mute(selem: &Selem) -> Result<bool> {
|
pub fn get_mute(selem: &Selem) -> Result<bool> {
|
||||||
let val = selem.get_playback_switch(FrontRight)?;
|
let val = selem.get_playback_switch(FrontRight)?;
|
||||||
return Ok(val == 0);
|
return Ok(val == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn set_mute(selem: &Selem, mute: bool) -> Result<()> {
|
pub fn set_mute(selem: &Selem, mute: bool) -> Result<()> {
|
||||||
/* true -> mute, false -> unmute */
|
/* true -> mute, false -> unmute */
|
||||||
let _ = selem.set_playback_switch_all(!mute as i32)?;
|
let _ = selem.set_playback_switch_all(!mute as i32)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
15
src/ui_entry.rs
Normal file
15
src/ui_entry.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use app_state::*;
|
||||||
|
use audio::AlsaCard;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use ui_popup_window::*;
|
||||||
|
use ui_tray_icon::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn init<'a>(appstate: &'a AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
||||||
|
|
||||||
|
init_tray_icon(&appstate);
|
||||||
|
init_popup_window(&appstate, rc_acard);
|
||||||
|
}
|
||||||
|
|
@ -1,42 +1,18 @@
|
|||||||
use app_state::*;
|
use app_state::*;
|
||||||
use audio::AlsaCard;
|
use audio::AlsaCard;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
use gdk::DeviceExt;
|
||||||
|
use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK};
|
||||||
use gdk;
|
use gdk;
|
||||||
use gdk_sys::GDK_KEY_Escape;
|
use gdk_sys::{GDK_KEY_Escape, GDK_CURRENT_TIME};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk;
|
use gtk;
|
||||||
use gui;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
|
||||||
pub fn init<'a>(appstate: &'a AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
|
||||||
|
|
||||||
init_tray_icon(&appstate);
|
pub fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
||||||
init_popup_window(&appstate, rc_acard);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn init_tray_icon(appstate: &AppS) {
|
|
||||||
|
|
||||||
let ref tray_icon = appstate.status_icon;
|
|
||||||
|
|
||||||
let popup_window: gtk::Window =
|
|
||||||
appstate.builder_popup.get_object("popup_window").unwrap();
|
|
||||||
let vol_scale: gtk::Scale =
|
|
||||||
appstate.builder_popup.get_object("vol_scale").unwrap();
|
|
||||||
|
|
||||||
tray_icon.connect_activate(move |_| if popup_window.get_visible() {
|
|
||||||
popup_window.hide();
|
|
||||||
} else {
|
|
||||||
popup_window.show_now();
|
|
||||||
vol_scale.grab_focus();
|
|
||||||
try_w!(gui::grab_devices(&popup_window));
|
|
||||||
});
|
|
||||||
tray_icon.set_visible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
|
||||||
/* popup_window.connect_show */
|
/* popup_window.connect_show */
|
||||||
{
|
{
|
||||||
let popup_window: gtk::Window =
|
let popup_window: gtk::Window =
|
||||||
@ -45,17 +21,22 @@ fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
|||||||
appstate.builder_popup.get_object("vol_scale_adj").unwrap();
|
appstate.builder_popup.get_object("vol_scale_adj").unwrap();
|
||||||
let mute_check: gtk::CheckButton =
|
let mute_check: gtk::CheckButton =
|
||||||
appstate.builder_popup.get_object("mute_check").unwrap();
|
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();
|
let card = rc_acard.clone();
|
||||||
popup_window.connect_show(move |_| {
|
popup_window.connect_show(move |w| {
|
||||||
let acard = card.borrow();
|
let acard = card.borrow();
|
||||||
|
|
||||||
let cur_vol = try_w!(acard.vol());
|
let cur_vol = try_w!(acard.vol());
|
||||||
println!("Cur vol: {}", cur_vol);
|
println!("Cur vol: {}", cur_vol);
|
||||||
gui::set_slider(&vol_scale_adj, cur_vol);
|
set_slider(&vol_scale_adj, cur_vol);
|
||||||
|
|
||||||
let muted = acard.get_mute();
|
let muted = acard.get_mute();
|
||||||
update_mute_check(&mute_check, muted);
|
update_mute_check(&mute_check, muted);
|
||||||
|
|
||||||
|
vol_scale.grab_focus();
|
||||||
|
try_w!(grab_devices(w));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +105,7 @@ fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn update_mute_check(check_button: >k::CheckButton, muted: Result<bool>) {
|
fn update_mute_check(check_button: >k::CheckButton, muted: Result<bool>) {
|
||||||
match muted {
|
match muted {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
@ -138,3 +120,55 @@ fn update_mute_check(check_button: >k::CheckButton, muted: Result<bool>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn set_slider(vol_scale_adj: >k::Adjustment, scale: f64) {
|
||||||
|
vol_scale_adj.set_value(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn grab_devices(window: >k::Window) -> Result<()> {
|
||||||
|
let device = gtk::get_current_event_device().ok_or("No current device")?;
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
|
||||||
|
if m_grab_status != GrabStatus::Success {
|
||||||
|
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_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"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
21
src/ui_tray_icon.rs
Normal file
21
src/ui_tray_icon.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use app_state::*;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn init_tray_icon(appstate: &AppS) {
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
tray_icon.set_visible(true);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user