Change menu icon on macOS when disabled. Fix #432
This commit is contained in:
parent
ff13da9a85
commit
b23763d4de
|
@ -29,5 +29,7 @@
|
|||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
|
||||
- (IBAction) statusIconClick: (id) sender;
|
||||
- (IBAction) contextMenuClick: (id) sender;
|
||||
- (void) updateIcon: (char *)iconPath;
|
||||
- (void) setIcon: (char *)iconPath;
|
||||
|
||||
@end
|
|
@ -27,14 +27,7 @@
|
|||
if (show_icon) {
|
||||
myStatusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
|
||||
|
||||
NSString *nsIconPath = [NSString stringWithUTF8String:icon_path];
|
||||
NSImage *statusImage = [[NSImage alloc] initWithContentsOfFile:nsIconPath];
|
||||
[statusImage setTemplate:YES];
|
||||
|
||||
[myStatusItem.button setImage:statusImage];
|
||||
[myStatusItem setHighlightMode:YES];
|
||||
[myStatusItem.button setAction:@selector(statusIconClick:)];
|
||||
[myStatusItem.button setTarget:self];
|
||||
[self setIcon: icon_path];
|
||||
}
|
||||
|
||||
// Setup key listener
|
||||
|
@ -66,6 +59,29 @@
|
|||
}];
|
||||
}
|
||||
|
||||
- (void) updateIcon: (char *)iconPath {
|
||||
if (show_icon) {
|
||||
[myStatusItem release];
|
||||
|
||||
[self setIcon: iconPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setIcon: (char *)iconPath {
|
||||
if (show_icon) {
|
||||
myStatusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
|
||||
|
||||
NSString *nsIconPath = [NSString stringWithUTF8String:iconPath];
|
||||
NSImage *statusImage = [[NSImage alloc] initWithContentsOfFile:nsIconPath];
|
||||
[statusImage setTemplate:YES];
|
||||
|
||||
[myStatusItem.button setImage:statusImage];
|
||||
[myStatusItem setHighlightMode:YES];
|
||||
[myStatusItem.button setAction:@selector(statusIconClick:)];
|
||||
[myStatusItem.button setTarget:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) statusIconClick: (id) sender {
|
||||
icon_click_callback(context_instance);
|
||||
}
|
||||
|
|
|
@ -26,12 +26,13 @@ extern "C" {
|
|||
|
||||
extern void * context_instance;
|
||||
extern char * icon_path;
|
||||
extern char * disabled_icon_path;
|
||||
extern int32_t show_icon;
|
||||
|
||||
/*
|
||||
* Initialize the AppDelegate and check for accessibility permissions
|
||||
*/
|
||||
int32_t initialize(void * context, const char * icon_path, int32_t show_icon);
|
||||
int32_t initialize(void * context, const char * icon_path, const char * disabled_icon_path, int32_t show_icon);
|
||||
|
||||
/*
|
||||
* Start the event loop indefinitely. Blocking call.
|
||||
|
@ -117,6 +118,11 @@ typedef void (*ContextMenuClickCallback)(void * self, int32_t id);
|
|||
extern ContextMenuClickCallback context_menu_click_callback;
|
||||
extern "C" void register_context_menu_click_callback(ContextMenuClickCallback callback);
|
||||
|
||||
/*
|
||||
* Update the tray icon status
|
||||
*/
|
||||
extern "C" void update_tray_icon(int32_t enabled);
|
||||
|
||||
// SYSTEM
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
|||
|
||||
void * context_instance;
|
||||
char * icon_path;
|
||||
char * disabled_icon_path;
|
||||
int32_t show_icon;
|
||||
AppDelegate * delegate_ptr;
|
||||
|
||||
|
@ -40,9 +41,10 @@ KeypressCallback keypress_callback;
|
|||
IconClickCallback icon_click_callback;
|
||||
ContextMenuClickCallback context_menu_click_callback;
|
||||
|
||||
int32_t initialize(void * context, const char * _icon_path, int32_t _show_icon) {
|
||||
int32_t initialize(void * context, const char * _icon_path, const char * _disabled_icon_path, int32_t _show_icon) {
|
||||
context_instance = context;
|
||||
icon_path = strdup(_icon_path);
|
||||
disabled_icon_path = strdup(_disabled_icon_path);
|
||||
show_icon = _show_icon;
|
||||
|
||||
AppDelegate *delegate = [[AppDelegate alloc] init];
|
||||
|
@ -74,6 +76,18 @@ int32_t headless_eventloop() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void update_tray_icon(int32_t enabled) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
NSApplication * application = [NSApplication sharedApplication];
|
||||
char * iconPath = icon_path;
|
||||
if (!enabled) {
|
||||
iconPath = disabled_icon_path;
|
||||
}
|
||||
|
||||
[[application delegate] updateIcon: iconPath];
|
||||
});
|
||||
}
|
||||
|
||||
void send_string(const char * string) {
|
||||
char * stringCopy = strdup(string);
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
|
|
|
@ -29,7 +29,12 @@ pub struct MacMenuItem {
|
|||
#[allow(improper_ctypes)]
|
||||
#[link(name = "macbridge", kind = "static")]
|
||||
extern "C" {
|
||||
pub fn initialize(s: *const c_void, icon_path: *const c_char, show_icon: i32);
|
||||
pub fn initialize(
|
||||
s: *const c_void,
|
||||
icon_path: *const c_char,
|
||||
disabled_icon_path: *const c_char,
|
||||
show_icon: i32,
|
||||
);
|
||||
pub fn eventloop();
|
||||
pub fn headless_eventloop();
|
||||
|
||||
|
@ -51,6 +56,7 @@ extern "C" {
|
|||
pub fn register_icon_click_callback(cb: extern "C" fn(_self: *mut c_void));
|
||||
pub fn show_context_menu(items: *const MacMenuItem, count: i32) -> i32;
|
||||
pub fn register_context_menu_click_callback(cb: extern "C" fn(_self: *mut c_void, id: i32));
|
||||
pub fn update_tray_icon(enabled: i32);
|
||||
|
||||
// Keyboard
|
||||
pub fn register_keypress_callback(
|
||||
|
|
|
@ -34,6 +34,7 @@ use std::sync::Arc;
|
|||
use std::{fs, thread};
|
||||
|
||||
const STATUS_ICON_BINARY: &[u8] = include_bytes!("../res/mac/icon.png");
|
||||
const DISABLED_STATUS_ICON_BINARY: &[u8] = include_bytes!("../res/mac/icondisabled.png");
|
||||
|
||||
pub struct MacContext {
|
||||
pub send_channel: Sender<Event>,
|
||||
|
@ -72,6 +73,7 @@ impl MacContext {
|
|||
// Initialize the status icon path
|
||||
let espanso_dir = super::get_data_dir();
|
||||
let status_icon_target = espanso_dir.join("icon.png");
|
||||
let disabled_status_icon_target = espanso_dir.join("icondisabled.png");
|
||||
|
||||
if status_icon_target.exists() {
|
||||
info!("Status icon already initialized, skipping.");
|
||||
|
@ -84,6 +86,19 @@ impl MacContext {
|
|||
});
|
||||
}
|
||||
|
||||
if disabled_status_icon_target.exists() {
|
||||
info!("Status icon (disabled) already initialized, skipping.");
|
||||
} else {
|
||||
fs::write(&disabled_status_icon_target, DISABLED_STATUS_ICON_BINARY).unwrap_or_else(
|
||||
|e| {
|
||||
error!(
|
||||
"Error copying the Status Icon (disabled) to the espanso data directory: {}",
|
||||
e
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let context_ptr = &*context as *const MacContext as *const c_void;
|
||||
|
||||
|
@ -93,9 +108,17 @@ impl MacContext {
|
|||
|
||||
let status_icon_path =
|
||||
CString::new(status_icon_target.to_str().unwrap_or_default()).unwrap_or_default();
|
||||
let disabled_status_icon_path =
|
||||
CString::new(disabled_status_icon_target.to_str().unwrap_or_default())
|
||||
.unwrap_or_default();
|
||||
let show_icon = if config.show_icon { 1 } else { 0 };
|
||||
|
||||
initialize(context_ptr, status_icon_path.as_ptr(), show_icon);
|
||||
initialize(
|
||||
context_ptr,
|
||||
status_icon_path.as_ptr(),
|
||||
disabled_status_icon_path.as_ptr(),
|
||||
show_icon,
|
||||
);
|
||||
}
|
||||
|
||||
context
|
||||
|
@ -146,6 +169,12 @@ impl MacContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_icon(enabled: bool) {
|
||||
unsafe {
|
||||
crate::bridge::macos::update_tray_icon(if enabled { 1 } else { 0 });
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Context for MacContext {
|
||||
fn eventloop(&self) {
|
||||
// Start the SecureInput watcher thread
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn new(
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn update_icon(enabled: bool) {
|
||||
// TODO: add update icon on macOS
|
||||
macos::update_icon(enabled);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
|
|
@ -498,9 +498,14 @@ impl<
|
|||
if config.secure_input_notification && config.show_notifications {
|
||||
self.ui_manager.notify_delay(&format!("{} has activated SecureInput. Espanso won't work until you disable it.", app_name), 5000);
|
||||
}
|
||||
|
||||
crate::context::update_icon(false);
|
||||
}
|
||||
SystemEvent::SecureInputDisabled => {
|
||||
info!("SecureInput has been disabled.");
|
||||
|
||||
let is_enabled = self.enabled.borrow();
|
||||
crate::context::update_icon(*is_enabled);
|
||||
}
|
||||
SystemEvent::NotifyRequest(message) => {
|
||||
let config = self.config_manager.default_config();
|
||||
|
|
BIN
src/res/mac/icondisabled.png
Normal file
BIN
src/res/mac/icondisabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Loading…
Reference in New Issue
Block a user