-
Notifications
You must be signed in to change notification settings - Fork 904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Taskbar icon and system menu information always shown on macOS #3921
Labels
Comments
Jooonnnaass
changed the title
Titlebar icon and system menu information always shown on macOS
Taskbar icon and system menu information always shown on macOS
Sep 18, 2024
Could you give more details on this? Did it work with previous versions of |
tray-icon = "0.17.0" I never used other versions. Below is the complete code. But it seams quite strange that it suddenly behaves like that because no window is created until tray item action. #![allow(unused)]
use std::{collections::HashMap, time::Instant};
use tray_icon::{
menu::{
accelerator::{Accelerator, Code, Modifiers},
AboutMetadata, Menu, MenuEvent, MenuItem, PredefinedMenuItem,
},
TrayIconBuilder, TrayIconEvent,
};
use winit::{
dpi::{LogicalPosition, LogicalSize, Position},
event::{Event, KeyEvent, WindowEvent},
event_loop::{self, ControlFlow, EventLoopBuilder},
keyboard::{Key, KeyCode, SmolStr},
monitor::{MonitorHandle, VideoModeHandle},
platform::{
macos::WindowAttributesExtMacOS, modifier_supplement::KeyEventExtModifierSupplement,
},
raw_window_handle::HasDisplayHandle,
window::{Fullscreen, Window, WindowAttributes, WindowId, WindowLevel},
};
struct AppState {
app_toggle: bool,
keebplay_toggle: bool,
capture_sequenz: bool,
app_window_id: Option<WindowId>,
overlay_window_id: Option<WindowId>,
windows: HashMap<WindowId, Box<Window>>,
key_sequenz: Vec<Key<SmolStr>>,
}
const SEQUENZ_THRESHOLD: i32 = 200;
fn main() {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/keyboard.png");
let tray_menu = Menu::new();
let mut app_toggle_item = MenuItem::with_id("app_toggle", "Open", true, None);
let mut keebplay_toggle_item =
MenuItem::with_id("keebplay_toggle", "Start Keebplay", true, None);
let quit_item = MenuItem::with_id("quit", "Quit", true, None);
let _ = tray_menu.append_items(&[
&app_toggle_item,
&PredefinedMenuItem::separator(),
&keebplay_toggle_item,
&PredefinedMenuItem::separator(),
&quit_item,
]);
// Since winit doesn't use gtk on Linux, and we need gtk for
// the tray icon to show up, we need to spawn a thread
// where we initialize gtk and create the tray_icon
#[cfg(target_os = "linux")]
std::thread::spawn(|| {
use tray_icon::menu::Menu;
let icon = load_icon(std::path::Path::new(path));
gtk::init().unwrap();
let _tray_icon = TrayIconBuilder::new()
.with_menu(Box::new(tray_menu))
.with_icon(icon)
.build()
.unwrap();
gtk::main();
});
let event_loop = EventLoopBuilder::new().build().unwrap();
#[cfg(not(target_os = "linux"))]
let mut tray_icon = None;
let menu_channel = MenuEvent::receiver();
let mut app_state = AppState {
app_toggle: false,
keebplay_toggle: false,
capture_sequenz: false,
app_window_id: None,
overlay_window_id: None,
windows: HashMap::new(),
key_sequenz: Vec::new(),
};
let last_keystroke = 0;
event_loop.run(move |event, event_loop| {
// We add delay of 16 ms (60fps) to event_loop to reduce cpu load.
// This can be removed to allow ControlFlow::Poll to poll on each cpu cycle
// Alternatively, you can set ControlFlow::Wait or use TrayIconEvent::set_event_handler,
// see https://github.com/tauri-apps/tray-icon/issues/83#issuecomment-1697773065
event_loop.set_control_flow(ControlFlow::WaitUntil(
std::time::Instant::now() + std::time::Duration::from_millis(16),
));
#[cfg(not(target_os = "linux"))]
if let winit::event::Event::NewEvents(winit::event::StartCause::Init) = event {
let icon = load_icon(std::path::Path::new(path));
// We create the icon once the event loop is actually running
// to prevent issues like https://github.com/tauri-apps/tray-icon/issues/90
tray_icon = Some(
TrayIconBuilder::new()
.with_menu(Box::new(tray_menu.clone()))
.with_tooltip("Keebplay")
.with_icon(icon)
.build()
.unwrap(),
);
// We have to request a redraw here to have the icon actually show up.
// Winit only exposes a redraw method on the Window so we use core-foundation directly.
#[cfg(target_os = "macos")]
unsafe {
use core_foundation::runloop::{CFRunLoopGetMain, CFRunLoopWakeUp};
let rl = CFRunLoopGetMain();
CFRunLoopWakeUp(rl);
}
}
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput { event, .. } => {
let this_keystroke = Instant::now();
if !app_state.capture_sequenz {
app_state.key_sequenz.clear();
app_state.capture_sequenz = true;
}
app_state.key_sequenz.push(event.key_without_modifiers());
}
_ => (),
},
_ => (),
};
if let Ok(event) = menu_channel.try_recv() {
if event.id == "app_toggle" {
if app_state.app_toggle {
app_state.app_toggle = false;
app_toggle_item.set_text("Open");
app_state.windows.remove(&app_state.app_window_id.unwrap());
} else {
app_state.app_toggle = true;
app_toggle_item.set_text("Stop");
let app_window_attributes = WindowAttributes::default()
.with_title("App")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_min_inner_size(LogicalSize::new(640.0f32, 480.0f32));
let window = event_loop.create_window(app_window_attributes).unwrap();
app_state.app_window_id = Some(window.id());
app_state.windows.insert(window.id(), Box::new(window));
}
}
if event.id == "keebplay_toggle" {
if app_state.keebplay_toggle {
app_state.keebplay_toggle = false;
keebplay_toggle_item.set_text("Start Keebplay");
app_state
.windows
.remove(&app_state.overlay_window_id.unwrap());
} else {
app_state.keebplay_toggle = true;
keebplay_toggle_item.set_text("Stop Keebplay");
let window_handle = &event_loop.primary_monitor().unwrap();
let size =
LogicalSize::new(window_handle.size().width, window_handle.size().height);
let overlay_window_attributes = WindowAttributes::default()
.with_title("Overlay")
.with_inner_size(size)
.with_window_level(WindowLevel::AlwaysOnTop)
.with_transparent(true);
let window = event_loop.create_window(overlay_window_attributes).unwrap();
app_state.overlay_window_id = Some(window.id());
app_state.windows.insert(window.id(), Box::new(window));
}
}
if event.id == "quit" {
event_loop.exit();
}
}
});
}
fn load_icon(path: &std::path::Path) -> tray_icon::Icon {
let (icon_rgba, icon_width, icon_height) = {
let image = image::open(path)
.expect("Failed to open icon path")
.into_rgba8();
let (width, height) = image.dimensions();
let rgba = image.into_raw();
(rgba, width, height)
};
tray_icon::Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Description
Im trying to create an overlay application with winit. I create an event loop and create a tray menu with the tray_icon crate.
Based on the MenuItems i create two windows, one for the app config and one for the overlay.
First everything was working fine but for some reason now every time i start the app, the exec icon shows up in the taskbar and the crate name will show up in the system titlebar of macOS even a window wasn't created yet.
I tried different window attributes but nothing works.
None of the opened issues helped me so far.
That's the code for creating the window based on the menu item button click.
macOS version
Winit version
0.30.5
The text was updated successfully, but these errors were encountered: