From ff1cf0cd3c59d0de2e7ad799d95f040bb52772dc Mon Sep 17 00:00:00 2001 From: unsecretised Date: Sun, 29 Mar 2026 17:36:21 +0800 Subject: [PATCH 1/2] Switch to NSEvent handling for hotkeys --- src/app.rs | 3 +- src/app/menubar.rs | 34 ++--- src/app/pages/settings.rs | 4 +- src/app/tile.rs | 32 +--- src/app/tile/elm.rs | 23 +-- src/app/tile/update.rs | 49 ++++++- src/main.rs | 39 ++--- src/platform/macos/launching.rs | 250 ++++++++++++++++++++++++++++++++ src/platform/macos/mod.rs | 1 + 9 files changed, 339 insertions(+), 96 deletions(-) create mode 100644 src/platform/macos/launching.rs diff --git a/src/app.rs b/src/app.rs index 2be7378..68b19e4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,6 +5,7 @@ use crate::app::apps::{App, AppCommand, ICNS_ICON}; use crate::commands::Function; use crate::config::{Config, MainPage, Shelly}; use crate::debounce::DebouncePolicy; +use crate::platform::macos::launching::Shortcut; use crate::utils::icns_data_to_handle; use crate::{app::tile::ExtSender, clipboard::ClipBoardContentType}; use iced::time::Duration; @@ -90,7 +91,7 @@ pub enum Message { OpenResult(u32), OpenToSettings, SearchQueryChanged(String, Id), - KeyPressed(u32), + KeyPressed(Shortcut), FocusTextInput(Move), HideWindow(Id), RunFunction(Function), diff --git a/src/app/menubar.rs b/src/app/menubar.rs index b9a566f..817a6e1 100644 --- a/src/app/menubar.rs +++ b/src/app/menubar.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, io::Cursor}; -use global_hotkey::hotkey::{Code, HotKey, Modifiers}; +use global_hotkey::hotkey::{Code, Modifiers}; use image::{DynamicImage, ImageReader}; use log::info; use tray_icon::{ @@ -16,6 +16,7 @@ use tray_icon::{ use crate::{ app::{Message, tile::ExtSender}, config::Config, + platform::macos::launching::Shortcut, utils::open_url, }; @@ -39,14 +40,15 @@ pub fn menu_icon(config: Config, sender: ExtSender) -> TrayIcon { } pub fn menu_builder(config: Config, sender: ExtSender, update_item: bool) -> Menu { - let hotkey = config.toggle_hotkey.parse::().ok(); + let shortcut = + Shortcut::parse(&config.toggle_hotkey).unwrap_or(Shortcut::parse("opt+space").unwrap()); let mut modes = config.modes; if !modes.contains_key("default") { modes.insert("Default".to_string(), "default".to_string()); } - init_event_handler(sender, hotkey.map(|x| x.id)); + init_event_handler(sender, shortcut); Menu::with_items(&[ &MenuItem::with_id( @@ -64,7 +66,7 @@ pub fn menu_builder(config: Config, sender: ExtSender, update_item: bool) -> Men &open_github_item(), &PredefinedMenuItem::separator(), &refresh_item(), - &open_item(hotkey), + &open_item(), &mode_item(modes), &PredefinedMenuItem::separator(), &open_issue_item(), @@ -86,10 +88,12 @@ fn get_image() -> DynamicImage { .unwrap() } -fn init_event_handler(sender: ExtSender, hotkey_id: Option) { +fn init_event_handler(sender: ExtSender, shortcut: Shortcut) { let runtime = Runtime::new().unwrap(); + let shortcut = shortcut.clone(); MenuEvent::set_event_handler(Some(move |x: MenuEvent| { + let shortcut = shortcut.clone(); let sender = sender.clone(); let sender = sender.0.clone(); info!("Menubar event called: {}", x.id.0); @@ -107,11 +111,12 @@ fn init_event_handler(sender: ExtSender, hotkey_id: Option) { open_url("https://github.com/RustCastLabs/rustcast/issues/new"); } "show_rustcast" => { - if let Some(hk) = hotkey_id { - runtime.spawn(async move { - sender.clone().try_send(Message::KeyPressed(hk)).unwrap(); - }); - } + runtime.spawn(async move { + sender + .clone() + .try_send(Message::KeyPressed(shortcut.clone())) + .unwrap(); + }); } "update" => { open_url("https://github.com/RustCastLabs/rustcast/releases/latest"); @@ -178,13 +183,8 @@ fn mode_item(modes: HashMap) -> Submenu { Submenu::with_items("Modes", true, &items).unwrap() } -fn open_item(hotkey: Option) -> MenuItem { - MenuItem::with_id( - "show_rustcast", - "Toggle View", - true, - hotkey.map(|hk| Accelerator::new(Some(hk.mods), hk.key)), - ) +fn open_item() -> MenuItem { + MenuItem::with_id("show_rustcast", "Toggle View", true, None) } fn open_github_item() -> MenuItem { diff --git a/src/app/pages/settings.rs b/src/app/pages/settings.rs index 6a20ab0..2c59db1 100644 --- a/src/app/pages/settings.rs +++ b/src/app/pages/settings.rs @@ -44,7 +44,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> { .width(Length::Fill) .style(move |_, _| settings_text_input_item_style(&hotkey_theme)) .into(), - notice_item(theme.clone(), "Requires a restart"), + notice_item(theme.clone(), "Use \"+\" as a seperator"), ]); let cb_theme = theme.clone(); @@ -56,7 +56,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> { .width(Length::Fill) .style(move |_, _| settings_text_input_item_style(&cb_theme)) .into(), - notice_item(theme.clone(), "Requires a restart"), + notice_item(theme.clone(), "Use \"+\" as a seperator"), ]); let placeholder_theme = theme.clone(); diff --git a/src/app/tile.rs b/src/app/tile.rs index f842a1c..a3c7b96 100644 --- a/src/app/tile.rs +++ b/src/app/tile.rs @@ -5,13 +5,12 @@ pub mod update; use crate::app::apps::App; use crate::app::{ArrowKey, Message, Move, Page}; use crate::clipboard::ClipBoardContentType; -use crate::config::Config; +use crate::config::{Config, Shelly}; use crate::debounce::Debouncer; use crate::platform::default_app_paths; +use crate::platform::macos::launching::Shortcut; use arboard::Clipboard; -use global_hotkey::hotkey::HotKey; -use global_hotkey::{GlobalHotKeyEvent, HotKeyState}; use iced::futures::SinkExt; use iced::futures::channel::mpsc::{Sender, channel}; @@ -190,9 +189,9 @@ pub struct Tile { /// Stores the toggle [`HotKey`] and the Clipboard [`HotKey`] #[derive(Clone, Debug)] pub struct Hotkeys { - pub toggle: HotKey, - pub clipboard_hotkey: HotKey, - pub shells: HashMap, + pub toggle: Shortcut, + pub clipboard_hotkey: Shortcut, + pub shells: HashMap, } impl Tile { @@ -229,7 +228,6 @@ impl Tile { _ => None, }); Subscription::batch([ - Subscription::run(handle_hotkeys), Subscription::run(handle_hot_reloading), keyboard, Subscription::run(handle_recipient), @@ -269,9 +267,8 @@ impl Tile { keyboard::Key::Named(Named::Backspace) => { return Some(Message::FocusTextInput(Move::Back)); } - _ => {} + _ => None, } - None } else { None } @@ -337,22 +334,6 @@ impl Tile { } } -/// This is the subscription function that handles hotkeys, e.g. for hiding / showing the window -fn handle_hotkeys() -> impl futures::Stream { - stream::channel(100, async |mut output| { - let receiver = GlobalHotKeyEvent::receiver(); - loop { - info!("Hotkey received"); - if let Ok(event) = receiver.recv() - && event.state == HotKeyState::Pressed - { - output.try_send(Message::KeyPressed(event.id)).unwrap(); - } - tokio::time::sleep(Duration::from_millis(100)).await; - } - }) -} - /// This is the subscription function that handles the change in clipboard history fn handle_clipboard_history() -> impl futures::Stream { stream::channel(100, async |mut output| { @@ -602,7 +583,6 @@ fn handle_recipient() -> impl futures::Stream { let abcd = recipient .try_recv() .map(async |msg| { - info!("Sending a message"); output.send(msg).await.unwrap(); }) .ok(); diff --git a/src/app/tile/elm.rs b/src/app/tile/elm.rs index 03eca1d..87fadf9 100644 --- a/src/app/tile/elm.rs +++ b/src/app/tile/elm.rs @@ -4,7 +4,6 @@ use std::collections::HashMap; use std::fs; -use global_hotkey::hotkey::HotKey; use iced::border::Radius; use iced::widget::scrollable::{Anchor, Direction, Scrollbar}; use iced::widget::text::LineHeight; @@ -35,7 +34,7 @@ use crate::{ }; /// Initialise the base window -pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { +pub fn new(hotkeys: Hotkeys, config: &Config) -> (Tile, Task) { let (id, open) = window::open(default_settings()); info!("Opening window"); @@ -60,24 +59,6 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { options.par_sort_by_key(|x| x.display_name.len()); let options = AppIndex::from_apps(options); - let mut shells_map = HashMap::new(); - for shell in &config.shells { - if let Some(hk_str) = &shell.hotkey - && let Ok(hk) = hk_str.parse::() - { - shells_map.insert(hk.id, shell.command.clone()); - } - } - - let hotkeys = Hotkeys { - toggle: hotkey, - clipboard_hotkey: config - .clipboard_hotkey - .parse() - .unwrap_or("SUPER+SHIFT+C".parse().unwrap()), - shells: shells_map, - }; - let home = std::env::var("HOME").unwrap_or("/".to_string()); let ranking = toml::from_str( @@ -94,8 +75,8 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { focus_id: 0, results: vec![], options, - emoji_apps: AppIndex::from_apps(App::emoji_apps()), hotkeys, + emoji_apps: AppIndex::from_apps(App::emoji_apps()), visible: true, frontmost: None, focused: false, diff --git a/src/app/tile/update.rs b/src/app/tile/update.rs index 4bca040..356e0ea 100644 --- a/src/app/tile/update.rs +++ b/src/app/tile/update.rs @@ -1,5 +1,6 @@ //! This handles the update logic for the tile (AKA rustcast's main window) use std::cmp::min; +use std::collections::HashMap; use std::fs; use std::io::Cursor; use std::thread; @@ -34,6 +35,8 @@ use crate::commands::Function; use crate::config::Config; use crate::config::MainPage; use crate::debounce::DebouncePolicy; +use crate::platform::macos::launching::Shortcut; +use crate::platform::macos::launching::global_handler; use crate::platform::macos::{start_at_login, stop_at_login}; use crate::quit::get_open_apps; use crate::unit_conversion; @@ -91,6 +94,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { Message::SetSender(sender) => { tile.sender = Some(sender.clone()); + global_handler(sender.clone()); if tile.config.show_trayicon { tile.tray_icon = Some(menu_icon(tile.config.clone(), sender)); } @@ -274,6 +278,24 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { Err(_) => return Task::none(), }; + if let Some(hotkey) = Shortcut::parse(&new_config.clipboard_hotkey).ok() { + tile.hotkeys.clipboard_hotkey = hotkey + } + + if let Some(hotkey) = Shortcut::parse(&new_config.toggle_hotkey).ok() { + tile.hotkeys.toggle = hotkey + } + + let mut shell_map = HashMap::new(); + + for shell in &new_config.shells { + if let Some(hotkey) = shell.hotkey.clone().and_then(|x| Shortcut::parse(&x).ok()) { + shell_map.insert(hotkey, shell.clone()); + } + } + + tile.hotkeys.shells = shell_map; + let update_apps_task = if tile.config.shells != new_config.shells { info!("App Update required"); Task::done(Message::UpdateApps) @@ -303,17 +325,20 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { Task::batch([Task::done(Message::LoadRanking), update_apps_task]) } - Message::KeyPressed(hk_id) => { - if let Some(cmd) = tile.hotkeys.shells.get(&hk_id) { - return Task::done(Message::RunFunction(Function::RunShellCommand(cmd.clone()))); + Message::KeyPressed(shortcut) => { + if let Some(cmd) = tile.hotkeys.shells.get(&shortcut) { + return Task::done(Message::RunFunction(Function::RunShellCommand( + cmd.command.clone(), + ))); } - - let is_clipboard_hotkey = tile.hotkeys.clipboard_hotkey.id == hk_id; - let is_open_hotkey = hk_id == tile.hotkeys.toggle.id; + let is_clipboard_hotkey = shortcut == tile.hotkeys.clipboard_hotkey; + let is_open_hotkey = shortcut == tile.hotkeys.toggle; let clipboard_page_task = if is_clipboard_hotkey { + info!("Switching to clipboard page"); Task::done(Message::SwitchToPage(Page::ClipboardHistory)) } else if is_open_hotkey { + info!("Switching to main page"); Task::done(Message::SwitchToPage(Page::Main)) } else { Task::none() @@ -485,6 +510,18 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { new_options.par_sort_by_key(|x| x.display_name.len()); tile.options = AppIndex::from_apps(new_options); + let mut shell_map = HashMap::new(); + + for shell in &tile.config.shells { + if let Some(has_hk) = &shell.hotkey + && let Some(hotkey) = Shortcut::parse(has_hk).ok() + { + shell_map.insert(hotkey, shell.clone()); + } + } + + tile.hotkeys.shells = shell_map; + Task::none() } diff --git a/src/main.rs b/src/main.rs index 6b06a7c..82c8863 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,18 +12,14 @@ mod styles; mod unit_conversion; mod utils; -use std::{fs::OpenOptions, path::Path}; +use std::{collections::HashMap, fs::OpenOptions, path::Path}; use crate::{ - app::tile::{self, Tile}, + app::tile::{self, Hotkeys, Tile}, config::Config, - platform::macos::get_autostart_status, + platform::macos::{get_autostart_status, launching::Shortcut}, }; -use global_hotkey::{ - GlobalHotKeyManager, - hotkey::{Code, HotKey, Modifiers}, -}; use log::info; use tracing_subscriber::{EnvFilter, Layer, util::SubscriberInitExt}; @@ -67,36 +63,33 @@ fn main() -> iced::Result { info!("Config loaded"); - let manager = GlobalHotKeyManager::new().unwrap(); + let show_hide = + Shortcut::parse(&config.toggle_hotkey).unwrap_or(Shortcut::parse("option+space").unwrap()); - let show_hide = config - .toggle_hotkey - .parse() - .unwrap_or(HotKey::new(Some(Modifiers::ALT), Code::Space)); + let cbhist = Shortcut::parse(&config.clipboard_hotkey.to_lowercase()) + .unwrap_or_else(|_| Shortcut::parse("cmd+shift+c").unwrap()); - let cbhist = config - .clipboard_hotkey - .parse() - .unwrap_or("SUPER+SHIFT+C".parse().unwrap()); + let mut shell_map = HashMap::new(); - let mut hotkeys = vec![show_hide, cbhist]; for shell in &config.shells { if let Some(hk_str) = &shell.hotkey - && let Ok(hk) = hk_str.parse::() + && let Ok(hk) = Shortcut::parse(hk_str) { - hotkeys.push(hk); + shell_map.insert(hk, shell.clone()); } } - manager - .register_all(&hotkeys) - .expect("Unable to register hotkeys"); + let hotkeys = Hotkeys { + toggle: show_hide, + clipboard_hotkey: cbhist, + shells: shell_map, + }; info!("Hotkeys loaded"); info!("Starting rustcast"); iced::daemon( - move || tile::elm::new(show_hide, &config), + move || tile::elm::new(hotkeys.clone(), &config), tile::update::handle_update, tile::elm::view, ) diff --git a/src/platform/macos/launching.rs b/src/platform/macos/launching.rs new file mode 100644 index 0000000..fd8c55b --- /dev/null +++ b/src/platform/macos/launching.rs @@ -0,0 +1,250 @@ +use std::sync::{Arc, Mutex}; + +use block2::RcBlock; +use objc2_app_kit::{NSEvent, NSEventMask, NSEventModifierFlags, NSEventType}; + +use crate::app::{Message, tile::ExtSender}; + +pub fn global_handler(sender: ExtSender) { + local_handler(sender.clone()); + let mask = NSEventMask::KeyDown | NSEventMask::FlagsChanged; + let sender = Arc::new(Mutex::new(sender.0.clone())); + + let block = RcBlock::new({ + move |event: std::ptr::NonNull| { + let event = unsafe { event.as_ref() }; + let event_type = event.r#type(); + + let key_code = event.keyCode(); + let mods = event.modifierFlags() + & (NSEventModifierFlags::Command + | NSEventModifierFlags::Option + | NSEventModifierFlags::Control + | NSEventModifierFlags::Function + | NSEventModifierFlags::CapsLock + | NSEventModifierFlags::Shift); + + let shortcut = match event_type { + NSEventType::KeyDown => Shortcut { + key_code: Some(key_code), + mods: if mods.0 != 0 { + Some(mods.0 as usize) + } else { + None + }, + }, + NSEventType::FlagsChanged => Shortcut { + key_code: None, + mods: if mods.0 != 0 { + Some(mods.0 as usize) + } else { + None + }, + }, + _ => return, + }; + + let mut s = sender.lock().unwrap(); + let _ = s.try_send(Message::KeyPressed(shortcut)); + } + }); + + NSEvent::addGlobalMonitorForEventsMatchingMask_handler(mask, &block); +} + +pub fn local_handler(sender: ExtSender) { + let mask = NSEventMask::KeyDown | NSEventMask::FlagsChanged; + let sender = Arc::new(Mutex::new(sender.0.clone())); + + let block = RcBlock::new({ + move |event: std::ptr::NonNull| -> *mut NSEvent { + let event_ref = unsafe { event.as_ref() }; + let event_type = event_ref.r#type(); + + let key_code = event_ref.keyCode(); + let mods = event_ref.modifierFlags() + & (NSEventModifierFlags::Command + | NSEventModifierFlags::Option + | NSEventModifierFlags::Control + | NSEventModifierFlags::Function + | NSEventModifierFlags::CapsLock + | NSEventModifierFlags::Shift); + + let shortcut = match event_type { + NSEventType::KeyDown => Shortcut { + key_code: Some(key_code), + mods: if mods.0 != 0 { + Some(mods.0 as usize) + } else { + None + }, + }, + NSEventType::FlagsChanged => Shortcut { + key_code: None, + mods: if mods.0 != 0 { + Some(mods.0 as usize) + } else { + None + }, + }, + _ => return event.as_ptr(), // pass through unhandled events + }; + + let mut s = sender.lock().unwrap(); + let _ = s.try_send(Message::KeyPressed(shortcut)); + + event.as_ptr() + } + }); + + unsafe { + NSEvent::addLocalMonitorForEventsMatchingMask_handler(mask, &block); + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Shortcut { + pub key_code: Option, + pub mods: Option, +} + +impl Shortcut { + pub fn new(key_code: Option, mods: Option) -> Self { + Self { key_code, mods } + } + + pub fn parse(s: &str) -> Result { + let parts: Vec<&str> = s.split('+').map(|p| p.trim()).collect(); + + let mut mods: usize = 0; + let mut key_code: Option = None; + let mut has_mods = false; + + for part in &parts { + match part.to_lowercase().as_str() { + "cmd" | "command" | "super" => { + mods |= NSEventModifierFlags::Command.0; + has_mods = true; + } + "opt" | "option" | "alt" => { + mods |= NSEventModifierFlags::Option.0; + has_mods = true; + } + "capslock" | "caps" | "caps lock" => mods |= NSEventModifierFlags::CapsLock.0, + "ctrl" | "control" => { + mods |= NSEventModifierFlags::Control.0; + has_mods = true; + } + "shift" => { + mods |= NSEventModifierFlags::Shift.0; + has_mods = true; + } + "fn" | "function" => { + mods |= NSEventModifierFlags::Function.0; + has_mods = true; + } + key => { + if key_code.is_some() { + return Err(format!("Multiple keys specified: '{}'", s)); + } + key_code = Some(str_to_keycode(key)?); + } + } + } + + Ok(Shortcut::new( + key_code, + if has_mods { Some(mods) } else { None }, + )) + } +} + +fn str_to_keycode(s: &str) -> Result { + let code = match s.to_lowercase().as_str() { + // Letters + "a" => 0x00, + "s" => 0x01, + "d" => 0x02, + "f" => 0x03, + "h" => 0x04, + "g" => 0x05, + "z" => 0x06, + "x" => 0x07, + "c" => 0x08, + "v" => 0x09, + "b" => 0x0b, + "q" => 0x0c, + "w" => 0x0d, + "e" => 0x0e, + "r" => 0x0f, + "y" => 0x10, + "t" => 0x11, + "o" => 0x1f, + "u" => 0x20, + "i" => 0x22, + "p" => 0x23, + "l" => 0x25, + "j" => 0x26, + "k" => 0x28, + "n" => 0x2d, + "m" => 0x2e, + + // Numbers + "1" => 0x12, + "2" => 0x13, + "3" => 0x14, + "4" => 0x15, + "5" => 0x17, + "6" => 0x16, + "7" => 0x1a, + "8" => 0x1c, + "9" => 0x19, + "0" => 0x1d, + + // Special keys + "return" | "enter" => 0x24, + "tab" => 0x30, + "space" => 0x31, + "delete" | "backspace" => 0x33, + "escape" | "esc" => 0x35, + "left" | "arrowleft" => 0x7b, + "right" | "arrowright" => 0x7c, + "down" | "arrowdown" => 0x7d, + "up" | "arrowup" => 0x7e, + "home" => 0x73, + "end" => 0x77, + "pageup" => 0x74, + "pagedown" => 0x79, + + // Function keys + "f1" => 0x7a, + "f2" => 0x78, + "f3" => 0x63, + "f4" => 0x76, + "f5" => 0x60, + "f6" => 0x61, + "f7" => 0x62, + "f8" => 0x64, + "f9" => 0x65, + "f10" => 0x6d, + "f11" => 0x67, + "f12" => 0x6f, + + // Symbols + "-" | "minus" => 0x1b, + "=" | "equal" => 0x18, + "[" | "bracketleft" => 0x21, + "]" | "bracketright" => 0x1e, + "\\" | "backslash" => 0x2a, + ";" | "semicolon" => 0x29, + "'" | "quote" => 0x27, + "`" | "backquote" | "grave" => 0x32, + "," | "comma" => 0x2b, + "." | "period" => 0x2f, + "/" | "slash" => 0x2c, + + _ => return Err(format!("Unknown key: '{}'", s)), + }; + + Ok(code) +} diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index ab7c05c..eeab128 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -1,6 +1,7 @@ //! Macos specific logic, such as window settings, etc. pub mod discovery; pub mod haptics; +pub mod launching; use iced::wgpu::rwh::WindowHandle; From 66cb6c70825a8e0b74701b95550dc7668a569e9f Mon Sep 17 00:00:00 2001 From: unsecretised Date: Sun, 29 Mar 2026 17:36:55 +0800 Subject: [PATCH 2/2] clippy & format -_- --- src/app/tile.rs | 22 ++++++++++------------ src/app/tile/update.rs | 4 ++-- src/platform/macos/launching.rs | 24 ++++-------------------- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/src/app/tile.rs b/src/app/tile.rs index a3c7b96..02e029a 100644 --- a/src/app/tile.rs +++ b/src/app/tile.rs @@ -239,33 +239,31 @@ impl Tile { if let keyboard::Event::KeyPressed { key, modifiers, .. } = event { match key { keyboard::Key::Named(Named::ArrowUp) => { - return Some(Message::ChangeFocus(ArrowKey::Up, 1)); + Some(Message::ChangeFocus(ArrowKey::Up, 1)) } keyboard::Key::Named(Named::ArrowLeft) => { - return Some(Message::ChangeFocus(ArrowKey::Left, 1)); + Some(Message::ChangeFocus(ArrowKey::Left, 1)) } keyboard::Key::Named(Named::ArrowRight) => { - return Some(Message::ChangeFocus(ArrowKey::Right, 1)); + Some(Message::ChangeFocus(ArrowKey::Right, 1)) } keyboard::Key::Named(Named::ArrowDown) => { - return Some(Message::ChangeFocus(ArrowKey::Down, 1)); + Some(Message::ChangeFocus(ArrowKey::Down, 1)) } keyboard::Key::Character(chr) => { if modifiers.command() && chr.to_string() == "r" { - return Some(Message::ReloadConfig); + Some(Message::ReloadConfig) } else if chr.to_string() == "p" && modifiers.control() { - return Some(Message::ChangeFocus(ArrowKey::Up, 1)); + Some(Message::ChangeFocus(ArrowKey::Up, 1)) } else if chr.to_string() == "n" && modifiers.control() { - return Some(Message::ChangeFocus(ArrowKey::Down, 1)); + Some(Message::ChangeFocus(ArrowKey::Down, 1)) } else { - return Some(Message::FocusTextInput(Move::Forwards( - chr.to_string(), - ))); + Some(Message::FocusTextInput(Move::Forwards(chr.to_string()))) } } - keyboard::Key::Named(Named::Enter) => return Some(Message::OpenFocused), + keyboard::Key::Named(Named::Enter) => Some(Message::OpenFocused), keyboard::Key::Named(Named::Backspace) => { - return Some(Message::FocusTextInput(Move::Back)); + Some(Message::FocusTextInput(Move::Back)) } _ => None, } diff --git a/src/app/tile/update.rs b/src/app/tile/update.rs index 356e0ea..9ae7951 100644 --- a/src/app/tile/update.rs +++ b/src/app/tile/update.rs @@ -278,11 +278,11 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { Err(_) => return Task::none(), }; - if let Some(hotkey) = Shortcut::parse(&new_config.clipboard_hotkey).ok() { + if let Ok(hotkey) = Shortcut::parse(&new_config.clipboard_hotkey) { tile.hotkeys.clipboard_hotkey = hotkey } - if let Some(hotkey) = Shortcut::parse(&new_config.toggle_hotkey).ok() { + if let Ok(hotkey) = Shortcut::parse(&new_config.toggle_hotkey) { tile.hotkeys.toggle = hotkey } diff --git a/src/platform/macos/launching.rs b/src/platform/macos/launching.rs index fd8c55b..5ef49b4 100644 --- a/src/platform/macos/launching.rs +++ b/src/platform/macos/launching.rs @@ -27,19 +27,11 @@ pub fn global_handler(sender: ExtSender) { let shortcut = match event_type { NSEventType::KeyDown => Shortcut { key_code: Some(key_code), - mods: if mods.0 != 0 { - Some(mods.0 as usize) - } else { - None - }, + mods: if mods.0 != 0 { Some(mods.0) } else { None }, }, NSEventType::FlagsChanged => Shortcut { key_code: None, - mods: if mods.0 != 0 { - Some(mods.0 as usize) - } else { - None - }, + mods: if mods.0 != 0 { Some(mods.0) } else { None }, }, _ => return, }; @@ -73,19 +65,11 @@ pub fn local_handler(sender: ExtSender) { let shortcut = match event_type { NSEventType::KeyDown => Shortcut { key_code: Some(key_code), - mods: if mods.0 != 0 { - Some(mods.0 as usize) - } else { - None - }, + mods: if mods.0 != 0 { Some(mods.0) } else { None }, }, NSEventType::FlagsChanged => Shortcut { key_code: None, - mods: if mods.0 != 0 { - Some(mods.0 as usize) - } else { - None - }, + mods: if mods.0 != 0 { Some(mods.0) } else { None }, }, _ => return event.as_ptr(), // pass through unhandled events };