Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 5 additions & 18 deletions src/global_hotkey.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#[cfg(target_os = "windows")]
use crate::workspace::is_valid_key_combo;
#[cfg(target_os = "windows")]
use log::{error, info, warn};
use serde::{Deserialize, Serialize};
use std::fmt;
#[cfg(target_os = "windows")]
use windows::Win32::UI::Input::KeyboardAndMouse::{
RegisterHotKey, UnregisterHotKey, HOT_KEY_MODIFIERS, MOD_CONTROL, MOD_ALT,
MOD_SHIFT, MOD_WIN,
RegisterHotKey, HOT_KEY_MODIFIERS, MOD_CONTROL, MOD_ALT, MOD_SHIFT, MOD_WIN,
};

#[derive(Clone, Serialize, Deserialize)]
pub struct Hotkey {
pub key_sequence: String,
#[cfg(target_os = "windows")]
#[serde(skip)]
pub id: Option<i32>,
}
Expand All @@ -22,6 +24,7 @@ impl fmt::Display for Hotkey {
}

impl Hotkey {
#[cfg(target_os = "windows")]
pub fn new(key_sequence: &str) -> Result<Self, String> {
if is_valid_key_combo(key_sequence) {
Ok(Self {
Expand Down Expand Up @@ -68,21 +71,5 @@ impl Hotkey {
}


#[cfg(target_os = "windows")]
pub fn unregister(&self, app: &crate::gui::LauncherApp) -> bool {
if let Some(id) = self.id {
unsafe {
if UnregisterHotKey(None, id).is_ok() {
let mut registered_hotkeys = app.registered_hotkeys.lock().unwrap();
registered_hotkeys.remove(&self.key_sequence);
info!("Unregistered hotkey '{}'.", self.key_sequence);
return true;
} else {
warn!("Failed to unregister hotkey '{}'.", self.key_sequence);
}
}
}
false
}

}
10 changes: 7 additions & 3 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ use std::collections::HashMap;
use std::sync::mpsc::{channel, Receiver};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
Arc,
};
#[cfg(target_os = "windows")]
use std::sync::Mutex;
use std::time::Instant;

fn scale_ui<R>(ui: &mut egui::Ui, scale: f32, add_contents: impl FnOnce(&mut egui::Ui) -> R) -> R {
Expand Down Expand Up @@ -62,6 +64,7 @@ pub struct LauncherApp {
pub plugins: PluginManager,
pub selected: Option<usize>,
pub usage: HashMap<String, u32>,
#[cfg(target_os = "windows")]
pub registered_hotkeys: Mutex<HashMap<String, usize>>,
pub show_editor: bool,
pub show_settings: bool,
Expand Down Expand Up @@ -250,6 +253,7 @@ impl LauncherApp {
plugins,
selected: None,
usage: usage::load_usage(USAGE_FILE).unwrap_or_default(),
#[cfg(target_os = "windows")]
registered_hotkeys: Mutex::new(HashMap::new()),
show_editor: false,
show_settings: false,
Expand Down Expand Up @@ -473,7 +477,7 @@ impl LauncherApp {
}

impl eframe::App for LauncherApp {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
use egui::*;

tracing::debug!("LauncherApp::update called");
Expand Down Expand Up @@ -524,7 +528,7 @@ impl eframe::App for LauncherApp {
(self.window_size.0 as f32, self.window_size.1 as f32),
);
#[cfg(target_os = "windows")]
if let Some(hwnd) = crate::window_manager::get_hwnd(frame) {
if let Some(hwnd) = crate::window_manager::get_hwnd(_frame) {
crate::window_manager::force_restore_and_foreground(hwnd);
}
}
Expand Down
8 changes: 0 additions & 8 deletions src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ fn load_history_internal() -> anyhow::Result<VecDeque<HistoryEntry>> {
Ok(list.into())
}

/// Load history from `history.json` into the global HISTORY list.
pub fn load_history() -> anyhow::Result<()> {
let hist = load_history_internal()?;
let mut h = HISTORY.lock().unwrap();
*h = hist;
Ok(())
}

/// Save the current HISTORY list to `history.json`.
pub fn save_history() -> anyhow::Result<()> {
let h = HISTORY.lock().unwrap();
Expand Down
50 changes: 26 additions & 24 deletions src/hotkey.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(target_os = "windows")]
pub use rdev::{EventType, Key};
pub use rdev::Key;

#[cfg(not(target_os = "windows"))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -89,14 +89,16 @@ pub enum Key {
AltGr,
}

#[cfg(not(target_os = "windows"))]
#[cfg(all(not(target_os = "windows"), test))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventType {
KeyPress(Key),
KeyRelease(Key),
}
use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
#[cfg(target_os = "windows")]
use std::thread;
#[cfg(target_os = "windows")]
use std::time::Duration;

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -256,11 +258,11 @@ fn parse_key(upper: &str) -> Option<Key> {
// Shared signal to open launcher
pub struct HotkeyTrigger {
pub open: Arc<Mutex<bool>>,
pub key: Key,
pub ctrl: bool,
pub shift: bool,
pub alt: bool,
pub win: bool,
pub _key: Key,
pub _ctrl: bool,
pub _shift: bool,
pub _alt: bool,
pub _win: bool,
}

pub struct HotkeyListener {
Expand All @@ -271,11 +273,11 @@ impl HotkeyTrigger {
pub fn new(hotkey: Hotkey) -> Self {
Self {
open: Arc::new(Mutex::new(false)),
key: hotkey.key,
ctrl: hotkey.ctrl,
shift: hotkey.shift,
alt: hotkey.alt,
win: hotkey.win,
_key: hotkey.key,
_ctrl: hotkey.ctrl,
_shift: hotkey.shift,
_alt: hotkey.alt,
_win: hotkey.win,
}
}

Expand Down Expand Up @@ -364,12 +366,12 @@ impl HotkeyTrigger {

let stop_flag = Arc::new(AtomicBool::new(false));
let stop_clone = stop_flag.clone();
let vk_keys: Vec<_> = triggers.iter().map(|t| vk_from_key(t.key)).collect();
let watch_keys: Vec<Key> = triggers.iter().map(|t| t.key).collect();
let need_ctrl: Vec<bool> = triggers.iter().map(|t| t.ctrl).collect();
let need_shift: Vec<bool> = triggers.iter().map(|t| t.shift).collect();
let need_alt: Vec<bool> = triggers.iter().map(|t| t.alt).collect();
let need_win: Vec<bool> = triggers.iter().map(|t| t.win).collect();
let vk_keys: Vec<_> = triggers.iter().map(|t| vk_from_key(t._key)).collect();
let watch_keys: Vec<Key> = triggers.iter().map(|t| t._key).collect();
let need_ctrl: Vec<bool> = triggers.iter().map(|t| t._ctrl).collect();
let need_shift: Vec<bool> = triggers.iter().map(|t| t._shift).collect();
let need_alt: Vec<bool> = triggers.iter().map(|t| t._alt).collect();
let need_win: Vec<bool> = triggers.iter().map(|t| t._win).collect();
thread::spawn(move || {
unsafe {
let _ = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
Expand Down Expand Up @@ -442,13 +444,14 @@ impl HotkeyListener {
}
}

#[cfg(test)]
pub fn process_test_events(triggers: &[Arc<HotkeyTrigger>], events: &[EventType]) {
let open_listeners: Vec<_> = triggers.iter().map(|t| t.open.clone()).collect();
let watch_keys: Vec<Key> = triggers.iter().map(|t| t.key).collect();
let need_ctrl: Vec<bool> = triggers.iter().map(|t| t.ctrl).collect();
let need_shift: Vec<bool> = triggers.iter().map(|t| t.shift).collect();
let need_alt: Vec<bool> = triggers.iter().map(|t| t.alt).collect();
let need_win: Vec<bool> = triggers.iter().map(|t| t.win).collect();
let watch_keys: Vec<Key> = triggers.iter().map(|t| t._key).collect();
let need_ctrl: Vec<bool> = triggers.iter().map(|t| t._ctrl).collect();
let need_shift: Vec<bool> = triggers.iter().map(|t| t._shift).collect();
let need_alt: Vec<bool> = triggers.iter().map(|t| t._alt).collect();
let need_win: Vec<bool> = triggers.iter().map(|t| t._win).collect();

let mut watch_pressed = vec![false; triggers.len()];
let mut triggered = vec![false; triggers.len()];
Expand Down Expand Up @@ -487,7 +490,6 @@ pub fn process_test_events(triggers: &[Arc<HotkeyTrigger>], events: &[EventType]
}
}
}
_ => {}
}

for i in 0..watch_keys.len() {
Expand Down
20 changes: 6 additions & 14 deletions src/launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ fn set_system_volume(percent: u32) {
}
}

#[cfg(not(target_os = "windows"))]
fn set_system_volume(_percent: u32) {}

#[cfg(target_os = "windows")]
fn mute_active_window() {
Expand Down Expand Up @@ -71,8 +69,6 @@ fn mute_active_window() {
}
}

#[cfg(not(target_os = "windows"))]
fn mute_active_window() {}

#[cfg(target_os = "windows")]
fn set_display_brightness(percent: u32) {
Expand Down Expand Up @@ -108,8 +104,6 @@ fn set_display_brightness(percent: u32) {
}
}

#[cfg(not(target_os = "windows"))]
fn set_display_brightness(_percent: u32) {}

#[cfg(target_os = "windows")]
fn clean_recycle_bin() {
Expand All @@ -119,8 +113,6 @@ fn clean_recycle_bin() {
}
}

#[cfg(not(target_os = "windows"))]
fn clean_recycle_bin() {}

fn system_command(action: &str) -> Option<std::process::Command> {
#[cfg(target_os = "windows")]
Expand Down Expand Up @@ -250,10 +242,10 @@ pub fn launch_action(action: &Action) -> anyhow::Result<()> {
return Ok(());
}
if let Some(pid) = action.action.strip_prefix("process:switch:") {
if let Ok(pid) = pid.parse::<u32>() {
if let Ok(_pid) = pid.parse::<u32>() {
#[cfg(target_os = "windows")]
{
crate::window_manager::activate_process(pid);
crate::window_manager::activate_process(_pid);
}
}
return Ok(());
Expand Down Expand Up @@ -330,16 +322,16 @@ pub fn launch_action(action: &Action) -> anyhow::Result<()> {
return Ok(());
}
if let Some(val) = action.action.strip_prefix("brightness:set:") {
if let Ok(v) = val.parse::<u32>() {
if let Ok(_v) = val.parse::<u32>() {
#[cfg(target_os = "windows")]
set_display_brightness(v);
set_display_brightness(_v);
}
return Ok(());
}
if let Some(val) = action.action.strip_prefix("volume:set:") {
if let Ok(v) = val.parse::<u32>() {
if let Ok(_v) = val.parse::<u32>() {
#[cfg(target_os = "windows")]
set_system_volume(v);
set_system_volume(_v);
}
return Ok(());
}
Expand Down
9 changes: 3 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ mod workspace;
use crate::actions::{load_actions, Action};
use crate::gui::LauncherApp;
use crate::hotkey::HotkeyTrigger;
use crate::plugin::{Plugin, PluginManager};
use crate::plugins::clipboard::ClipboardPlugin;
use crate::plugins_builtin::{CalculatorPlugin, WebSearchPlugin};
use crate::plugin::PluginManager;
use crate::settings::Settings;
use crate::visibility::handle_visibility_trigger;

Expand Down Expand Up @@ -87,7 +85,6 @@ fn spawn_gui(
let plugin_dirs = settings.plugin_dirs.clone();
let index_paths = settings.index_paths.clone();
let enabled_plugins = settings.enabled_plugins.clone();
let enabled_capabilities = settings.enabled_capabilities.clone();
let visible_flag = Arc::new(AtomicBool::new(true));
let restore_flag = Arc::new(AtomicBool::new(false));
let help_flag = Arc::new(AtomicBool::new(false));
Expand All @@ -105,11 +102,11 @@ fn spawn_gui(
.with_min_inner_size([320.0, 160.0])
.with_always_on_top()
.with_visible(true),
event_loop_builder: Some(Box::new(|builder| {
event_loop_builder: Some(Box::new(|_builder| {
#[cfg(target_os = "windows")]
{
use winit::platform::windows::EventLoopBuilderExtWindows;
builder.with_any_thread(true);
_builder.with_any_thread(true);
}
})),
..Default::default()
Expand Down
62 changes: 0 additions & 62 deletions src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,6 @@ impl PluginManager {
self.plugins.iter().map(|p| p.name().to_string()).collect()
}

/// Return the capabilities for all plugins.
pub fn plugin_capabilities(&self) -> Vec<(String, Vec<String>)> {
self.plugins
.iter()
.map(|p| {
(
p.name().to_string(),
p.capabilities().iter().map(|c| c.to_string()).collect(),
)
})
.collect()
}

/// Return names, descriptions and capabilities for all plugins.
pub fn plugin_infos(&self) -> Vec<(String, String, Vec<String>)> {
self.plugins
Expand Down Expand Up @@ -169,55 +156,6 @@ impl PluginManager {
Ok(())
}

/// Load plugins from a directory, enabling only those whose names are
/// present in `enabled` when provided.
pub fn load_dir_filtered(
&mut self,
path: &str,
enabled: Option<&Vec<String>>,
) -> anyhow::Result<()> {
use std::ffi::OsStr;

let ext = "dll";

for entry in std::fs::read_dir(path)? {
let entry = entry?;
let file_type = entry.file_type()?;
if !file_type.is_file() {
continue;
}
if entry.path().extension() != Some(OsStr::new(ext)) {
continue;
}

unsafe {
let lib = Library::new(entry.path())?;
let constructor: libloading::Symbol<unsafe extern "C" fn() -> Box<dyn Plugin>> =
lib.get(b"create_plugin")?;
let plugin = constructor();
let name = plugin.name().to_string();
if let Some(list) = enabled {
if !list.contains(&name) {
tracing::debug!("skipping disabled plugin {name}");
continue;
}
}
self.plugins.push(plugin);
self.libs.push(lib);
tracing::debug!("loaded plugin {name}");
}
}
Ok(())
}

pub fn search(&self, query: &str) -> Vec<Action> {
let mut actions = Vec::new();
for p in &self.plugins {
actions.extend(p.search(query));
}
actions
}

/// Search with plugin and capability filters.
pub fn search_filtered(
&self,
Expand Down
Loading