Make tray icon red on Windows when disabled. Fix #293

This commit is contained in:
Federico Terzi 2020-08-15 21:07:41 +02:00
parent 411078a503
commit b9fad30878
7 changed files with 65 additions and 2 deletions

View File

@ -62,6 +62,7 @@ HWND nw = NULL;
HWND hwnd_st_u = NULL;
HBITMAP g_espanso_bmp = NULL;
HICON g_espanso_ico = NULL;
HICON g_espanso_red_ico = NULL;
NOTIFYICONDATA nid = {};
UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
@ -309,13 +310,14 @@ LRESULT CALLBACK window_procedure(HWND window, unsigned int msg, WPARAM wp, LPAR
}
}
int32_t initialize(void * self, wchar_t * ico_path, wchar_t * bmp_path, int32_t _show_icon) {
int32_t initialize(void * self, wchar_t * ico_path, wchar_t * red_ico_path, wchar_t * bmp_path, int32_t _show_icon) {
manager_instance = self;
show_icon = _show_icon;
// Load the images
g_espanso_bmp = (HBITMAP)LoadImage(NULL, bmp_path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
g_espanso_ico = (HICON)LoadImage(NULL, ico_path, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_SHARED | LR_DEFAULTSIZE | LR_LOADFROMFILE);
g_espanso_red_ico = (HICON)LoadImage(NULL, red_ico_path, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_SHARED | LR_DEFAULTSIZE | LR_LOADFROMFILE);
// Make the notification capable of handling different screen definitions
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
@ -472,6 +474,19 @@ void eventloop() {
// Something went wrong, this should have been an infinite loop.
}
void update_tray_icon(int32_t enabled) {
if (enabled) {
nid.hIcon = g_espanso_ico;
}else{
nid.hIcon = g_espanso_red_ico;
}
// Update the icon
if (show_icon) {
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
}
/*
* Type the given string simulating keyboard presses.
*/

View File

@ -33,7 +33,7 @@ extern void * manager_instance;
* Initialize the Windows parameters
* return: 1 if OK, -1 otherwise.
*/
extern "C" int32_t initialize(void * self, wchar_t * ico_path, wchar_t * bmp_path, int32_t show_icon);
extern "C" int32_t initialize(void * self, wchar_t * ico_path, wchar_t * red_ico_path, wchar_t * bmp_path, int32_t show_icon);
#define LEFT_VARIANT 1
#define RIGHT_VARIANT 2
@ -152,6 +152,11 @@ extern "C" int32_t show_notification(wchar_t * message);
*/
extern "C" void close_notification();
/*
* Update the tray icon status
*/
extern "C" void update_tray_icon(int32_t enabled);
// CLIPBOARD
/*

View File

@ -33,6 +33,7 @@ extern "C" {
pub fn initialize(
s: *const c_void,
ico_path: *const u16,
red_ico_path: *const u16,
bmp_path: *const u16,
show_icon: i32,
) -> i32;
@ -48,6 +49,7 @@ extern "C" {
pub fn register_icon_click_callback(cb: extern "C" fn(_self: *mut c_void));
pub fn register_context_menu_click_callback(cb: extern "C" fn(_self: *mut c_void, id: i32));
pub fn cleanup_ui();
pub fn update_tray_icon(enabled: i32);
// CLIPBOARD
pub fn get_clipboard(buffer: *mut u16, size: i32) -> i32;

View File

@ -48,6 +48,11 @@ pub fn new(
macos::MacContext::new(config, send_channel, is_injecting)
}
#[cfg(target_os = "macos")]
pub fn update_icon(enabled: bool) {
// TODO: add update icon on macOS
}
// LINUX IMPLEMENTATION
#[cfg(target_os = "linux")]
pub fn new(
@ -58,6 +63,11 @@ pub fn new(
linux::LinuxContext::new(config, send_channel, is_injecting)
}
#[cfg(target_os = "linux")]
pub fn update_icon(enabled: bool) {
// No icon on Linux
}
// WINDOWS IMPLEMENTATION
#[cfg(target_os = "windows")]
pub fn new(
@ -68,6 +78,11 @@ pub fn new(
windows::WindowsContext::new(config, send_channel, is_injecting)
}
#[cfg(target_os = "windows")]
pub fn update_icon(enabled: bool) {
windows::update_icon(enabled);
}
// espanso directories
static WARING_INIT: Once = Once::new();

View File

@ -32,6 +32,7 @@ use widestring::{U16CStr, U16CString};
const BMP_BINARY: &[u8] = include_bytes!("../res/win/espanso.bmp");
const ICO_BINARY: &[u8] = include_bytes!("../res/win/espanso.ico");
const RED_ICO_BINARY: &[u8] = include_bytes!("../res/win/espansored.ico");
pub struct WindowsContext {
send_channel: Sender<Event>,
@ -77,8 +78,22 @@ impl WindowsContext {
);
}
let espanso_red_ico_image = espanso_dir.join("espansored.ico");
if espanso_red_ico_image.exists() {
info!("red ICO already initialized, skipping.");
} else {
fs::write(&espanso_red_ico_image, RED_ICO_BINARY)
.expect("Unable to write windows ico file");
info!(
"Extracted 'red ico' icon to: {}",
espanso_red_ico_image.to_str().unwrap_or("error")
);
}
let bmp_icon = espanso_bmp_image.to_str().unwrap_or_default();
let ico_icon = espanso_ico_image.to_str().unwrap_or_default();
let red_ico_icon = espanso_red_ico_image.to_str().unwrap_or_default();
let send_channel = send_channel;
@ -96,6 +111,7 @@ impl WindowsContext {
register_context_menu_click_callback(context_menu_click_callback);
let ico_file_c = U16CString::from_str(ico_icon).unwrap();
let red_ico_file_c = U16CString::from_str(red_ico_icon).unwrap();
let bmp_file_c = U16CString::from_str(bmp_icon).unwrap();
let show_icon = if config.show_icon { 1 } else { 0 };
@ -104,6 +120,7 @@ impl WindowsContext {
let res = initialize(
context_ptr,
ico_file_c.as_ptr(),
red_ico_file_c.as_ptr(),
bmp_file_c.as_ptr(),
show_icon,
);
@ -126,6 +143,12 @@ impl super::Context for WindowsContext {
// Native bridge code
pub fn update_icon(enabled: bool) {
unsafe {
crate::bridge::windows::update_tray_icon(if enabled { 1 } else { 0 });
}
}
extern "C" fn keypress_callback(
_self: *mut c_void,
raw_buffer: *const u16,

View File

@ -377,6 +377,9 @@ impl<
if config.show_notifications {
self.ui_manager.notify(message);
}
// Update the icon on supported OSes.
crate::context::update_icon(status);
}
fn on_passive(&self) {

BIN
src/res/win/espansored.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB