Skip to content

Commit f26e6e8

Browse files
rounded corners for tray window on macos (#895)
* rounded corners for tray window on macos * Update ConnectionsWatcher.tsx
1 parent 7dddd97 commit f26e6e8

6 files changed

Lines changed: 151 additions & 30 deletions

File tree

new-ui/src/shared/components/WindowHeader/components/ConnectionWatcher/ConnectionsWatcher.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export const ConnectionWatcher = () => {
6060

6161
const hover = useHover(context, {
6262
handleClose: safePolygon(),
63+
enabled: connected,
6364
});
6465

6566
const dismiss = useDismiss(context, {

src-tauri/Cargo.lock

Lines changed: 68 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ x25519-dalek = { version = "2", features = [
124124
] }
125125

126126
[target.'cfg(target_os = "macos")'.dependencies]
127+
cocoa = "0.26"
127128
block2 = "0.6"
128129
objc2 = "0.6"
129130
objc2-foundation = "0.3"

src-tauri/src/tray.rs

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -144,38 +144,48 @@ pub async fn setup_tray(app: &AppHandle) -> Result<(), Error> {
144144

145145
TrayIconBuilder::with_id(TRAY_ICON_ID)
146146
.menu(&tray_menu)
147-
.show_menu_on_left_click(cfg!(target_os = "macos"))
147+
.show_menu_on_left_click(false)
148148
.on_tray_icon_event(|icon, event| {
149149
store_tray_click_position(icon.app_handle(), &event);
150-
if let TrayIconEvent::Click {
151-
button: MouseButton::Left,
152-
button_state: MouseButtonState::Up,
153-
..
154-
} = event
155-
{
156-
let app = icon.app_handle();
157-
let any_visible = [NEW_UI_WINDOW_ID, OLD_UI_WINDOW_ID].iter().any(|id| {
158-
app.get_webview_window(id)
159-
.and_then(|w| w.is_visible().ok())
160-
.unwrap_or(false)
161-
});
162-
if any_visible {
163-
hide_visible_windows(app);
164-
} else {
165-
#[cfg(not(target_os = "linux"))]
166-
{
167-
let has_locations = tauri::async_runtime::block_on(
168-
crate::window_manager::has_non_service_locations(),
169-
);
170-
if has_locations {
171-
show_new_ui_window_near_tray(app);
172-
} else {
173-
let _ = WindowManager::open_full_view(app);
150+
match event {
151+
#[cfg(target_os = "macos")]
152+
TrayIconEvent::Click {
153+
button: MouseButton::Right,
154+
button_state: MouseButtonState::Up,
155+
..
156+
} => {
157+
let _ = icon.show_menu();
158+
}
159+
TrayIconEvent::Click {
160+
button: MouseButton::Left,
161+
button_state: MouseButtonState::Up,
162+
..
163+
} => {
164+
let app = icon.app_handle();
165+
let any_visible = [NEW_UI_WINDOW_ID, OLD_UI_WINDOW_ID].iter().any(|id| {
166+
app.get_webview_window(id)
167+
.and_then(|w| w.is_visible().ok())
168+
.unwrap_or(false)
169+
});
170+
if any_visible {
171+
hide_visible_windows(app);
172+
} else {
173+
#[cfg(not(target_os = "linux"))]
174+
{
175+
let has_locations = tauri::async_runtime::block_on(
176+
crate::window_manager::has_non_service_locations(),
177+
);
178+
if has_locations {
179+
show_new_ui_window_near_tray(app);
180+
} else {
181+
let _ = WindowManager::open_full_view(app);
182+
}
174183
}
184+
#[cfg(target_os = "linux")]
185+
show_new_ui_window_near_tray(app);
175186
}
176-
#[cfg(target_os = "linux")]
177-
show_new_ui_window_near_tray(app);
178187
}
188+
_ => {}
179189
}
180190
})
181191
.on_menu_event(handle_tray_menu_event)

src-tauri/src/window_manager/macos.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
use tauri::{AppHandle, LogicalPosition, Manager, Monitor, PhysicalSize, Position, WebviewWindow};
22

3+
#[cfg(target_os = "macos")]
4+
use tauri::Runtime;
5+
36
use crate::appstate::AppState;
47
use crate::window_manager::{WindowManager, NEW_UI_WINDOW_ID, OLD_UI_WINDOW_ID};
58

9+
#[cfg(target_os = "macos")]
10+
use cocoa::{
11+
appkit::{NSView, NSWindow, NSWindowStyleMask},
12+
base::id,
13+
};
14+
15+
#[cfg(target_os = "macos")]
16+
pub fn enable_rounded_corners<R: Runtime>(window: WebviewWindow<R>) -> Result<(), String> {
17+
window
18+
.with_webview(move |webview| {
19+
unsafe {
20+
let ns_window = webview.ns_window() as id;
21+
22+
let mut style_mask = ns_window.styleMask();
23+
24+
// Add necessary styles for rounded corners
25+
style_mask |= NSWindowStyleMask::NSFullSizeContentViewWindowMask;
26+
style_mask |= NSWindowStyleMask::NSTitledWindowMask;
27+
style_mask |= NSWindowStyleMask::NSClosableWindowMask;
28+
style_mask |= NSWindowStyleMask::NSMiniaturizableWindowMask;
29+
style_mask |= NSWindowStyleMask::NSResizableWindowMask;
30+
31+
ns_window.setStyleMask_(style_mask);
32+
ns_window.setTitlebarAppearsTransparent_(cocoa::base::YES);
33+
34+
let content_view = ns_window.contentView();
35+
content_view.setWantsLayer(cocoa::base::YES);
36+
}
37+
})
38+
.map_err(|e| e.to_string())
39+
}
40+
641
/// Try to get monitor at the given position, with a fall back to primary monitor, and then to the
742
/// first one on the list of available monitors.
843
fn get_monitor_for_position(app: &AppHandle, x: f64, y: f64) -> Option<Monitor> {

src-tauri/src/window_manager/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ pub struct WindowManager;
4242

4343
impl WindowManager {
4444
pub fn build_tray_window(app: &AppHandle) -> tauri::Result<WebviewWindow> {
45-
WebviewWindowBuilder::new(app, NEW_UI_WINDOW_ID, new_ui_url())
45+
let window = WebviewWindowBuilder::new(app, NEW_UI_WINDOW_ID, new_ui_url())
4646
.title("Defguard")
4747
.inner_size(NEW_UI_WIDTH, NEW_UI_HEIGHT)
4848
.resizable(false)
4949
.decorations(false)
5050
.visible(false)
5151
.always_on_top(true)
5252
.skip_taskbar(true)
53-
.build()
53+
.build()?;
54+
55+
#[cfg(target_os = "macos")]
56+
if let Err(err) = macos::enable_rounded_corners(window.clone()) {
57+
tracing::warn!("Failed to enable rounded corners on tray window: {err}");
58+
}
59+
60+
Ok(window)
5461
}
5562

5663
pub fn build_full_window(app: &AppHandle) -> tauri::Result<WebviewWindow> {

0 commit comments

Comments
 (0)