customize traffic light on macOS

This commit is contained in:
Ren Amamiya 2023-09-25 07:43:13 +07:00
parent c049fa8865
commit 9ff74599eb
4 changed files with 88 additions and 3 deletions

2
src-tauri/Cargo.lock generated
View File

@ -2623,6 +2623,8 @@ dependencies = [
name = "lume"
version = "1.2.5"
dependencies = [
"cocoa 0.25.0",
"objc",
"rust-argon2",
"serde",
"serde_json",

View File

@ -16,7 +16,8 @@ tauri-build = { version = "1.4", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.4", features = [ "macos-private-api",
tauri = { version = "1.4", features = [
"macos-private-api",
"window-close",
"window-print",
"window-create",
@ -53,6 +54,8 @@ sqlx-cli = { version = "0.7.0", default-features = false, features = [
] }
rust-argon2 = "1.0"
webpage = { version = "1.6.0", features = ["serde"] }
cocoa = "0.25.0"
objc = "0.2.7"
[features]
# by default Tauri runs in production mode

View File

@ -3,15 +3,25 @@
windows_subsystem = "windows"
)]
use tauri::Manager;
#[cfg(target_os = "macos")]
#[macro_use]
extern crate objc;
use std::time::Duration;
use tauri::{Manager, WindowEvent};
use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_sql::{Migration, MigrationKind};
use webpage::{Webpage, WebpageOptions};
use std::time::Duration;
#[cfg(target_os = "macos")]
use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial};
#[cfg(target_os = "macos")]
use traffic_light::TrafficLight;
#[cfg(target_os = "macos")]
mod traffic_light;
#[derive(Clone, serde::Serialize)]
struct Payload {
args: Vec<String>,
@ -102,8 +112,18 @@ fn main() {
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, None)
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
#[cfg(target_os = "macos")]
window.set_transparent_titlebar(true);
window.position_traffic_lights(16.0, 25.0);
Ok(())
})
.on_window_event(|e| {
if let WindowEvent::Resized(..) = e.event() {
let window = e.window();
window.position_traffic_lights(16., 25.);
}
})
.plugin(
tauri_plugin_sql::Builder::default()
.add_migrations(

View File

@ -0,0 +1,60 @@
use tauri::{Runtime, Window};
pub trait TrafficLight {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool);
fn position_traffic_lights(&self, x: f64, y: f64);
}
impl<R: Runtime> TrafficLight for Window<R> {
#[cfg(target_os = "macos")]
fn set_transparent_titlebar(&self, transparent: bool) {
use cocoa::appkit::{NSWindow, NSWindowTitleVisibility};
let window = self.ns_window().unwrap() as cocoa::base::id;
unsafe {
window.setTitleVisibility_(NSWindowTitleVisibility::NSWindowTitleHidden);
if transparent {
window.setTitlebarAppearsTransparent_(cocoa::base::YES);
} else {
window.setTitlebarAppearsTransparent_(cocoa::base::NO);
}
}
}
#[cfg(target_os = "macos")]
fn position_traffic_lights(&self, x: f64, y: f64) {
use cocoa::appkit::{NSView, NSWindow, NSWindowButton};
use cocoa::foundation::NSRect;
let window = self.ns_window().unwrap() as cocoa::base::id;
unsafe {
let close = window.standardWindowButton_(NSWindowButton::NSWindowCloseButton);
let miniaturize = window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton);
let zoom = window.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
let title_bar_container_view = close.superview().superview();
let close_rect: NSRect = msg_send![close, frame];
let button_height = close_rect.size.height;
let title_bar_frame_height = button_height + y;
let mut title_bar_rect = NSView::frame(title_bar_container_view);
title_bar_rect.size.height = title_bar_frame_height;
title_bar_rect.origin.y = NSView::frame(window).size.height - title_bar_frame_height;
let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect];
let window_buttons = vec![close, miniaturize, zoom];
let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x;
for (i, button) in window_buttons.into_iter().enumerate() {
let mut rect: NSRect = NSView::frame(button);
rect.origin.x = x + (i as f64 * space_between);
button.setFrameOrigin(rect.origin);
}
}
}
}