mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 21:31:29 +11:00
Migrate from lazy_static to once_cell
This commit is contained in:
parent
4c39b3188c
commit
2c01e9e747
|
@ -26,7 +26,7 @@ wayland-csd-adwaita-notitle = ["sctk-adwaita"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
||||||
lazy_static = "1"
|
once_cell = "1.12"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
serde = { version = "1", optional = true, features = ["serde_derive"] }
|
serde = { version = "1", optional = true, features = ["serde_derive"] }
|
||||||
raw-window-handle = "0.4.2"
|
raw-window-handle = "0.4.2"
|
||||||
|
|
|
@ -133,9 +133,6 @@
|
||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
#![cfg(target_os = "android")]
|
#![cfg(target_os = "android")]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::VecDeque,
|
||||||
|
sync::{Arc, Mutex, RwLock},
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use ndk::{
|
||||||
|
configuration::Configuration,
|
||||||
|
event::{InputEvent, KeyAction, Keycode, MotionAction},
|
||||||
|
looper::{ForeignLooper, Poll, ThreadLooper},
|
||||||
|
};
|
||||||
|
use ndk_glue::{Event, Rect};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use raw_window_handle::{AndroidNdkHandle, RawWindowHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
error,
|
error,
|
||||||
|
@ -7,32 +22,20 @@ use crate::{
|
||||||
event_loop::{self, ControlFlow},
|
event_loop::{self, ControlFlow},
|
||||||
monitor, window,
|
monitor, window,
|
||||||
};
|
};
|
||||||
use ndk::{
|
|
||||||
configuration::Configuration,
|
|
||||||
event::{InputEvent, KeyAction, Keycode, MotionAction},
|
|
||||||
looper::{ForeignLooper, Poll, ThreadLooper},
|
|
||||||
};
|
|
||||||
use ndk_glue::{Event, Rect};
|
|
||||||
use raw_window_handle::{AndroidNdkHandle, RawWindowHandle};
|
|
||||||
use std::{
|
|
||||||
collections::VecDeque,
|
|
||||||
sync::{Arc, Mutex, RwLock},
|
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
|
|
||||||
lazy_static! {
|
static CONFIG: Lazy<RwLock<Configuration>> = Lazy::new(|| {
|
||||||
static ref CONFIG: RwLock<Configuration> = RwLock::new(Configuration::from_asset_manager(
|
RwLock::new(Configuration::from_asset_manager(
|
||||||
#[allow(deprecated)] // TODO: rust-windowing/winit#2196
|
#[allow(deprecated)] // TODO: rust-windowing/winit#2196
|
||||||
&ndk_glue::native_activity().asset_manager()
|
&ndk_glue::native_activity().asset_manager(),
|
||||||
));
|
))
|
||||||
// If this is `Some()` a `Poll::Wake` is considered an `EventSource::Internal` with the event
|
});
|
||||||
// contained in the `Option`. The event is moved outside of the `Option` replacing it with a
|
// If this is `Some()` a `Poll::Wake` is considered an `EventSource::Internal` with the event
|
||||||
// `None`.
|
// contained in the `Option`. The event is moved outside of the `Option` replacing it with a
|
||||||
//
|
// `None`.
|
||||||
// This allows us to inject event into the event loop without going through `ndk-glue` and
|
//
|
||||||
// calling unsafe function that should only be called by Android.
|
// This allows us to inject event into the event loop without going through `ndk-glue` and
|
||||||
static ref INTERNAL_EVENT: RwLock<Option<InternalEvent>> = RwLock::new(None);
|
// calling unsafe function that should only be called by Android.
|
||||||
}
|
static INTERNAL_EVENT: Lazy<RwLock<Option<InternalEvent>>> = Lazy::new(|| RwLock::new(None));
|
||||||
|
|
||||||
enum InternalEvent {
|
enum InternalEvent {
|
||||||
RedrawRequested,
|
RedrawRequested,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use objc::runtime::{BOOL, YES};
|
use objc::runtime::{BOOL, YES};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
|
@ -1016,29 +1017,27 @@ impl NSOperatingSystemVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn os_capabilities() -> OSCapabilities {
|
pub fn os_capabilities() -> OSCapabilities {
|
||||||
lazy_static! {
|
static OS_CAPABILITIES: Lazy<OSCapabilities> = Lazy::new(|| {
|
||||||
static ref OS_CAPABILITIES: OSCapabilities = {
|
let version: NSOperatingSystemVersion = unsafe {
|
||||||
let version: NSOperatingSystemVersion = unsafe {
|
let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
|
||||||
let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
|
let atleast_ios_8: BOOL = msg_send![
|
||||||
let atleast_ios_8: BOOL = msg_send![
|
process_info,
|
||||||
process_info,
|
respondsToSelector: sel!(operatingSystemVersion)
|
||||||
respondsToSelector: sel!(operatingSystemVersion)
|
];
|
||||||
];
|
// winit requires atleast iOS 8 because no one has put the time into supporting earlier os versions.
|
||||||
// winit requires atleast iOS 8 because no one has put the time into supporting earlier os versions.
|
// Older iOS versions are increasingly difficult to test. For example, Xcode 11 does not support
|
||||||
// Older iOS versions are increasingly difficult to test. For example, Xcode 11 does not support
|
// debugging on devices with an iOS version of less than 8. Another example, in order to use an iOS
|
||||||
// debugging on devices with an iOS version of less than 8. Another example, in order to use an iOS
|
// simulator older than iOS 8, you must download an older version of Xcode (<9), and at least Xcode 7
|
||||||
// simulator older than iOS 8, you must download an older version of Xcode (<9), and at least Xcode 7
|
// has been tested to not even run on macOS 10.15 - Xcode 8 might?
|
||||||
// has been tested to not even run on macOS 10.15 - Xcode 8 might?
|
//
|
||||||
//
|
// The minimum required iOS version is likely to grow in the future.
|
||||||
// The minimum required iOS version is likely to grow in the future.
|
assert!(
|
||||||
assert!(
|
atleast_ios_8 == YES,
|
||||||
atleast_ios_8 == YES,
|
"`winit` requires iOS version 8 or greater"
|
||||||
"`winit` requires iOS version 8 or greater"
|
);
|
||||||
);
|
msg_send![process_info, operatingSystemVersion]
|
||||||
msg_send![process_info, operatingSystemVersion]
|
|
||||||
};
|
|
||||||
version.into()
|
|
||||||
};
|
};
|
||||||
}
|
version.into()
|
||||||
|
});
|
||||||
OS_CAPABILITIES.clone()
|
OS_CAPABILITIES.clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ use std::{collections::VecDeque, env, fmt};
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Arc};
|
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Arc};
|
||||||
|
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use raw_window_handle::RawWindowHandle;
|
use raw_window_handle::RawWindowHandle;
|
||||||
|
@ -135,10 +137,8 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
lazy_static! {
|
pub static X11_BACKEND: Lazy<Mutex<Result<Arc<XConnection>, XNotSupported>>> =
|
||||||
pub static ref X11_BACKEND: Mutex<Result<Arc<XConnection>, XNotSupported>> =
|
Lazy::new(|| Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)));
|
||||||
Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum OsError {
|
pub enum OsError {
|
||||||
|
|
|
@ -7,13 +7,12 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use super::{ffi, util, XConnection, XError};
|
use super::{ffi, util, XConnection, XError};
|
||||||
|
|
||||||
lazy_static! {
|
static GLOBAL_LOCK: Lazy<Mutex<()>> = Lazy::new(Default::default);
|
||||||
static ref GLOBAL_LOCK: Mutex<()> = Default::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<ffi::XIM> {
|
unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<ffi::XIM> {
|
||||||
let _lock = GLOBAL_LOCK.lock();
|
let _lock = GLOBAL_LOCK.lock();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::os::raw::*;
|
use std::os::raw::*;
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -18,9 +19,7 @@ use crate::{
|
||||||
// Used for testing. This should always be committed as false.
|
// Used for testing. This should always be committed as false.
|
||||||
const DISABLE_MONITOR_LIST_CACHING: bool = false;
|
const DISABLE_MONITOR_LIST_CACHING: bool = false;
|
||||||
|
|
||||||
lazy_static! {
|
static MONITORS: Lazy<Mutex<Option<Vec<MonitorHandle>>>> = Lazy::new(Mutex::default);
|
||||||
static ref MONITORS: Mutex<Option<Vec<MonitorHandle>>> = Mutex::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorHandle>> {
|
pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorHandle>> {
|
||||||
// We update this lazily.
|
// We update this lazily.
|
||||||
|
|
|
@ -5,15 +5,14 @@ use std::{
|
||||||
os::raw::*,
|
os::raw::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
type AtomCache = HashMap<CString, ffi::Atom>;
|
type AtomCache = HashMap<CString, ffi::Atom>;
|
||||||
|
|
||||||
lazy_static! {
|
static ATOM_CACHE: Lazy<Mutex<AtomCache>> = Lazy::new(|| Mutex::new(HashMap::with_capacity(2048)));
|
||||||
static ref ATOM_CACHE: Mutex<AtomCache> = Mutex::new(HashMap::with_capacity(2048));
|
|
||||||
}
|
|
||||||
|
|
||||||
impl XConnection {
|
impl XConnection {
|
||||||
pub fn get_atom<T: AsRef<CStr> + Debug>(&self, name: T) -> ffi::Atom {
|
pub fn get_atom<T: AsRef<CStr> + Debug>(&self, name: T) -> ffi::Atom {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// This info is global to the window manager.
|
// This info is global to the window manager.
|
||||||
lazy_static! {
|
static SUPPORTED_HINTS: Lazy<Mutex<Vec<ffi::Atom>>> =
|
||||||
static ref SUPPORTED_HINTS: Mutex<Vec<ffi::Atom>> = Mutex::new(Vec::with_capacity(0));
|
Lazy::new(|| Mutex::new(Vec::with_capacity(0)));
|
||||||
static ref WM_NAME: Mutex<Option<String>> = Mutex::new(None);
|
static WM_NAME: Lazy<Mutex<Option<String>>> = Lazy::new(|| Mutex::new(None));
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hint_is_supported(hint: ffi::Atom) -> bool {
|
pub fn hint_is_supported(hint: ffi::Atom) -> bool {
|
||||||
(*SUPPORTED_HINTS.lock()).contains(&hint)
|
(*SUPPORTED_HINTS.lock()).contains(&hint)
|
||||||
|
|
|
@ -8,6 +8,7 @@ use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
runtime::{Class, Object, Sel},
|
runtime::{Class, Object, Sel},
|
||||||
};
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use super::{app_state::AppState, event::EventWrapper, util, DEVICE_ID};
|
use super::{app_state::AppState, event::EventWrapper, util, DEVICE_ID};
|
||||||
use crate::event::{DeviceEvent, ElementState, Event};
|
use crate::event::{DeviceEvent, ElementState, Event};
|
||||||
|
@ -16,19 +17,17 @@ pub struct AppClass(pub *const Class);
|
||||||
unsafe impl Send for AppClass {}
|
unsafe impl Send for AppClass {}
|
||||||
unsafe impl Sync for AppClass {}
|
unsafe impl Sync for AppClass {}
|
||||||
|
|
||||||
lazy_static! {
|
pub static APP_CLASS: Lazy<AppClass> = Lazy::new(|| unsafe {
|
||||||
pub static ref APP_CLASS: AppClass = unsafe {
|
let superclass = class!(NSApplication);
|
||||||
let superclass = class!(NSApplication);
|
let mut decl = ClassDecl::new("WinitApp", superclass).unwrap();
|
||||||
let mut decl = ClassDecl::new("WinitApp", superclass).unwrap();
|
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(sendEvent:),
|
sel!(sendEvent:),
|
||||||
send_event as extern "C" fn(&Object, Sel, id),
|
send_event as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
AppClass(decl.register())
|
AppClass(decl.register())
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Normally, holding Cmd + any key never sends us a `keyUp` event for that key.
|
// Normally, holding Cmd + any key never sends us a `keyUp` event for that key.
|
||||||
// Overriding `sendEvent:` like this fixes that. (https://stackoverflow.com/a/15294196)
|
// Overriding `sendEvent:` like this fixes that. (https://stackoverflow.com/a/15294196)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use crate::{platform::macos::ActivationPolicy, platform_impl::platform::app_state::AppState};
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
os::raw::c_void,
|
||||||
|
};
|
||||||
|
|
||||||
use cocoa::base::id;
|
use cocoa::base::id;
|
||||||
use objc::{
|
use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
runtime::{Class, Object, Sel},
|
runtime::{Class, Object, Sel},
|
||||||
};
|
};
|
||||||
use std::{
|
use once_cell::sync::Lazy;
|
||||||
cell::{RefCell, RefMut},
|
|
||||||
os::raw::c_void,
|
use crate::{platform::macos::ActivationPolicy, platform_impl::platform::app_state::AppState};
|
||||||
};
|
|
||||||
|
|
||||||
static AUX_DELEGATE_STATE_NAME: &str = "auxState";
|
static AUX_DELEGATE_STATE_NAME: &str = "auxState";
|
||||||
|
|
||||||
|
@ -21,23 +23,21 @@ pub struct AppDelegateClass(pub *const Class);
|
||||||
unsafe impl Send for AppDelegateClass {}
|
unsafe impl Send for AppDelegateClass {}
|
||||||
unsafe impl Sync for AppDelegateClass {}
|
unsafe impl Sync for AppDelegateClass {}
|
||||||
|
|
||||||
lazy_static! {
|
pub static APP_DELEGATE_CLASS: Lazy<AppDelegateClass> = Lazy::new(|| unsafe {
|
||||||
pub static ref APP_DELEGATE_CLASS: AppDelegateClass = unsafe {
|
let superclass = class!(NSResponder);
|
||||||
let superclass = class!(NSResponder);
|
let mut decl = ClassDecl::new("WinitAppDelegate", superclass).unwrap();
|
||||||
let mut decl = ClassDecl::new("WinitAppDelegate", superclass).unwrap();
|
|
||||||
|
|
||||||
decl.add_class_method(sel!(new), new as extern "C" fn(&Class, Sel) -> id);
|
decl.add_class_method(sel!(new), new as extern "C" fn(&Class, Sel) -> id);
|
||||||
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidFinishLaunching:),
|
sel!(applicationDidFinishLaunching:),
|
||||||
did_finish_launching as extern "C" fn(&Object, Sel, id),
|
did_finish_launching as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_ivar::<*mut c_void>(AUX_DELEGATE_STATE_NAME);
|
decl.add_ivar::<*mut c_void>(AUX_DELEGATE_STATE_NAME);
|
||||||
|
|
||||||
AppDelegateClass(decl.register())
|
AppDelegateClass(decl.register())
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/// Safety: Assumes that Object is an instance of APP_DELEGATE_CLASS
|
/// Safety: Assumes that Object is an instance of APP_DELEGATE_CLASS
|
||||||
pub unsafe fn get_aux_state_mut(this: &Object) -> RefMut<'_, AuxDelegateState> {
|
pub unsafe fn get_aux_state_mut(this: &Object) -> RefMut<'_, AuxDelegateState> {
|
||||||
|
|
|
@ -21,6 +21,7 @@ use objc::{
|
||||||
rc::autoreleasepool,
|
rc::autoreleasepool,
|
||||||
runtime::{Object, BOOL, NO, YES},
|
runtime::{Object, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
|
@ -41,9 +42,7 @@ use crate::{
|
||||||
window::WindowId,
|
window::WindowId,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
static HANDLER: Lazy<Handler> = Lazy::new(Default::default);
|
||||||
static ref HANDLER: Handler = Default::default();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Never> Event<'a, Never> {
|
impl<'a, Never> Event<'a, Never> {
|
||||||
fn userify<T: 'static>(self) -> Event<'a, T> {
|
fn userify<T: 'static>(self) -> Event<'a, T> {
|
||||||
|
|
|
@ -18,6 +18,7 @@ use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize},
|
dpi::{LogicalPosition, LogicalSize},
|
||||||
|
@ -155,173 +156,171 @@ struct ViewClass(*const Class);
|
||||||
unsafe impl Send for ViewClass {}
|
unsafe impl Send for ViewClass {}
|
||||||
unsafe impl Sync for ViewClass {}
|
unsafe impl Sync for ViewClass {}
|
||||||
|
|
||||||
lazy_static! {
|
static VIEW_CLASS: Lazy<ViewClass> = Lazy::new(|| unsafe {
|
||||||
static ref VIEW_CLASS: ViewClass = unsafe {
|
let superclass = class!(NSView);
|
||||||
let superclass = class!(NSView);
|
let mut decl = ClassDecl::new("WinitView", superclass).unwrap();
|
||||||
let mut decl = ClassDecl::new("WinitView", superclass).unwrap();
|
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
||||||
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(initWithWinit:),
|
||||||
sel!(initWithWinit:),
|
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
||||||
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
);
|
||||||
);
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(viewDidMoveToWindow),
|
||||||
sel!(viewDidMoveToWindow),
|
view_did_move_to_window as extern "C" fn(&Object, Sel),
|
||||||
view_did_move_to_window as extern "C" fn(&Object, Sel),
|
);
|
||||||
);
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(drawRect:),
|
||||||
sel!(drawRect:),
|
draw_rect as extern "C" fn(&Object, Sel, NSRect),
|
||||||
draw_rect as extern "C" fn(&Object, Sel, NSRect),
|
);
|
||||||
);
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(acceptsFirstResponder),
|
||||||
sel!(acceptsFirstResponder),
|
accepts_first_responder as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
accepts_first_responder as extern "C" fn(&Object, Sel) -> BOOL,
|
);
|
||||||
);
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(touchBar),
|
||||||
sel!(touchBar),
|
touch_bar as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
touch_bar as extern "C" fn(&Object, Sel) -> BOOL,
|
);
|
||||||
);
|
decl.add_method(
|
||||||
decl.add_method(
|
sel!(resetCursorRects),
|
||||||
sel!(resetCursorRects),
|
reset_cursor_rects as extern "C" fn(&Object, Sel),
|
||||||
reset_cursor_rects as extern "C" fn(&Object, Sel),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// NSTextInputClient
|
// NSTextInputClient
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(hasMarkedText),
|
sel!(hasMarkedText),
|
||||||
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
|
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(markedRange),
|
sel!(markedRange),
|
||||||
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
|
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(selectedRange),
|
sel!(selectedRange),
|
||||||
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
|
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(setMarkedText:selectedRange:replacementRange:),
|
sel!(setMarkedText:selectedRange:replacementRange:),
|
||||||
set_marked_text as extern "C" fn(&mut Object, Sel, id, NSRange, NSRange),
|
set_marked_text as extern "C" fn(&mut Object, Sel, id, NSRange, NSRange),
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
|
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(validAttributesForMarkedText),
|
sel!(validAttributesForMarkedText),
|
||||||
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
|
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(attributedSubstringForProposedRange:actualRange:),
|
sel!(attributedSubstringForProposedRange:actualRange:),
|
||||||
attributed_substring_for_proposed_range
|
attributed_substring_for_proposed_range
|
||||||
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(insertText:replacementRange:),
|
sel!(insertText:replacementRange:),
|
||||||
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
|
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(characterIndexForPoint:),
|
sel!(characterIndexForPoint:),
|
||||||
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> NSUInteger,
|
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> NSUInteger,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(firstRectForCharacterRange:actualRange:),
|
sel!(firstRectForCharacterRange:actualRange:),
|
||||||
first_rect_for_character_range
|
first_rect_for_character_range
|
||||||
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> NSRect,
|
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> NSRect,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(doCommandBySelector:),
|
sel!(doCommandBySelector:),
|
||||||
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
|
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
|
||||||
);
|
);
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
decl.add_method(sel!(keyDown:), key_down as extern "C" fn(&Object, Sel, id));
|
decl.add_method(sel!(keyDown:), key_down as extern "C" fn(&Object, Sel, id));
|
||||||
decl.add_method(sel!(keyUp:), key_up as extern "C" fn(&Object, Sel, id));
|
decl.add_method(sel!(keyUp:), key_up as extern "C" fn(&Object, Sel, id));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(flagsChanged:),
|
sel!(flagsChanged:),
|
||||||
flags_changed as extern "C" fn(&Object, Sel, id),
|
flags_changed as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(insertTab:),
|
sel!(insertTab:),
|
||||||
insert_tab as extern "C" fn(&Object, Sel, id),
|
insert_tab as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(insertBackTab:),
|
sel!(insertBackTab:),
|
||||||
insert_back_tab as extern "C" fn(&Object, Sel, id),
|
insert_back_tab as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(mouseDown:),
|
sel!(mouseDown:),
|
||||||
mouse_down as extern "C" fn(&Object, Sel, id),
|
mouse_down as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(mouseUp:), mouse_up as extern "C" fn(&Object, Sel, id));
|
decl.add_method(sel!(mouseUp:), mouse_up as extern "C" fn(&Object, Sel, id));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(rightMouseDown:),
|
sel!(rightMouseDown:),
|
||||||
right_mouse_down as extern "C" fn(&Object, Sel, id),
|
right_mouse_down as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(rightMouseUp:),
|
sel!(rightMouseUp:),
|
||||||
right_mouse_up as extern "C" fn(&Object, Sel, id),
|
right_mouse_up as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(otherMouseDown:),
|
sel!(otherMouseDown:),
|
||||||
other_mouse_down as extern "C" fn(&Object, Sel, id),
|
other_mouse_down as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(otherMouseUp:),
|
sel!(otherMouseUp:),
|
||||||
other_mouse_up as extern "C" fn(&Object, Sel, id),
|
other_mouse_up as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(mouseMoved:),
|
sel!(mouseMoved:),
|
||||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
mouse_moved as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(mouseDragged:),
|
sel!(mouseDragged:),
|
||||||
mouse_dragged as extern "C" fn(&Object, Sel, id),
|
mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(rightMouseDragged:),
|
sel!(rightMouseDragged:),
|
||||||
right_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
right_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(otherMouseDragged:),
|
sel!(otherMouseDragged:),
|
||||||
other_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
other_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(mouseEntered:),
|
sel!(mouseEntered:),
|
||||||
mouse_entered as extern "C" fn(&Object, Sel, id),
|
mouse_entered as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(mouseExited:),
|
sel!(mouseExited:),
|
||||||
mouse_exited as extern "C" fn(&Object, Sel, id),
|
mouse_exited as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(scrollWheel:),
|
sel!(scrollWheel:),
|
||||||
scroll_wheel as extern "C" fn(&Object, Sel, id),
|
scroll_wheel as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(pressureChangeWithEvent:),
|
sel!(pressureChangeWithEvent:),
|
||||||
pressure_change_with_event as extern "C" fn(&Object, Sel, id),
|
pressure_change_with_event as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(_wantsKeyDownForEvent:),
|
sel!(_wantsKeyDownForEvent:),
|
||||||
wants_key_down_for_event as extern "C" fn(&Object, Sel, id) -> BOOL,
|
wants_key_down_for_event as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(cancelOperation:),
|
sel!(cancelOperation:),
|
||||||
cancel_operation as extern "C" fn(&Object, Sel, id),
|
cancel_operation as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(frameDidChange:),
|
sel!(frameDidChange:),
|
||||||
frame_did_change as extern "C" fn(&Object, Sel, id),
|
frame_did_change as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(acceptsFirstMouse:),
|
sel!(acceptsFirstMouse:),
|
||||||
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
|
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_ivar::<*mut c_void>("winitState");
|
decl.add_ivar::<*mut c_void>("winitState");
|
||||||
decl.add_ivar::<id>("markedText");
|
decl.add_ivar::<id>("markedText");
|
||||||
let protocol = Protocol::get("NSTextInputClient").unwrap();
|
let protocol = Protocol::get("NSTextInputClient").unwrap();
|
||||||
decl.add_protocol(protocol);
|
decl.add_protocol(protocol);
|
||||||
ViewClass(decl.register())
|
ViewClass(decl.register())
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn dealloc(this: &Object, _sel: Sel) {
|
extern "C" fn dealloc(this: &Object, _sel: Sel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -46,6 +46,7 @@ use objc::{
|
||||||
rc::autoreleasepool,
|
rc::autoreleasepool,
|
||||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct WindowId(pub usize);
|
pub struct WindowId(pub usize);
|
||||||
|
@ -246,32 +247,30 @@ struct WindowClass(*const Class);
|
||||||
unsafe impl Send for WindowClass {}
|
unsafe impl Send for WindowClass {}
|
||||||
unsafe impl Sync for WindowClass {}
|
unsafe impl Sync for WindowClass {}
|
||||||
|
|
||||||
lazy_static! {
|
static WINDOW_CLASS: Lazy<WindowClass> = Lazy::new(|| unsafe {
|
||||||
static ref WINDOW_CLASS: WindowClass = unsafe {
|
let window_superclass = class!(NSWindow);
|
||||||
let window_superclass = class!(NSWindow);
|
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
|
||||||
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
|
|
||||||
|
|
||||||
pub extern "C" fn can_become_main_window(_: &Object, _: Sel) -> BOOL {
|
pub extern "C" fn can_become_main_window(_: &Object, _: Sel) -> BOOL {
|
||||||
trace_scope!("canBecomeMainWindow");
|
trace_scope!("canBecomeMainWindow");
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn can_become_key_window(_: &Object, _: Sel) -> BOOL {
|
pub extern "C" fn can_become_key_window(_: &Object, _: Sel) -> BOOL {
|
||||||
trace_scope!("canBecomeKeyWindow");
|
trace_scope!("canBecomeKeyWindow");
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(canBecomeMainWindow),
|
sel!(canBecomeMainWindow),
|
||||||
can_become_main_window as extern "C" fn(&Object, Sel) -> BOOL,
|
can_become_main_window as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(canBecomeKeyWindow),
|
sel!(canBecomeKeyWindow),
|
||||||
can_become_key_window as extern "C" fn(&Object, Sel) -> BOOL,
|
can_become_key_window as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
);
|
||||||
WindowClass(decl.register())
|
WindowClass(decl.register())
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SharedState {
|
pub struct SharedState {
|
||||||
|
|
|
@ -14,6 +14,7 @@ use objc::{
|
||||||
rc::autoreleasepool,
|
rc::autoreleasepool,
|
||||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize},
|
dpi::{LogicalPosition, LogicalSize},
|
||||||
|
@ -134,97 +135,95 @@ struct WindowDelegateClass(*const Class);
|
||||||
unsafe impl Send for WindowDelegateClass {}
|
unsafe impl Send for WindowDelegateClass {}
|
||||||
unsafe impl Sync for WindowDelegateClass {}
|
unsafe impl Sync for WindowDelegateClass {}
|
||||||
|
|
||||||
lazy_static! {
|
static WINDOW_DELEGATE_CLASS: Lazy<WindowDelegateClass> = Lazy::new(|| unsafe {
|
||||||
static ref WINDOW_DELEGATE_CLASS: WindowDelegateClass = unsafe {
|
let superclass = class!(NSResponder);
|
||||||
let superclass = class!(NSResponder);
|
let mut decl = ClassDecl::new("WinitWindowDelegate", superclass).unwrap();
|
||||||
let mut decl = ClassDecl::new("WinitWindowDelegate", superclass).unwrap();
|
|
||||||
|
|
||||||
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(initWithWinit:),
|
sel!(initWithWinit:),
|
||||||
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowShouldClose:),
|
sel!(windowShouldClose:),
|
||||||
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
|
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillClose:),
|
sel!(windowWillClose:),
|
||||||
window_will_close as extern "C" fn(&Object, Sel, id),
|
window_will_close as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidResize:),
|
sel!(windowDidResize:),
|
||||||
window_did_resize as extern "C" fn(&Object, Sel, id),
|
window_did_resize as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidMove:),
|
sel!(windowDidMove:),
|
||||||
window_did_move as extern "C" fn(&Object, Sel, id),
|
window_did_move as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidChangeBackingProperties:),
|
sel!(windowDidChangeBackingProperties:),
|
||||||
window_did_change_backing_properties as extern "C" fn(&Object, Sel, id),
|
window_did_change_backing_properties as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidBecomeKey:),
|
sel!(windowDidBecomeKey:),
|
||||||
window_did_become_key as extern "C" fn(&Object, Sel, id),
|
window_did_become_key as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidResignKey:),
|
sel!(windowDidResignKey:),
|
||||||
window_did_resign_key as extern "C" fn(&Object, Sel, id),
|
window_did_resign_key as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(draggingEntered:),
|
sel!(draggingEntered:),
|
||||||
dragging_entered as extern "C" fn(&Object, Sel, id) -> BOOL,
|
dragging_entered as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
prepare_for_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
|
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(draggingExited:),
|
sel!(draggingExited:),
|
||||||
dragging_exited as extern "C" fn(&Object, Sel, id),
|
dragging_exited as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(window:willUseFullScreenPresentationOptions:),
|
sel!(window:willUseFullScreenPresentationOptions:),
|
||||||
window_will_use_fullscreen_presentation_options
|
window_will_use_fullscreen_presentation_options
|
||||||
as extern "C" fn(&Object, Sel, id, NSUInteger) -> NSUInteger,
|
as extern "C" fn(&Object, Sel, id, NSUInteger) -> NSUInteger,
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidEnterFullScreen:),
|
sel!(windowDidEnterFullScreen:),
|
||||||
window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillEnterFullScreen:),
|
sel!(windowWillEnterFullScreen:),
|
||||||
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidExitFullScreen:),
|
sel!(windowDidExitFullScreen:),
|
||||||
window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillExitFullScreen:),
|
sel!(windowWillExitFullScreen:),
|
||||||
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidFailToEnterFullScreen:),
|
sel!(windowDidFailToEnterFullScreen:),
|
||||||
window_did_fail_to_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
window_did_fail_to_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_ivar::<*mut c_void>("winitState");
|
decl.add_ivar::<*mut c_void>("winitState");
|
||||||
WindowDelegateClass(decl.register())
|
WindowDelegateClass(decl.register())
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// This function is definitely unsafe, but labeling that would increase
|
// This function is definitely unsafe, but labeling that would increase
|
||||||
// boilerplate and wouldn't really clarify anything...
|
// boilerplate and wouldn't really clarify anything...
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/// which is inspired by the solution in https://github.com/ysc3839/win32-darkmode
|
/// which is inspired by the solution in https://github.com/ysc3839/win32-darkmode
|
||||||
use std::{ffi::c_void, ptr};
|
use std::{ffi::c_void, ptr};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use windows_sys::{
|
use windows_sys::{
|
||||||
core::PCSTR,
|
core::PCSTR,
|
||||||
Win32::{
|
Win32::{
|
||||||
|
@ -22,47 +23,45 @@ use crate::window::Theme;
|
||||||
|
|
||||||
use super::util;
|
use super::util;
|
||||||
|
|
||||||
lazy_static! {
|
static WIN10_BUILD_VERSION: Lazy<Option<u32>> = Lazy::new(|| {
|
||||||
static ref WIN10_BUILD_VERSION: Option<u32> = {
|
type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> NTSTATUS;
|
||||||
type RtlGetVersion = unsafe extern "system" fn (*mut OSVERSIONINFOW) -> NTSTATUS;
|
let handle = get_function!("ntdll.dll", RtlGetVersion);
|
||||||
let handle = get_function!("ntdll.dll", RtlGetVersion);
|
|
||||||
|
|
||||||
if let Some(rtl_get_version) = handle {
|
if let Some(rtl_get_version) = handle {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut vi = OSVERSIONINFOW {
|
let mut vi = OSVERSIONINFOW {
|
||||||
dwOSVersionInfoSize: 0,
|
dwOSVersionInfoSize: 0,
|
||||||
dwMajorVersion: 0,
|
dwMajorVersion: 0,
|
||||||
dwMinorVersion: 0,
|
dwMinorVersion: 0,
|
||||||
dwBuildNumber: 0,
|
dwBuildNumber: 0,
|
||||||
dwPlatformId: 0,
|
dwPlatformId: 0,
|
||||||
szCSDVersion: [0; 128],
|
szCSDVersion: [0; 128],
|
||||||
};
|
};
|
||||||
|
|
||||||
let status = (rtl_get_version)(&mut vi);
|
let status = (rtl_get_version)(&mut vi);
|
||||||
|
|
||||||
if status >= 0 && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 {
|
if status >= 0 && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 {
|
||||||
Some(vi.dwBuildNumber)
|
Some(vi.dwBuildNumber)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
static ref DARK_MODE_SUPPORTED: bool = {
|
static DARK_MODE_SUPPORTED: Lazy<bool> = Lazy::new(|| {
|
||||||
// We won't try to do anything for windows versions < 17763
|
// We won't try to do anything for windows versions < 17763
|
||||||
// (Windows 10 October 2018 update)
|
// (Windows 10 October 2018 update)
|
||||||
match *WIN10_BUILD_VERSION {
|
match *WIN10_BUILD_VERSION {
|
||||||
Some(v) => v >= 17763,
|
Some(v) => v >= 17763,
|
||||||
None => false
|
None => false,
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
static ref DARK_THEME_NAME: Vec<u16> = util::encode_wide("DarkMode_Explorer");
|
static DARK_THEME_NAME: Lazy<Vec<u16>> = Lazy::new(|| util::encode_wide("DarkMode_Explorer"));
|
||||||
static ref LIGHT_THEME_NAME: Vec<u16> = util::encode_wide("");
|
static LIGHT_THEME_NAME: Lazy<Vec<u16>> = Lazy::new(|| util::encode_wide(""));
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to set a theme on a window, if necessary.
|
/// Attempt to set a theme on a window, if necessary.
|
||||||
/// Returns the theme that was picked
|
/// Returns the theme that was picked
|
||||||
|
@ -113,10 +112,8 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool {
|
||||||
cbData: usize,
|
cbData: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
static SET_WINDOW_COMPOSITION_ATTRIBUTE: Lazy<Option<SetWindowCompositionAttribute>> =
|
||||||
static ref SET_WINDOW_COMPOSITION_ATTRIBUTE: Option<SetWindowCompositionAttribute> =
|
Lazy::new(|| get_function!("user32.dll", SetWindowCompositionAttribute));
|
||||||
get_function!("user32.dll", SetWindowCompositionAttribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(set_window_composition_attribute) = *SET_WINDOW_COMPOSITION_ATTRIBUTE {
|
if let Some(set_window_composition_attribute) = *SET_WINDOW_COMPOSITION_ATTRIBUTE {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -144,23 +141,19 @@ fn should_use_dark_mode() -> bool {
|
||||||
|
|
||||||
fn should_apps_use_dark_mode() -> bool {
|
fn should_apps_use_dark_mode() -> bool {
|
||||||
type ShouldAppsUseDarkMode = unsafe extern "system" fn() -> bool;
|
type ShouldAppsUseDarkMode = unsafe extern "system" fn() -> bool;
|
||||||
lazy_static! {
|
static SHOULD_APPS_USE_DARK_MODE: Lazy<Option<ShouldAppsUseDarkMode>> = Lazy::new(|| unsafe {
|
||||||
static ref SHOULD_APPS_USE_DARK_MODE: Option<ShouldAppsUseDarkMode> = {
|
const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: PCSTR = 132 as PCSTR;
|
||||||
unsafe {
|
|
||||||
const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: PCSTR = 132 as PCSTR;
|
|
||||||
|
|
||||||
let module = LoadLibraryA("uxtheme.dll\0".as_ptr());
|
let module = LoadLibraryA("uxtheme.dll\0".as_ptr());
|
||||||
|
|
||||||
if module == 0 {
|
if module == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let handle = GetProcAddress(module, UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL);
|
let handle = GetProcAddress(module, UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL);
|
||||||
|
|
||||||
handle.map(|handle| std::mem::transmute(handle))
|
handle.map(|handle| std::mem::transmute(handle))
|
||||||
}
|
});
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHOULD_APPS_USE_DARK_MODE
|
SHOULD_APPS_USE_DARK_MODE
|
||||||
.map(|should_apps_use_dark_mode| unsafe { (should_apps_use_dark_mode)() })
|
.map(|should_apps_use_dark_mode| unsafe { (should_apps_use_dark_mode)() })
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
mod runner;
|
mod runner;
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
|
@ -112,18 +113,17 @@ type GetPointerTouchInfo =
|
||||||
type GetPointerPenInfo =
|
type GetPointerPenInfo =
|
||||||
unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL;
|
unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL;
|
||||||
|
|
||||||
lazy_static! {
|
static GET_POINTER_FRAME_INFO_HISTORY: Lazy<Option<GetPointerFrameInfoHistory>> =
|
||||||
static ref GET_POINTER_FRAME_INFO_HISTORY: Option<GetPointerFrameInfoHistory> =
|
Lazy::new(|| get_function!("user32.dll", GetPointerFrameInfoHistory));
|
||||||
get_function!("user32.dll", GetPointerFrameInfoHistory);
|
static SKIP_POINTER_FRAME_MESSAGES: Lazy<Option<SkipPointerFrameMessages>> =
|
||||||
static ref SKIP_POINTER_FRAME_MESSAGES: Option<SkipPointerFrameMessages> =
|
Lazy::new(|| get_function!("user32.dll", SkipPointerFrameMessages));
|
||||||
get_function!("user32.dll", SkipPointerFrameMessages);
|
static GET_POINTER_DEVICE_RECTS: Lazy<Option<GetPointerDeviceRects>> =
|
||||||
static ref GET_POINTER_DEVICE_RECTS: Option<GetPointerDeviceRects> =
|
Lazy::new(|| get_function!("user32.dll", GetPointerDeviceRects));
|
||||||
get_function!("user32.dll", GetPointerDeviceRects);
|
static GET_POINTER_TOUCH_INFO: Lazy<Option<GetPointerTouchInfo>> =
|
||||||
static ref GET_POINTER_TOUCH_INFO: Option<GetPointerTouchInfo> =
|
Lazy::new(|| get_function!("user32.dll", GetPointerTouchInfo));
|
||||||
get_function!("user32.dll", GetPointerTouchInfo);
|
static GET_POINTER_PEN_INFO: Lazy<Option<GetPointerPenInfo>> =
|
||||||
static ref GET_POINTER_PEN_INFO: Option<GetPointerPenInfo> =
|
Lazy::new(|| get_function!("user32.dll", GetPointerPenInfo));
|
||||||
get_function!("user32.dll", GetPointerPenInfo);
|
|
||||||
}
|
|
||||||
pub(crate) struct WindowData<T: 'static> {
|
pub(crate) struct WindowData<T: 'static> {
|
||||||
pub window_state: Arc<Mutex<WindowState>>,
|
pub window_state: Arc<Mutex<WindowState>>,
|
||||||
pub event_loop_runner: EventLoopRunnerShared<T>,
|
pub event_loop_runner: EventLoopRunnerShared<T>,
|
||||||
|
@ -375,19 +375,17 @@ fn get_wait_thread_id() -> u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
static WAIT_PERIOD_MIN: Lazy<Option<u32>> = Lazy::new(|| unsafe {
|
||||||
static ref WAIT_PERIOD_MIN: Option<u32> = unsafe {
|
let mut caps = TIMECAPS {
|
||||||
let mut caps = TIMECAPS {
|
wPeriodMin: 0,
|
||||||
wPeriodMin: 0,
|
wPeriodMax: 0,
|
||||||
wPeriodMax: 0,
|
|
||||||
};
|
|
||||||
if timeGetDevCaps(&mut caps, mem::size_of::<TIMECAPS>() as u32) == TIMERR_NOERROR {
|
|
||||||
Some(caps.wPeriodMin)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
if timeGetDevCaps(&mut caps, mem::size_of::<TIMECAPS>() as u32) == TIMERR_NOERROR {
|
||||||
|
Some(caps.wPeriodMin)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fn wait_thread(parent_thread_id: u32, msg_window_id: HWND) {
|
fn wait_thread(parent_thread_id: u32, msg_window_id: HWND) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -582,59 +580,36 @@ impl<T: 'static> EventLoopProxy<T> {
|
||||||
|
|
||||||
type WaitUntilInstantBox = Box<Instant>;
|
type WaitUntilInstantBox = Box<Instant>;
|
||||||
|
|
||||||
lazy_static! {
|
// Message sent by the `EventLoopProxy` when we want to wake up the thread.
|
||||||
// Message sent by the `EventLoopProxy` when we want to wake up the thread.
|
// WPARAM and LPARAM are unused.
|
||||||
// WPARAM and LPARAM are unused.
|
static USER_EVENT_MSG_ID: Lazy<u32> =
|
||||||
static ref USER_EVENT_MSG_ID: u32 = {
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::WakeupMsg\0".as_ptr()) });
|
||||||
unsafe {
|
// Message sent when we want to execute a closure in the thread.
|
||||||
RegisterWindowMessageA("Winit::WakeupMsg\0".as_ptr())
|
// WPARAM contains a Box<Box<dyn FnMut()>> that must be retrieved with `Box::from_raw`,
|
||||||
}
|
// and LPARAM is unused.
|
||||||
};
|
static EXEC_MSG_ID: Lazy<u32> =
|
||||||
// Message sent when we want to execute a closure in the thread.
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr()) });
|
||||||
// WPARAM contains a Box<Box<dyn FnMut()>> that must be retrieved with `Box::from_raw`,
|
static PROCESS_NEW_EVENTS_MSG_ID: Lazy<u32> =
|
||||||
// and LPARAM is unused.
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::ProcessNewEvents\0".as_ptr()) });
|
||||||
static ref EXEC_MSG_ID: u32 = {
|
/// lparam is the wait thread's message id.
|
||||||
unsafe {
|
static SEND_WAIT_THREAD_ID_MSG_ID: Lazy<u32> =
|
||||||
RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr())
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::SendWaitThreadId\0".as_ptr()) });
|
||||||
}
|
/// lparam points to a `Box<Instant>` signifying the time `PROCESS_NEW_EVENTS_MSG_ID` should
|
||||||
};
|
/// be sent.
|
||||||
static ref PROCESS_NEW_EVENTS_MSG_ID: u32 = {
|
static WAIT_UNTIL_MSG_ID: Lazy<u32> =
|
||||||
unsafe {
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::WaitUntil\0".as_ptr()) });
|
||||||
RegisterWindowMessageA("Winit::ProcessNewEvents\0".as_ptr())
|
static CANCEL_WAIT_UNTIL_MSG_ID: Lazy<u32> =
|
||||||
}
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::CancelWaitUntil\0".as_ptr()) });
|
||||||
};
|
// Message sent by a `Window` when it wants to be destroyed by the main thread.
|
||||||
/// lparam is the wait thread's message id.
|
// WPARAM and LPARAM are unused.
|
||||||
static ref SEND_WAIT_THREAD_ID_MSG_ID: u32 = {
|
pub static DESTROY_MSG_ID: Lazy<u32> =
|
||||||
unsafe {
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::DestroyMsg\0".as_ptr()) });
|
||||||
RegisterWindowMessageA("Winit::SendWaitThreadId\0".as_ptr())
|
// WPARAM is a bool specifying the `WindowFlags::MARKER_RETAIN_STATE_ON_SIZE` flag. See the
|
||||||
}
|
// documentation in the `window_state` module for more information.
|
||||||
};
|
pub static SET_RETAIN_STATE_ON_SIZE_MSG_ID: Lazy<u32> =
|
||||||
/// lparam points to a `Box<Instant>` signifying the time `PROCESS_NEW_EVENTS_MSG_ID` should
|
Lazy::new(|| unsafe { RegisterWindowMessageA("Winit::SetRetainMaximized\0".as_ptr()) });
|
||||||
/// be sent.
|
static THREAD_EVENT_TARGET_WINDOW_CLASS: Lazy<Vec<u16>> =
|
||||||
static ref WAIT_UNTIL_MSG_ID: u32 = {
|
Lazy::new(|| util::encode_wide("Winit Thread Event Target"));
|
||||||
unsafe {
|
|
||||||
RegisterWindowMessageA("Winit::WaitUntil\0".as_ptr())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static ref CANCEL_WAIT_UNTIL_MSG_ID: u32 = {
|
|
||||||
unsafe {
|
|
||||||
RegisterWindowMessageA("Winit::CancelWaitUntil\0".as_ptr())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Message sent by a `Window` when it wants to be destroyed by the main thread.
|
|
||||||
// WPARAM and LPARAM are unused.
|
|
||||||
pub static ref DESTROY_MSG_ID: u32 = {
|
|
||||||
unsafe {
|
|
||||||
RegisterWindowMessageA("Winit::DestroyMsg\0".as_ptr())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// WPARAM is a bool specifying the `WindowFlags::MARKER_RETAIN_STATE_ON_SIZE` flag. See the
|
|
||||||
// documentation in the `window_state` module for more information.
|
|
||||||
pub static ref SET_RETAIN_STATE_ON_SIZE_MSG_ID: u32 = unsafe {
|
|
||||||
RegisterWindowMessageA("Winit::SetRetainMaximized\0".as_ptr())
|
|
||||||
};
|
|
||||||
static ref THREAD_EVENT_TARGET_WINDOW_CLASS: Vec<u16> = util::encode_wide("Winit Thread Event Target");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_event_target_window<T: 'static>() -> HWND {
|
fn create_event_target_window<T: 'static>() -> HWND {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::{
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use windows_sys::{
|
use windows_sys::{
|
||||||
core::{HRESULT, PCWSTR},
|
core::{HRESULT, PCWSTR},
|
||||||
Win32::{
|
Win32::{
|
||||||
|
@ -298,19 +299,17 @@ pub type AdjustWindowRectExForDpi = unsafe extern "system" fn(
|
||||||
dpi: u32,
|
dpi: u32,
|
||||||
) -> BOOL;
|
) -> BOOL;
|
||||||
|
|
||||||
lazy_static! {
|
pub static GET_DPI_FOR_WINDOW: Lazy<Option<GetDpiForWindow>> =
|
||||||
pub static ref GET_DPI_FOR_WINDOW: Option<GetDpiForWindow> =
|
Lazy::new(|| get_function!("user32.dll", GetDpiForWindow));
|
||||||
get_function!("user32.dll", GetDpiForWindow);
|
pub static ADJUST_WINDOW_RECT_EX_FOR_DPI: Lazy<Option<AdjustWindowRectExForDpi>> =
|
||||||
pub static ref ADJUST_WINDOW_RECT_EX_FOR_DPI: Option<AdjustWindowRectExForDpi> =
|
Lazy::new(|| get_function!("user32.dll", AdjustWindowRectExForDpi));
|
||||||
get_function!("user32.dll", AdjustWindowRectExForDpi);
|
pub static GET_DPI_FOR_MONITOR: Lazy<Option<GetDpiForMonitor>> =
|
||||||
pub static ref GET_DPI_FOR_MONITOR: Option<GetDpiForMonitor> =
|
Lazy::new(|| get_function!("shcore.dll", GetDpiForMonitor));
|
||||||
get_function!("shcore.dll", GetDpiForMonitor);
|
pub static ENABLE_NON_CLIENT_DPI_SCALING: Lazy<Option<EnableNonClientDpiScaling>> =
|
||||||
pub static ref ENABLE_NON_CLIENT_DPI_SCALING: Option<EnableNonClientDpiScaling> =
|
Lazy::new(|| get_function!("user32.dll", EnableNonClientDpiScaling));
|
||||||
get_function!("user32.dll", EnableNonClientDpiScaling);
|
pub static SET_PROCESS_DPI_AWARENESS_CONTEXT: Lazy<Option<SetProcessDpiAwarenessContext>> =
|
||||||
pub static ref SET_PROCESS_DPI_AWARENESS_CONTEXT: Option<SetProcessDpiAwarenessContext> =
|
Lazy::new(|| get_function!("user32.dll", SetProcessDpiAwarenessContext));
|
||||||
get_function!("user32.dll", SetProcessDpiAwarenessContext);
|
pub static SET_PROCESS_DPI_AWARENESS: Lazy<Option<SetProcessDpiAwareness>> =
|
||||||
pub static ref SET_PROCESS_DPI_AWARENESS: Option<SetProcessDpiAwareness> =
|
Lazy::new(|| get_function!("shcore.dll", SetProcessDpiAwareness));
|
||||||
get_function!("shcore.dll", SetProcessDpiAwareness);
|
pub static SET_PROCESS_DPI_AWARE: Lazy<Option<SetProcessDPIAware>> =
|
||||||
pub static ref SET_PROCESS_DPI_AWARE: Option<SetProcessDPIAware> =
|
Lazy::new(|| get_function!("user32.dll", SetProcessDPIAware));
|
||||||
get_function!("user32.dll", SetProcessDPIAware);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue