From ed58ccc6dd8bdfd954f49be5c589245340c6c5c2 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Thu, 5 Oct 2023 17:46:08 -0700 Subject: [PATCH 1/2] feat: Implement a proper show/hide UI function Hide the app icon from the dock bar, and add a new menu item to show UI again after hide. Fixes #85 --- Cargo.lock | 9 +++------ Cargo.toml | 4 ++-- src/platform/linux.rs | 3 --- src/platform/macos.rs | 2 -- src/platform/macos_ext.rs | 16 +++++++++------- src/platform/mod.rs | 2 +- src/platform/windows.rs | 3 --- src/ui.rs | 33 ++++++++++++++++++++------------- 8 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc9c310..fa1adea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,8 +383,7 @@ dependencies = [ [[package]] name = "druid" version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ece41814b410c87e6379441caa7316539500b2e387b8d691f2ba5c0f4aff631" +source = "git+https://github.com/huytd/druid?branch=master#ff762386f6de691bd96a36254fbe2f3a335e3cd3" dependencies = [ "console_error_panic_hook", "druid-derive", @@ -405,8 +404,7 @@ dependencies = [ [[package]] name = "druid-derive" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808d664482b1888a2ccb7f4dc9fa24165174d65ba96726315964064bdbc7d6cb" +source = "git+https://github.com/huytd/druid?branch=master#ff762386f6de691bd96a36254fbe2f3a335e3cd3" dependencies = [ "proc-macro2", "quote", @@ -416,8 +414,7 @@ dependencies = [ [[package]] name = "druid-shell" version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7682d9c8fbf934504c30970775bfcfba7858a600f2f6e56bed331989958350fc" +source = "git+https://github.com/huytd/druid?branch=master#ff762386f6de691bd96a36254fbe2f3a335e3cd3" dependencies = [ "anyhow", "bitflags 1.3.2", diff --git a/Cargo.toml b/Cargo.toml index d47f9ff..c3dfbf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,9 @@ version = "0.1.2" env_logger = "0.10.0" libc = "0.2.139" log = "0.4.17" -vi = { git = "https:/github.com/zerox-dg/vi-rs", branch = "master" } +vi = { git = "https://github.com/zerox-dg/vi-rs", branch = "master" } bitflags = "1.3.2" -druid = { version = "0.8.2", features = ["image", "png"] } +druid = { features = ["image", "png"], git = "https://github.com/huytd/druid", branch = "master" } once_cell = "1.17.0" auto-launch = "0.5.0" diff --git a/src/platform/linux.rs b/src/platform/linux.rs index de0de8f..ef9e953 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -9,9 +9,6 @@ pub const SYMBOL_CTRL: &str = "⌃"; pub const SYMBOL_SUPER: &str = "❖"; pub const SYMBOL_ALT: &str = "⌥"; -// TODO: support HIDE_WINDOW on next druid future versions -pub const HIDE_COMMAND: Selector = CLOSE_WINDOW; - pub fn get_home_dir() -> Option { env::var("HOME").ok().map(PathBuf::from) } diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 0e258fa..6deac62 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -16,7 +16,6 @@ use core_graphics::{ }, sys, }; -use druid::{commands::HIDE_APPLICATION, Selector}; use objc::{class, msg_send, sel, sel_impl}; pub use macos_ext::SystemTray; @@ -46,7 +45,6 @@ pub const SYMBOL_CTRL: &str = "⌃"; pub const SYMBOL_SUPER: &str = "⌘"; pub const SYMBOL_ALT: &str = "⌥"; -pub const HIDE_COMMAND: Selector = HIDE_APPLICATION; static AUTO_LAUNCH: Lazy = Lazy::new(|| { let app_path = get_current_app_path(); let app_name = Path::new(&app_path) diff --git a/src/platform/macos_ext.rs b/src/platform/macos_ext.rs index 825bb72..ccdf700 100644 --- a/src/platform/macos_ext.rs +++ b/src/platform/macos_ext.rs @@ -1,6 +1,4 @@ -use cocoa::appkit::{ - NSApp, NSApplication, NSButton, NSMenu, NSMenuItem, NSStatusBar, NSStatusItem, -}; +use cocoa::appkit::{NSApp, NSApplication, NSButton, NSMenu, NSMenuItem, NSStatusBar, NSStatusItem}; use cocoa::base::{nil, YES}; use cocoa::foundation::{NSAutoreleasePool, NSString}; use core_foundation::dictionary::CFDictionaryRef; @@ -31,6 +29,7 @@ impl Data for Wrapper { } pub enum SystemTrayMenuItemKey { + ShowUI, Enable, TypingMethodTelex, TypingMethodVNI, @@ -75,6 +74,8 @@ impl SystemTray { } pub fn init_menu_items(&self) { + self.add_menu_item("Bật bảng điều khiển", || ()); + self.add_menu_separator(); self.add_menu_item("Tắt gõ tiếng việt", || ()); self.add_menu_separator(); self.add_menu_item("Telex ✓", || ()); @@ -109,10 +110,11 @@ impl SystemTray { pub fn get_menu_item_index_by_key(&self, key: SystemTrayMenuItemKey) -> i64 { match key { - SystemTrayMenuItemKey::Enable => 0, - SystemTrayMenuItemKey::TypingMethodTelex => 2, - SystemTrayMenuItemKey::TypingMethodVNI => 3, - SystemTrayMenuItemKey::Exit => 5, + SystemTrayMenuItemKey::ShowUI => 0, + SystemTrayMenuItemKey::Enable => 2, + SystemTrayMenuItemKey::TypingMethodTelex => 4, + SystemTrayMenuItemKey::TypingMethodVNI => 5, + SystemTrayMenuItemKey::Exit => 7, } } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index cb28f50..e7670aa 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -9,7 +9,7 @@ use bitflags::bitflags; pub use os::{ ensure_accessibility_permission, get_active_app_name, get_home_dir, is_in_text_selection, is_launch_on_login, run_event_listener, send_backspace, send_string, update_launch_on_login, - Handle, HIDE_COMMAND, SYMBOL_ALT, SYMBOL_CTRL, SYMBOL_SHIFT, SYMBOL_SUPER, + Handle, SYMBOL_ALT, SYMBOL_CTRL, SYMBOL_SHIFT, SYMBOL_SUPER, }; #[cfg(target_os = "macos")] diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 88fc56e..734efdd 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -9,9 +9,6 @@ pub const SYMBOL_CTRL: &str = "⌃"; pub const SYMBOL_SUPER: &str = "⊞"; pub const SYMBOL_ALT: &str = "⌥"; -// TODO: support HIDE_WINDOW on next druid future versions -pub const HIDE_COMMAND: Selector = CLOSE_WINDOW; - pub fn get_home_dir() -> Option { env::var("USERPROFILE").ok().map(PathBuf::from) .or_else(|| env::var("HOMEDRIVE").ok().and_then(|home_drive| { diff --git a/src/ui.rs b/src/ui.rs index 9664586..6cac0ae 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,24 +1,19 @@ use crate::{ input::{rebuild_keyboard_layout_map, TypingMethod, INPUT_STATE}, platform::{ - self, is_launch_on_login, update_launch_on_login, KeyModifier, SystemTray, + is_launch_on_login, update_launch_on_login, KeyModifier, SystemTray, SystemTrayMenuItemKey, SYMBOL_ALT, SYMBOL_CTRL, SYMBOL_SHIFT, SYMBOL_SUPER, }, UI_EVENT_SINK, }; -use druid::{ - commands::QUIT_APP, - theme::{BACKGROUND_DARK, BORDER_DARK, PLACEHOLDER_COLOR}, - widget::{ - Button, Checkbox, Container, Controller, FillStrat, Flex, Image, Label, LineBreaking, - RadioGroup, Switch, TextBox, - }, - Application, Data, Env, Event, EventCtx, ImageBuf, Lens, Screen, Selector, Target, Widget, - WidgetExt, -}; +use druid::{commands::{QUIT_APP}, theme::{BACKGROUND_DARK, BORDER_DARK, PLACEHOLDER_COLOR}, widget::{ + Button, Checkbox, Container, Controller, FillStrat, Flex, Image, Label, LineBreaking, + RadioGroup, Switch, TextBox, +}, Application, Data, Env, Event, EventCtx, ImageBuf, Lens, Screen, Selector, Target, Widget, WidgetExt}; use log::error; pub const UPDATE_UI: Selector = Selector::new("gox-ui.update-ui"); +pub const SHOW_UI: Selector = Selector::new("gox-ui.show-ui"); pub const WINDOW_WIDTH: f64 = 320.0; pub const WINDOW_HEIGHT: f64 = 268.0; @@ -142,6 +137,12 @@ impl UIDataAdapter { } fn setup_system_tray_actions(&mut self) { + self.systray + .set_menu_item_callback(SystemTrayMenuItemKey::ShowUI, || { + UI_EVENT_SINK + .get() + .map(|event| Some(event.submit_command(SHOW_UI, (), Target::Auto))); + }); self.systray .set_menu_item_callback(SystemTrayMenuItemKey::Enable, || { unsafe { @@ -202,10 +203,14 @@ impl> Controller for UIController { data.update(); rebuild_keyboard_layout_map(); } + if cmd.get(SHOW_UI).is_some() { + ctx.set_handled(); + ctx.window().bring_to_front_and_focus(); + } } Event::WindowCloseRequested => { ctx.set_handled(); - ctx.submit_command(platform::HIDE_COMMAND); + ctx.window().hide(); } _ => {} } @@ -353,7 +358,9 @@ pub fn main_ui_builder() -> impl Widget { Button::new("Đóng") .fix_width(100.0) .fix_height(28.0) - .on_click(|event, _, _| event.submit_command(platform::HIDE_COMMAND)), + .on_click(|event, _, _| { + event.window().hide(); + }), ) .cross_axis_alignment(druid::widget::CrossAxisAlignment::Start) .main_axis_alignment(druid::widget::MainAxisAlignment::End) From 83f1e75e00660e54fa6b7e4585f1d2f2fb6e8f20 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Thu, 5 Oct 2023 23:24:21 -0700 Subject: [PATCH 2/2] Make the UI window always on top --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index e3473df..9db28ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -175,6 +175,7 @@ fn main() { .title("gõkey") .window_size((ui::WINDOW_WIDTH, ui::WINDOW_HEIGHT)) .set_position(ui::center_window_position()) + .set_always_on_top(true) .resizable(false); let app = AppLauncher::with_window(win); let event_sink = app.get_external_handle();