mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
feat: add custom titlebar
This commit is contained in:
parent
ca06f2b6ed
commit
f60e438a64
18
src-tauri/Cargo.lock
generated
18
src-tauri/Cargo.lock
generated
@ -2869,6 +2869,7 @@ dependencies = [
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-clipboard-manager",
|
||||
"tauri-plugin-decorum",
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-fs",
|
||||
"tauri-plugin-http",
|
||||
@ -5305,6 +5306,23 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-decorum"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d44342c777f49441733f657ec22da85c0660056c97f4b5db507088a7cbf399e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cocoa",
|
||||
"objc",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"thiserror",
|
||||
"windows 0.56.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.0.0-beta.7"
|
||||
|
@ -35,6 +35,7 @@ tauri-plugin-upload = "2.0.0-beta"
|
||||
tauri-plugin-window-state = "2.0.0-beta"
|
||||
webpage = { version = "2.0", features = ["serde"] }
|
||||
keyring = "2"
|
||||
tauri-plugin-decorum = "0.1.0"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
cocoa = "0.25.0"
|
||||
|
@ -36,6 +36,13 @@
|
||||
"window:allow-create",
|
||||
"window:allow-close",
|
||||
"window:allow-set-focus",
|
||||
"window:allow-center",
|
||||
"window:allow-minimize",
|
||||
"window:allow-maximize",
|
||||
"window:allow-set-size",
|
||||
"window:allow-set-focus",
|
||||
"window:allow-start-dragging",
|
||||
"decorum:allow-show-snap-overlay",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"webview:allow-create-webview-window",
|
||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:allow-open","dialog:allow-ask","dialog:allow-message","process:allow-restart","fs:allow-read-file","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
|
||||
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","window:allow-center","window:allow-minimize","window:allow-maximize","window:allow-set-size","window:allow-set-focus","window:allow-start-dragging","decorum:allow-show-snap-overlay","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:allow-open","dialog:allow-ask","dialog:allow-message","process:allow-restart","fs:allow-read-file","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
|
@ -2635,6 +2635,26 @@
|
||||
"clipboard-manager:deny-write-text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "decorum:allow-show-snap-overlay -> Enables the show_snap_overlay command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:allow-show-snap-overlay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "decorum:deny-show-snap-overlay -> Denies the show_snap_overlay command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:deny-show-snap-overlay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
@ -2635,6 +2635,26 @@
|
||||
"clipboard-manager:deny-write-text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "decorum:allow-show-snap-overlay -> Enables the show_snap_overlay command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:allow-show-snap-overlay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "decorum:deny-show-snap-overlay -> Denies the show_snap_overlay command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"decorum:deny-show-snap-overlay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
@ -6,6 +6,7 @@ use tauri::window::Effect;
|
||||
use tauri::TitleBarStyle;
|
||||
use tauri::WebviewWindowBuilder;
|
||||
use tauri::{LogicalPosition, LogicalSize, Manager, WebviewUrl};
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn create_column(
|
||||
@ -112,7 +113,7 @@ pub fn open_window(
|
||||
};
|
||||
} else {
|
||||
#[cfg(target_os = "macos")]
|
||||
let _ = WebviewWindowBuilder::new(&app_handle, label, WebviewUrl::App(PathBuf::from(url)))
|
||||
let window = WebviewWindowBuilder::new(&app_handle, label, WebviewUrl::App(PathBuf::from(url)))
|
||||
.title(title)
|
||||
.min_inner_size(width, height)
|
||||
.inner_size(width, height)
|
||||
@ -128,17 +129,20 @@ pub fn open_window(
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// [macOS] Custom traffic light possition
|
||||
// #[cfg(target_os = "macos")]
|
||||
// setup_traffic_light_positioner(app_handle.get_window(label).unwrap());
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let _ = WebviewWindowBuilder::new(&app_handle, label, WebviewUrl::App(PathBuf::from(url)))
|
||||
let window = WebviewWindowBuilder::new(&app_handle, label, WebviewUrl::App(PathBuf::from(url)))
|
||||
.title(title)
|
||||
.min_inner_size(width, height)
|
||||
.inner_size(width, height)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// Create a custom titlebar
|
||||
window.create_overlay_titlebar().unwrap();
|
||||
|
||||
// Set a custom inset to the traffic lights
|
||||
#[cfg(target_os = "macos")]
|
||||
window.set_traffic_lights_inset(8.0, 16.0).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
pub mod commands;
|
||||
pub mod nostr;
|
||||
pub mod traffic_light;
|
||||
pub mod tray;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@ -18,8 +17,7 @@ extern crate objc;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::fs;
|
||||
use tauri::Manager;
|
||||
#[cfg(target_os = "macos")]
|
||||
use traffic_light::setup_traffic_light_positioner;
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
|
||||
pub struct Nostr {
|
||||
client: Client,
|
||||
@ -28,8 +26,13 @@ pub struct Nostr {
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
// Create a custom titlebar for main window
|
||||
let main_window = app.get_webview_window("main").unwrap();
|
||||
main_window.create_overlay_titlebar().unwrap();
|
||||
|
||||
// Set a custom inset to the traffic lights
|
||||
#[cfg(target_os = "macos")]
|
||||
setup_traffic_light_positioner(app.get_window("main").unwrap());
|
||||
main_window.set_traffic_lights_inset(8.0, 16.0).unwrap();
|
||||
|
||||
// Setup app tray
|
||||
let handle = app.handle().clone();
|
||||
@ -82,6 +85,7 @@ fn main() {
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.plugin(tauri_plugin_decorum::init())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
|
@ -1,343 +0,0 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
#[cfg(target_os = "macos")]
|
||||
use rand::{distributions::Alphanumeric, Rng};
|
||||
use tauri::{
|
||||
plugin::{Builder, TauriPlugin},
|
||||
Manager, Runtime, Window,
|
||||
}; // 0.8
|
||||
|
||||
const WINDOW_CONTROL_PAD_X: f64 = 8.0;
|
||||
const WINDOW_CONTROL_PAD_Y: f64 = 16.0;
|
||||
|
||||
struct UnsafeWindowHandle(*mut std::ffi::c_void);
|
||||
unsafe impl Send for UnsafeWindowHandle {}
|
||||
unsafe impl Sync for UnsafeWindowHandle {}
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("traffic_light_positioner")
|
||||
.on_window_ready(|window| {
|
||||
#[cfg(target_os = "macos")]
|
||||
setup_traffic_light_positioner(window);
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) {
|
||||
use cocoa::appkit::{NSView, NSWindow, NSWindowButton};
|
||||
use cocoa::foundation::NSRect;
|
||||
let ns_window = ns_window_handle.0 as cocoa::base::id;
|
||||
unsafe {
|
||||
let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton);
|
||||
let miniaturize = ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton);
|
||||
let zoom = ns_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(ns_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[derive(Debug)]
|
||||
struct WindowState<R: Runtime> {
|
||||
window: Window<R>,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
|
||||
use cocoa::appkit::NSWindow;
|
||||
use cocoa::base::{id, BOOL};
|
||||
use cocoa::foundation::NSUInteger;
|
||||
use objc::runtime::{Object, Sel};
|
||||
use std::ffi::c_void;
|
||||
|
||||
// Do the initial positioning
|
||||
position_traffic_lights(
|
||||
UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")),
|
||||
WINDOW_CONTROL_PAD_X,
|
||||
WINDOW_CONTROL_PAD_Y,
|
||||
);
|
||||
|
||||
// Ensure they stay in place while resizing the window.
|
||||
fn with_window_state<R: Runtime, F: FnOnce(&mut WindowState<R>) -> T, T>(this: &Object, func: F) {
|
||||
let ptr = unsafe {
|
||||
let x: *mut c_void = *this.get_ivar("app_box");
|
||||
&mut *(x as *mut WindowState<R>)
|
||||
};
|
||||
func(ptr);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ns_win = window
|
||||
.ns_window()
|
||||
.expect("NS Window should exist to mount traffic light delegate.") as id;
|
||||
|
||||
let current_delegate: id = ns_win.delegate();
|
||||
|
||||
extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
msg_send![super_del, windowShouldClose: sender]
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_will_close(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowWillClose: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_resize<R: Runtime>(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
with_window_state(this, |state: &mut WindowState<R>| {
|
||||
let id = state
|
||||
.window
|
||||
.ns_window()
|
||||
.expect("NS window should exist on state to handle resize") as id;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
position_traffic_lights(
|
||||
UnsafeWindowHandle(id as *mut std::ffi::c_void),
|
||||
WINDOW_CONTROL_PAD_X,
|
||||
WINDOW_CONTROL_PAD_Y,
|
||||
);
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidResize: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_move(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidMove: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_change_backing_properties(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidChangeBackingProperties: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_become_key(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidBecomeKey: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_resign_key(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidResignKey: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_dragging_entered(this: &Object, _cmd: Sel, notification: id) -> BOOL {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
msg_send![super_del, draggingEntered: notification]
|
||||
}
|
||||
}
|
||||
extern "C" fn on_prepare_for_drag_operation(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) -> BOOL {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
msg_send![super_del, prepareForDragOperation: notification]
|
||||
}
|
||||
}
|
||||
extern "C" fn on_perform_drag_operation(this: &Object, _cmd: Sel, sender: id) -> BOOL {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
msg_send![super_del, performDragOperation: sender]
|
||||
}
|
||||
}
|
||||
extern "C" fn on_conclude_drag_operation(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, concludeDragOperation: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_dragging_exited(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, draggingExited: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_will_use_full_screen_presentation_options(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
window: id,
|
||||
proposed_options: NSUInteger,
|
||||
) -> NSUInteger {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
msg_send![super_del, window: window willUseFullScreenPresentationOptions: proposed_options]
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_enter_full_screen<R: Runtime>(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("did-enter-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidEnterFullScreen: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_will_enter_full_screen<R: Runtime>(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("will-enter-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowWillEnterFullScreen: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_exit_full_screen<R: Runtime>(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("did-exit-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
|
||||
let id = state.window.ns_window().expect("Failed to emit event") as id;
|
||||
position_traffic_lights(
|
||||
UnsafeWindowHandle(id as *mut std::ffi::c_void),
|
||||
WINDOW_CONTROL_PAD_X,
|
||||
WINDOW_CONTROL_PAD_Y,
|
||||
);
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidExitFullScreen: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_will_exit_full_screen<R: Runtime>(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("will-exit-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowWillExitFullScreen: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_window_did_fail_to_enter_full_screen(this: &Object, _cmd: Sel, window: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, windowDidFailToEnterFullScreen: window];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_effective_appearance_did_change(this: &Object, _cmd: Sel, notification: id) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![super_del, effectiveAppearanceDidChange: notification];
|
||||
}
|
||||
}
|
||||
extern "C" fn on_effective_appearance_did_changed_on_main_thread(
|
||||
this: &Object,
|
||||
_cmd: Sel,
|
||||
notification: id,
|
||||
) {
|
||||
unsafe {
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
let _: () = msg_send![
|
||||
super_del,
|
||||
effectiveAppearanceDidChangedOnMainThread: notification
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Are we deallocing this properly ? (I miss safe Rust :( )
|
||||
let window_label = window.label().to_string();
|
||||
|
||||
let app_state = WindowState { window };
|
||||
let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void;
|
||||
let random_str: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(20)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
|
||||
// We need to ensure we have a unique delegate name, otherwise we will panic while trying to create a duplicate
|
||||
// delegate with the same name.
|
||||
let delegate_name = format!("windowDelegate_{}_{}", window_label, random_str);
|
||||
|
||||
ns_win.setDelegate_(cocoa::delegate!(&delegate_name, {
|
||||
window: id = ns_win,
|
||||
app_box: *mut c_void = app_box,
|
||||
toolbar: id = cocoa::base::nil,
|
||||
super_delegate: id = current_delegate,
|
||||
(windowShouldClose:) => on_window_should_close as extern fn(&Object, Sel, id) -> BOOL,
|
||||
(windowWillClose:) => on_window_will_close as extern fn(&Object, Sel, id),
|
||||
(windowDidResize:) => on_window_did_resize::<R> as extern fn(&Object, Sel, id),
|
||||
(windowDidMove:) => on_window_did_move as extern fn(&Object, Sel, id),
|
||||
(windowDidChangeBackingProperties:) => on_window_did_change_backing_properties as extern fn(&Object, Sel, id),
|
||||
(windowDidBecomeKey:) => on_window_did_become_key as extern fn(&Object, Sel, id),
|
||||
(windowDidResignKey:) => on_window_did_resign_key as extern fn(&Object, Sel, id),
|
||||
(draggingEntered:) => on_dragging_entered as extern fn(&Object, Sel, id) -> BOOL,
|
||||
(prepareForDragOperation:) => on_prepare_for_drag_operation as extern fn(&Object, Sel, id) -> BOOL,
|
||||
(performDragOperation:) => on_perform_drag_operation as extern fn(&Object, Sel, id) -> BOOL,
|
||||
(concludeDragOperation:) => on_conclude_drag_operation as extern fn(&Object, Sel, id),
|
||||
(draggingExited:) => on_dragging_exited as extern fn(&Object, Sel, id),
|
||||
(window:willUseFullScreenPresentationOptions:) => on_window_will_use_full_screen_presentation_options as extern fn(&Object, Sel, id, NSUInteger) -> NSUInteger,
|
||||
(windowDidEnterFullScreen:) => on_window_did_enter_full_screen::<R> as extern fn(&Object, Sel, id),
|
||||
(windowWillEnterFullScreen:) => on_window_will_enter_full_screen::<R> as extern fn(&Object, Sel, id),
|
||||
(windowDidExitFullScreen:) => on_window_did_exit_full_screen::<R> as extern fn(&Object, Sel, id),
|
||||
(windowWillExitFullScreen:) => on_window_will_exit_full_screen::<R> as extern fn(&Object, Sel, id),
|
||||
(windowDidFailToEnterFullScreen:) => on_window_did_fail_to_enter_full_screen as extern fn(&Object, Sel, id),
|
||||
(effectiveAppearanceDidChange:) => on_effective_appearance_did_change as extern fn(&Object, Sel, id),
|
||||
(effectiveAppearanceDidChangedOnMainThread:) => on_effective_appearance_did_changed_on_main_thread as extern fn(&Object, Sel, id)
|
||||
}))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user