Format everything and add rustfmt to travis (#951)
* Format everything and add rustfmt to travis * Remove extern crate winit from examples and add force_multiline_blocks * Format the code properly * Fix inconsistent period in PULL_REQUEST_TEMPLATE.md * Only run rustfmt on nightly * Travis fixings
This commit is contained in:
parent
b1b5aefc4b
commit
e2c84725de
109 changed files with 4787 additions and 3679 deletions
|
|
@ -1,10 +1,18 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use cocoa::{appkit::{self, NSEvent}, base::id};
|
||||
use objc::{declare::ClassDecl, runtime::{Class, Object, Sel}};
|
||||
use cocoa::{
|
||||
appkit::{self, NSEvent},
|
||||
base::id,
|
||||
};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Sel},
|
||||
};
|
||||
|
||||
use crate::event::{DeviceEvent, Event};
|
||||
use crate::platform_impl::platform::{app_state::AppState, DEVICE_ID, util};
|
||||
use crate::{
|
||||
event::{DeviceEvent, Event},
|
||||
platform_impl::platform::{app_state::AppState, util, DEVICE_ID},
|
||||
};
|
||||
|
||||
pub struct AppClass(pub *const Class);
|
||||
unsafe impl Send for AppClass {}
|
||||
|
|
@ -17,7 +25,7 @@ lazy_static! {
|
|||
|
||||
decl.add_method(
|
||||
sel!(sendEvent:),
|
||||
send_event as extern fn(&Object, Sel, id),
|
||||
send_event as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
AppClass(decl.register())
|
||||
|
|
@ -27,23 +35,25 @@ lazy_static! {
|
|||
// 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)
|
||||
// Fun fact: Firefox still has this bug! (https://bugzilla.mozilla.org/show_bug.cgi?id=1299553)
|
||||
extern fn send_event(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn send_event(this: &Object, _sel: Sel, event: id) {
|
||||
unsafe {
|
||||
// For posterity, there are some undocumented event types
|
||||
// (https://github.com/servo/cocoa-rs/issues/155)
|
||||
// but that doesn't really matter here.
|
||||
let event_type = event.eventType();
|
||||
let modifier_flags = event.modifierFlags();
|
||||
if event_type == appkit::NSKeyUp && util::has_flag(
|
||||
modifier_flags,
|
||||
appkit::NSEventModifierFlags::NSCommandKeyMask,
|
||||
) {
|
||||
if event_type == appkit::NSKeyUp
|
||||
&& util::has_flag(
|
||||
modifier_flags,
|
||||
appkit::NSEventModifierFlags::NSCommandKeyMask,
|
||||
)
|
||||
{
|
||||
let key_window: id = msg_send![this, keyWindow];
|
||||
let _: () = msg_send![key_window, sendEvent:event];
|
||||
let _: () = msg_send![key_window, sendEvent: event];
|
||||
} else {
|
||||
maybe_dispatch_device_event(event);
|
||||
let superclass = util::superclass(this);
|
||||
let _: () = msg_send![super(this, superclass), sendEvent:event];
|
||||
let _: () = msg_send![super(this, superclass), sendEvent: event];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,10 +61,10 @@ extern fn send_event(this: &Object, _sel: Sel, event: id) {
|
|||
unsafe fn maybe_dispatch_device_event(event: id) {
|
||||
let event_type = event.eventType();
|
||||
match event_type {
|
||||
appkit::NSMouseMoved |
|
||||
appkit::NSLeftMouseDragged |
|
||||
appkit::NSOtherMouseDragged |
|
||||
appkit::NSRightMouseDragged => {
|
||||
appkit::NSMouseMoved
|
||||
| appkit::NSLeftMouseDragged
|
||||
| appkit::NSOtherMouseDragged
|
||||
| appkit::NSRightMouseDragged => {
|
||||
let mut events = VecDeque::with_capacity(3);
|
||||
|
||||
let delta_x = event.deltaX() as f64;
|
||||
|
|
@ -63,21 +73,29 @@ unsafe fn maybe_dispatch_device_event(event: id) {
|
|||
if delta_x != 0.0 {
|
||||
events.push_back(Event::DeviceEvent {
|
||||
device_id: DEVICE_ID,
|
||||
event: DeviceEvent::Motion { axis: 0, value: delta_x },
|
||||
event: DeviceEvent::Motion {
|
||||
axis: 0,
|
||||
value: delta_x,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if delta_y != 0.0 {
|
||||
events.push_back(Event::DeviceEvent {
|
||||
device_id: DEVICE_ID,
|
||||
event: DeviceEvent::Motion { axis: 1, value: delta_y },
|
||||
event: DeviceEvent::Motion {
|
||||
axis: 1,
|
||||
value: delta_y,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if delta_x != 0.0 || delta_y != 0.0 {
|
||||
events.push_back(Event::DeviceEvent {
|
||||
device_id: DEVICE_ID,
|
||||
event: DeviceEvent::MouseMotion { delta: (delta_x, delta_y) },
|
||||
event: DeviceEvent::MouseMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use cocoa::base::id;
|
||||
use objc::{runtime::{Class, Object, Sel, BOOL, YES}, declare::ClassDecl};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Sel, BOOL, YES},
|
||||
};
|
||||
|
||||
use crate::platform_impl::platform::app_state::AppState;
|
||||
|
||||
|
|
@ -14,41 +17,41 @@ lazy_static! {
|
|||
|
||||
decl.add_method(
|
||||
sel!(applicationDidFinishLaunching:),
|
||||
did_finish_launching as extern fn(&Object, Sel, id) -> BOOL,
|
||||
did_finish_launching as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidBecomeActive:),
|
||||
did_become_active as extern fn(&Object, Sel, id),
|
||||
did_become_active as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillResignActive:),
|
||||
will_resign_active as extern fn(&Object, Sel, id),
|
||||
will_resign_active as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillEnterForeground:),
|
||||
will_enter_foreground as extern fn(&Object, Sel, id),
|
||||
will_enter_foreground as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidEnterBackground:),
|
||||
did_enter_background as extern fn(&Object, Sel, id),
|
||||
did_enter_background as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillTerminate:),
|
||||
will_terminate as extern fn(&Object, Sel, id),
|
||||
will_terminate as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
AppDelegateClass(decl.register())
|
||||
};
|
||||
}
|
||||
|
||||
extern fn did_finish_launching(_: &Object, _: Sel, _: id) -> BOOL {
|
||||
extern "C" fn did_finish_launching(_: &Object, _: Sel, _: id) -> BOOL {
|
||||
trace!("Triggered `didFinishLaunching`");
|
||||
AppState::launched();
|
||||
trace!("Completed `didFinishLaunching`");
|
||||
YES
|
||||
}
|
||||
|
||||
extern fn did_become_active(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn did_become_active(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `didBecomeActive`");
|
||||
/*unsafe {
|
||||
HANDLER.lock().unwrap().handle_nonuser_event(Event::Suspended(false))
|
||||
|
|
@ -56,7 +59,7 @@ extern fn did_become_active(_: &Object, _: Sel, _: id) {
|
|||
trace!("Completed `didBecomeActive`");
|
||||
}
|
||||
|
||||
extern fn will_resign_active(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `willResignActive`");
|
||||
/*unsafe {
|
||||
HANDLER.lock().unwrap().handle_nonuser_event(Event::Suspended(true))
|
||||
|
|
@ -64,17 +67,17 @@ extern fn will_resign_active(_: &Object, _: Sel, _: id) {
|
|||
trace!("Completed `willResignActive`");
|
||||
}
|
||||
|
||||
extern fn will_enter_foreground(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `willEnterForeground`");
|
||||
trace!("Completed `willEnterForeground`");
|
||||
}
|
||||
|
||||
extern fn did_enter_background(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn did_enter_background(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `didEnterBackground`");
|
||||
trace!("Completed `didEnterBackground`");
|
||||
}
|
||||
|
||||
extern fn will_terminate(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn will_terminate(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `willTerminate`");
|
||||
/*unsafe {
|
||||
let app: id = msg_send![class!(UIApplication), sharedApplication];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
use std::{
|
||||
collections::VecDeque, fmt::{self, Debug},
|
||||
hint::unreachable_unchecked, mem,
|
||||
sync::{atomic::{AtomicBool, Ordering}, Mutex, MutexGuard}, time::Instant,
|
||||
collections::VecDeque,
|
||||
fmt::{self, Debug},
|
||||
hint::unreachable_unchecked,
|
||||
mem,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Mutex, MutexGuard,
|
||||
},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use cocoa::{appkit::NSApp, base::nil};
|
||||
|
|
@ -9,9 +15,9 @@ use cocoa::{appkit::NSApp, base::nil};
|
|||
use crate::{
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget},
|
||||
platform_impl::platform::{observer::EventLoopWaker, util::Never},
|
||||
window::WindowId,
|
||||
};
|
||||
use crate::platform_impl::platform::{observer::EventLoopWaker, util::Never};
|
||||
|
||||
lazy_static! {
|
||||
static ref HANDLER: Handler = Default::default();
|
||||
|
|
@ -39,7 +45,8 @@ struct EventLoopHandler<F, T: 'static> {
|
|||
|
||||
impl<F, T> Debug for EventLoopHandler<F, T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.debug_struct("EventLoopHandler")
|
||||
formatter
|
||||
.debug_struct("EventLoopHandler")
|
||||
.field("window_target", &self.window_target)
|
||||
.finish()
|
||||
}
|
||||
|
|
@ -51,11 +58,7 @@ where
|
|||
T: 'static,
|
||||
{
|
||||
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow) {
|
||||
(self.callback)(
|
||||
event.userify(),
|
||||
&self.window_target,
|
||||
control_flow,
|
||||
);
|
||||
(self.callback)(event.userify(), &self.window_target, control_flow);
|
||||
self.will_exit |= *control_flow == ControlFlow::Exit;
|
||||
if self.will_exit {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
|
|
@ -65,11 +68,7 @@ where
|
|||
fn handle_user_events(&mut self, control_flow: &mut ControlFlow) {
|
||||
let mut will_exit = self.will_exit;
|
||||
for event in self.window_target.p.receiver.try_iter() {
|
||||
(self.callback)(
|
||||
Event::UserEvent(event),
|
||||
&self.window_target,
|
||||
control_flow,
|
||||
);
|
||||
(self.callback)(Event::UserEvent(event), &self.window_target, control_flow);
|
||||
will_exit |= *control_flow == ControlFlow::Exit;
|
||||
if will_exit {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
|
|
@ -167,18 +166,13 @@ impl Handler {
|
|||
|
||||
fn handle_nonuser_event(&self, event: Event<Never>) {
|
||||
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
|
||||
callback.handle_nonuser_event(
|
||||
event,
|
||||
&mut *self.control_flow.lock().unwrap(),
|
||||
);
|
||||
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_user_events(&self) {
|
||||
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
|
||||
callback.handle_user_events(
|
||||
&mut *self.control_flow.lock().unwrap(),
|
||||
);
|
||||
callback.handle_user_events(&mut *self.control_flow.lock().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -213,13 +207,17 @@ impl AppState {
|
|||
}
|
||||
|
||||
pub fn wakeup() {
|
||||
if !HANDLER.is_ready() { return }
|
||||
if !HANDLER.is_ready() {
|
||||
return;
|
||||
}
|
||||
let start = HANDLER.get_start_time().unwrap();
|
||||
let cause = match HANDLER.get_control_flow_and_update_prev() {
|
||||
ControlFlow::Poll => StartCause::Poll,
|
||||
ControlFlow::Wait => StartCause::WaitCancelled {
|
||||
start,
|
||||
requested_resume: None,
|
||||
ControlFlow::Wait => {
|
||||
StartCause::WaitCancelled {
|
||||
start,
|
||||
requested_resume: None,
|
||||
}
|
||||
},
|
||||
ControlFlow::WaitUntil(requested_resume) => {
|
||||
if Instant::now() >= requested_resume {
|
||||
|
|
@ -234,7 +232,7 @@ impl AppState {
|
|||
}
|
||||
}
|
||||
},
|
||||
ControlFlow::Exit => StartCause::Poll,//panic!("unexpected `ControlFlow::Exit`"),
|
||||
ControlFlow::Exit => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
|
||||
};
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(Event::NewEvents(cause));
|
||||
|
|
@ -278,7 +276,9 @@ impl AppState {
|
|||
}
|
||||
|
||||
pub fn cleared() {
|
||||
if !HANDLER.is_ready() { return }
|
||||
if !HANDLER.is_ready() {
|
||||
return;
|
||||
}
|
||||
if !HANDLER.get_in_callback() {
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_user_events();
|
||||
|
|
@ -295,8 +295,8 @@ impl AppState {
|
|||
HANDLER.set_in_callback(false);
|
||||
}
|
||||
if HANDLER.should_exit() {
|
||||
let _: () = unsafe { msg_send![NSApp(), stop:nil] };
|
||||
return
|
||||
let _: () = unsafe { msg_send![NSApp(), stop: nil] };
|
||||
return;
|
||||
}
|
||||
HANDLER.update_start_time();
|
||||
match HANDLER.get_old_and_new_control_flow() {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
use std::os::raw::c_ushort;
|
||||
|
||||
use cocoa::{appkit::{NSEvent, NSEventModifierFlags}, base::id};
|
||||
|
||||
use crate::event::{
|
||||
ElementState, KeyboardInput,
|
||||
ModifiersState, VirtualKeyCode, WindowEvent,
|
||||
use cocoa::{
|
||||
appkit::{NSEvent, NSEventModifierFlags},
|
||||
base::id,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent},
|
||||
platform_impl::platform::DEVICE_ID,
|
||||
};
|
||||
use crate::platform_impl::platform::DEVICE_ID;
|
||||
|
||||
pub fn char_to_keycode(c: char) -> Option<VirtualKeyCode> {
|
||||
// We only translate keys that are affected by keyboard layout.
|
||||
|
|
@ -57,9 +59,9 @@ pub fn char_to_keycode(c: char) -> Option<VirtualKeyCode> {
|
|||
'-' | '_' => VirtualKeyCode::Minus,
|
||||
']' | '}' => VirtualKeyCode::RBracket,
|
||||
'[' | '{' => VirtualKeyCode::LBracket,
|
||||
'\''| '"' => VirtualKeyCode::Apostrophe,
|
||||
'\'' | '"' => VirtualKeyCode::Apostrophe,
|
||||
';' | ':' => VirtualKeyCode::Semicolon,
|
||||
'\\'| '|' => VirtualKeyCode::Backslash,
|
||||
'\\' | '|' => VirtualKeyCode::Backslash,
|
||||
',' | '<' => VirtualKeyCode::Comma,
|
||||
'/' | '?' => VirtualKeyCode::Slash,
|
||||
'.' | '>' => VirtualKeyCode::Period,
|
||||
|
|
@ -198,7 +200,6 @@ pub fn scancode_to_keycode(scancode: c_ushort) -> Option<VirtualKeyCode> {
|
|||
0x7d => VirtualKeyCode::Down,
|
||||
0x7e => VirtualKeyCode::Up,
|
||||
//0x7f => unkown,
|
||||
|
||||
0xa => VirtualKeyCode::Caret,
|
||||
_ => return None,
|
||||
})
|
||||
|
|
@ -215,16 +216,14 @@ pub fn check_function_keys(string: &String) -> Option<VirtualKeyCode> {
|
|||
0xf71a => VirtualKeyCode::F23,
|
||||
0xf71b => VirtualKeyCode::F24,
|
||||
_ => return None,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn event_mods(event: id) -> ModifiersState {
|
||||
let flags = unsafe {
|
||||
NSEvent::modifierFlags(event)
|
||||
};
|
||||
let flags = unsafe { NSEvent::modifierFlags(event) };
|
||||
ModifiersState {
|
||||
shift: flags.contains(NSEventModifierFlags::NSShiftKeyMask),
|
||||
ctrl: flags.contains(NSEventModifierFlags::NSControlKeyMask),
|
||||
|
|
@ -238,9 +237,7 @@ pub fn get_scancode(event: cocoa::base::id) -> c_ushort {
|
|||
// and there is no easy way to navtively retrieve the layout-dependent character.
|
||||
// In winit, we use keycode to refer to the key's character, and so this function aligns
|
||||
// AppKit's terminology with ours.
|
||||
unsafe {
|
||||
msg_send![event, keyCode]
|
||||
}
|
||||
unsafe { msg_send![event, keyCode] }
|
||||
}
|
||||
|
||||
pub unsafe fn modifier_event(
|
||||
|
|
@ -249,7 +246,8 @@ pub unsafe fn modifier_event(
|
|||
was_key_pressed: bool,
|
||||
) -> Option<WindowEvent> {
|
||||
if !was_key_pressed && NSEvent::modifierFlags(ns_event).contains(keymask)
|
||||
|| was_key_pressed && !NSEvent::modifierFlags(ns_event).contains(keymask) {
|
||||
|| was_key_pressed && !NSEvent::modifierFlags(ns_event).contains(keymask)
|
||||
{
|
||||
let state = if was_key_pressed {
|
||||
ElementState::Released
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,24 @@
|
|||
use std::{
|
||||
collections::VecDeque, mem, os::raw::c_void, process, ptr, sync::mpsc, marker::PhantomData
|
||||
collections::VecDeque, marker::PhantomData, mem, os::raw::c_void, process, ptr, sync::mpsc,
|
||||
};
|
||||
|
||||
use cocoa::{appkit::NSApp, base::{id, nil}, foundation::NSAutoreleasePool};
|
||||
use cocoa::{
|
||||
appkit::NSApp,
|
||||
base::{id, nil},
|
||||
foundation::NSAutoreleasePool,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
event::Event,
|
||||
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget},
|
||||
};
|
||||
use crate::platform_impl::platform::{
|
||||
app::APP_CLASS, app_delegate::APP_DELEGATE_CLASS,
|
||||
app_state::AppState, monitor::{self, MonitorHandle},
|
||||
observer::*, util::IdRef,
|
||||
platform_impl::platform::{
|
||||
app::APP_CLASS,
|
||||
app_delegate::APP_DELEGATE_CLASS,
|
||||
app_state::AppState,
|
||||
monitor::{self, MonitorHandle},
|
||||
observer::*,
|
||||
util::IdRef,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct EventLoopWindowTarget<T: 'static> {
|
||||
|
|
@ -75,7 +82,8 @@ impl<T> EventLoop<T> {
|
|||
}
|
||||
|
||||
pub fn run<F>(self, callback: F) -> !
|
||||
where F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
where
|
||||
F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
unsafe {
|
||||
let _pool = NSAutoreleasePool::new(nil);
|
||||
|
|
@ -89,7 +97,8 @@ impl<T> EventLoop<T> {
|
|||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, _callback: F)
|
||||
where F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
where
|
||||
F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
unimplemented!();
|
||||
}
|
||||
|
|
@ -119,11 +128,8 @@ impl<T> Proxy<T> {
|
|||
let rl = CFRunLoopGetMain();
|
||||
let mut context: CFRunLoopSourceContext = mem::zeroed();
|
||||
context.perform = event_loop_proxy_handler;
|
||||
let source = CFRunLoopSourceCreate(
|
||||
ptr::null_mut(),
|
||||
CFIndex::max_value() - 1,
|
||||
&mut context,
|
||||
);
|
||||
let source =
|
||||
CFRunLoopSourceCreate(ptr::null_mut(), CFIndex::max_value() - 1, &mut context);
|
||||
CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
|
||||
CFRunLoopWakeUp(rl);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
#![allow(dead_code, non_snake_case, non_upper_case_globals)]
|
||||
|
||||
use cocoa::base::id;
|
||||
use cocoa::foundation::{NSInteger, NSUInteger};
|
||||
use cocoa::{
|
||||
base::id,
|
||||
foundation::{NSInteger, NSUInteger},
|
||||
};
|
||||
use objc;
|
||||
|
||||
pub const NSNotFound: NSInteger = NSInteger::max_value();
|
||||
|
|
@ -53,11 +55,11 @@ impl NSMutableAttributedString for id {
|
|||
}
|
||||
|
||||
unsafe fn initWithString(self, string: id) -> id {
|
||||
msg_send![self, initWithString:string]
|
||||
msg_send![self, initWithString: string]
|
||||
}
|
||||
|
||||
unsafe fn initWithAttributedString(self, string: id) -> id {
|
||||
msg_send![self, initWithAttributedString:string]
|
||||
msg_send![self, initWithAttributedString: string]
|
||||
}
|
||||
|
||||
unsafe fn string(self) -> id {
|
||||
|
|
|
|||
|
|
@ -15,16 +15,13 @@ mod window_delegate;
|
|||
|
||||
use std::{fmt, ops::Deref, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
event::DeviceId as RootDeviceId, window::WindowAttributes,
|
||||
error::OsError as RootOsError,
|
||||
};
|
||||
pub use self::{
|
||||
event_loop::{EventLoop, EventLoopWindowTarget, Proxy as EventLoopProxy},
|
||||
monitor::MonitorHandle,
|
||||
window::{
|
||||
Id as WindowId, PlatformSpecificWindowBuilderAttributes, UnownedWindow,
|
||||
},
|
||||
window::{Id as WindowId, PlatformSpecificWindowBuilderAttributes, UnownedWindow},
|
||||
};
|
||||
use crate::{
|
||||
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
|
||||
};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
|
@ -48,7 +45,7 @@ pub struct Window {
|
|||
#[derive(Debug)]
|
||||
pub enum OsError {
|
||||
CGError(core_graphics::base::CGError),
|
||||
CreationError(&'static str)
|
||||
CreationError(&'static str),
|
||||
}
|
||||
|
||||
unsafe impl Send for Window {}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ use core_video_sys::{
|
|||
CVDisplayLinkGetNominalOutputVideoRefreshPeriod, CVDisplayLinkRelease,
|
||||
};
|
||||
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::platform_impl::platform::util::IdRef;
|
||||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
monitor::VideoMode,
|
||||
platform_impl::platform::util::IdRef,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct MonitorHandle(CGDirectDisplayID);
|
||||
|
|
@ -79,10 +81,7 @@ impl MonitorHandle {
|
|||
let display = CGDisplay::new(display_id);
|
||||
let height = display.pixels_high();
|
||||
let width = display.pixels_wide();
|
||||
PhysicalSize::from_logical(
|
||||
(width as f64, height as f64),
|
||||
self.hidpi_factor(),
|
||||
)
|
||||
PhysicalSize::from_logical((width as f64, height as f64), self.hidpi_factor())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::{self, ptr, os::raw::*, time::Instant};
|
||||
use std::{self, os::raw::*, ptr, time::Instant};
|
||||
|
||||
use crate::platform_impl::platform::app_state::AppState;
|
||||
|
||||
#[link(name = "CoreFoundation", kind = "framework")]
|
||||
extern {
|
||||
extern "C" {
|
||||
pub static kCFRunLoopDefaultMode: CFRunLoopMode;
|
||||
pub static kCFRunLoopCommonModes: CFRunLoopMode;
|
||||
|
||||
|
|
@ -33,15 +33,8 @@ extern {
|
|||
callout: CFRunLoopTimerCallBack,
|
||||
context: *mut CFRunLoopTimerContext,
|
||||
) -> CFRunLoopTimerRef;
|
||||
pub fn CFRunLoopAddTimer(
|
||||
rl: CFRunLoopRef,
|
||||
timer: CFRunLoopTimerRef,
|
||||
mode: CFRunLoopMode,
|
||||
);
|
||||
pub fn CFRunLoopTimerSetNextFireDate(
|
||||
timer: CFRunLoopTimerRef,
|
||||
fireDate: CFAbsoluteTime,
|
||||
);
|
||||
pub fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFRunLoopMode);
|
||||
pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime);
|
||||
pub fn CFRunLoopTimerInvalidate(time: CFRunLoopTimerRef);
|
||||
|
||||
pub fn CFRunLoopSourceCreate(
|
||||
|
|
@ -49,11 +42,7 @@ extern {
|
|||
order: CFIndex,
|
||||
context: *mut CFRunLoopSourceContext,
|
||||
) -> CFRunLoopSourceRef;
|
||||
pub fn CFRunLoopAddSource(
|
||||
rl: CFRunLoopRef,
|
||||
source: CFRunLoopSourceRef,
|
||||
mode: CFRunLoopMode,
|
||||
);
|
||||
pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFRunLoopMode);
|
||||
#[allow(dead_code)]
|
||||
pub fn CFRunLoopSourceInvalidate(source: CFRunLoopSourceRef);
|
||||
pub fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef);
|
||||
|
|
@ -98,15 +87,9 @@ pub const kCFRunLoopAfterWaiting: CFRunLoopActivity = 1 << 6;
|
|||
#[allow(non_upper_case_globals)]
|
||||
pub const kCFRunLoopExit: CFRunLoopActivity = 1 << 7;
|
||||
|
||||
pub type CFRunLoopObserverCallBack = extern "C" fn(
|
||||
observer: CFRunLoopObserverRef,
|
||||
activity: CFRunLoopActivity,
|
||||
info: *mut c_void,
|
||||
);
|
||||
pub type CFRunLoopTimerCallBack = extern "C" fn(
|
||||
timer: CFRunLoopTimerRef,
|
||||
info: *mut c_void
|
||||
);
|
||||
pub type CFRunLoopObserverCallBack =
|
||||
extern "C" fn(observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void);
|
||||
pub type CFRunLoopTimerCallBack = extern "C" fn(timer: CFRunLoopTimerRef, info: *mut c_void);
|
||||
|
||||
pub enum CFRunLoopObserverContext {}
|
||||
pub enum CFRunLoopTimerContext {}
|
||||
|
|
@ -127,7 +110,7 @@ pub struct CFRunLoopSourceContext {
|
|||
}
|
||||
|
||||
// begin is queued with the highest priority to ensure it is processed before other observers
|
||||
extern fn control_flow_begin_handler(
|
||||
extern "C" fn control_flow_begin_handler(
|
||||
_: CFRunLoopObserverRef,
|
||||
activity: CFRunLoopActivity,
|
||||
_: *mut c_void,
|
||||
|
|
@ -146,7 +129,7 @@ extern fn control_flow_begin_handler(
|
|||
|
||||
// end is queued with the lowest priority to ensure it is processed after other observers
|
||||
// without that, LoopDestroyed would get sent after EventsCleared
|
||||
extern fn control_flow_end_handler(
|
||||
extern "C" fn control_flow_end_handler(
|
||||
_: CFRunLoopObserverRef,
|
||||
activity: CFRunLoopActivity,
|
||||
_: *mut c_void,
|
||||
|
|
@ -158,7 +141,7 @@ extern fn control_flow_end_handler(
|
|||
AppState::cleared();
|
||||
//trace!("Completed `CFRunLoopBeforeWaiting`");
|
||||
},
|
||||
kCFRunLoopExit => (),//unimplemented!(), // not expected to ever happen
|
||||
kCFRunLoopExit => (), //unimplemented!(), // not expected to ever happen
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -179,7 +162,7 @@ impl RunLoop {
|
|||
let observer = CFRunLoopObserverCreate(
|
||||
ptr::null_mut(),
|
||||
flags,
|
||||
TRUE, // Indicates we want this to run repeatedly
|
||||
TRUE, // Indicates we want this to run repeatedly
|
||||
priority, // The lower the value, the sooner this will run
|
||||
handler,
|
||||
ptr::null_mut(),
|
||||
|
|
@ -204,7 +187,6 @@ pub fn setup_control_flow_observers() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct EventLoopWaker {
|
||||
timer: CFRunLoopTimerRef,
|
||||
}
|
||||
|
|
@ -220,7 +202,7 @@ impl Drop for EventLoopWaker {
|
|||
|
||||
impl Default for EventLoopWaker {
|
||||
fn default() -> EventLoopWaker {
|
||||
extern fn wakeup_main_loop(_timer: CFRunLoopTimerRef, _info: *mut c_void) {}
|
||||
extern "C" fn wakeup_main_loop(_timer: CFRunLoopTimerRef, _info: *mut c_void) {}
|
||||
unsafe {
|
||||
// create a timer with a 1µs interval (1ns does not work) to mimic polling.
|
||||
// it is initially setup with a first fire time really far into the
|
||||
|
|
@ -257,8 +239,8 @@ impl EventLoopWaker {
|
|||
unsafe {
|
||||
let current = CFAbsoluteTimeGetCurrent();
|
||||
let duration = instant - now;
|
||||
let fsecs = duration.subsec_nanos() as f64 / 1_000_000_000.0
|
||||
+ duration.as_secs() as f64;
|
||||
let fsecs =
|
||||
duration.subsec_nanos() as f64 / 1_000_000_000.0 + duration.as_secs() as f64;
|
||||
CFRunLoopTimerSetNextFireDate(self.timer, current + fsecs)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ use cocoa::{
|
|||
};
|
||||
use dispatch::ffi::{dispatch_async_f, dispatch_get_main_queue, dispatch_sync_f};
|
||||
|
||||
use crate::dpi::LogicalSize;
|
||||
use crate::platform_impl::platform::{ffi, util::IdRef, window::SharedState};
|
||||
use crate::{
|
||||
dpi::LogicalSize,
|
||||
platform_impl::platform::{ffi, util::IdRef, window::SharedState},
|
||||
};
|
||||
|
||||
unsafe fn set_style_mask(ns_window: id, ns_view: id, mask: NSWindowStyleMask) {
|
||||
ns_window.setStyleMask_(mask);
|
||||
|
|
@ -26,15 +28,15 @@ struct SetStyleMaskData {
|
|||
mask: NSWindowStyleMask,
|
||||
}
|
||||
impl SetStyleMaskData {
|
||||
fn new_ptr(
|
||||
ns_window: id,
|
||||
ns_view: id,
|
||||
mask: NSWindowStyleMask,
|
||||
) -> *mut Self {
|
||||
Box::into_raw(Box::new(SetStyleMaskData { ns_window, ns_view, mask }))
|
||||
fn new_ptr(ns_window: id, ns_view: id, mask: NSWindowStyleMask) -> *mut Self {
|
||||
Box::into_raw(Box::new(SetStyleMaskData {
|
||||
ns_window,
|
||||
ns_view,
|
||||
mask,
|
||||
}))
|
||||
}
|
||||
}
|
||||
extern fn set_style_mask_callback(context: *mut c_void) {
|
||||
extern "C" fn set_style_mask_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut SetStyleMaskData;
|
||||
{
|
||||
|
|
@ -70,14 +72,11 @@ struct SetContentSizeData {
|
|||
size: LogicalSize,
|
||||
}
|
||||
impl SetContentSizeData {
|
||||
fn new_ptr(
|
||||
ns_window: id,
|
||||
size: LogicalSize,
|
||||
) -> *mut Self {
|
||||
fn new_ptr(ns_window: id, size: LogicalSize) -> *mut Self {
|
||||
Box::into_raw(Box::new(SetContentSizeData { ns_window, size }))
|
||||
}
|
||||
}
|
||||
extern fn set_content_size_callback(context: *mut c_void) {
|
||||
extern "C" fn set_content_size_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut SetContentSizeData;
|
||||
{
|
||||
|
|
@ -109,14 +108,11 @@ struct SetFrameTopLeftPointData {
|
|||
point: NSPoint,
|
||||
}
|
||||
impl SetFrameTopLeftPointData {
|
||||
fn new_ptr(
|
||||
ns_window: id,
|
||||
point: NSPoint,
|
||||
) -> *mut Self {
|
||||
fn new_ptr(ns_window: id, point: NSPoint) -> *mut Self {
|
||||
Box::into_raw(Box::new(SetFrameTopLeftPointData { ns_window, point }))
|
||||
}
|
||||
}
|
||||
extern fn set_frame_top_left_point_callback(context: *mut c_void) {
|
||||
extern "C" fn set_frame_top_left_point_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut SetFrameTopLeftPointData;
|
||||
{
|
||||
|
|
@ -142,14 +138,11 @@ struct SetLevelData {
|
|||
level: ffi::NSWindowLevel,
|
||||
}
|
||||
impl SetLevelData {
|
||||
fn new_ptr(
|
||||
ns_window: id,
|
||||
level: ffi::NSWindowLevel,
|
||||
) -> *mut Self {
|
||||
fn new_ptr(ns_window: id, level: ffi::NSWindowLevel) -> *mut Self {
|
||||
Box::into_raw(Box::new(SetLevelData { ns_window, level }))
|
||||
}
|
||||
}
|
||||
extern fn set_level_callback(context: *mut c_void) {
|
||||
extern "C" fn set_level_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut SetLevelData;
|
||||
{
|
||||
|
|
@ -190,7 +183,7 @@ impl ToggleFullScreenData {
|
|||
}))
|
||||
}
|
||||
}
|
||||
extern fn toggle_full_screen_callback(context: *mut c_void) {
|
||||
extern "C" fn toggle_full_screen_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut ToggleFullScreenData;
|
||||
{
|
||||
|
|
@ -227,12 +220,7 @@ pub unsafe fn toggle_full_screen_async(
|
|||
not_fullscreen: bool,
|
||||
shared_state: Weak<Mutex<SharedState>>,
|
||||
) {
|
||||
let context = ToggleFullScreenData::new_ptr(
|
||||
ns_window,
|
||||
ns_view,
|
||||
not_fullscreen,
|
||||
shared_state,
|
||||
);
|
||||
let context = ToggleFullScreenData::new_ptr(ns_window, ns_view, not_fullscreen, shared_state);
|
||||
dispatch_async_f(
|
||||
dispatch_get_main_queue(),
|
||||
context as *mut _,
|
||||
|
|
@ -325,7 +313,7 @@ impl OrderOutData {
|
|||
Box::into_raw(Box::new(OrderOutData { ns_window }))
|
||||
}
|
||||
}
|
||||
extern fn order_out_callback(context: *mut c_void) {
|
||||
extern "C" fn order_out_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut OrderOutData;
|
||||
{
|
||||
|
|
@ -354,7 +342,7 @@ impl MakeKeyAndOrderFrontData {
|
|||
Box::into_raw(Box::new(MakeKeyAndOrderFrontData { ns_window }))
|
||||
}
|
||||
}
|
||||
extern fn make_key_and_order_front_callback(context: *mut c_void) {
|
||||
extern "C" fn make_key_and_order_front_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut MakeKeyAndOrderFrontData;
|
||||
{
|
||||
|
|
@ -415,7 +403,7 @@ impl CloseData {
|
|||
Box::into_raw(Box::new(CloseData { ns_window }))
|
||||
}
|
||||
}
|
||||
extern fn close_callback(context: *mut c_void) {
|
||||
extern "C" fn close_callback(context: *mut c_void) {
|
||||
unsafe {
|
||||
let context_ptr = context as *mut CloseData;
|
||||
{
|
||||
|
|
@ -431,9 +419,5 @@ extern fn close_callback(context: *mut c_void) {
|
|||
// thread. Though, it's a good idea to look into that more...
|
||||
pub unsafe fn close_async(ns_window: id) {
|
||||
let context = CloseData::new_ptr(ns_window);
|
||||
dispatch_async_f(
|
||||
dispatch_get_main_queue(),
|
||||
context as *mut _,
|
||||
close_callback,
|
||||
);
|
||||
dispatch_async_f(dispatch_get_main_queue(), context as *mut _, close_callback);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use cocoa::{
|
||||
appkit::NSImage, base::{id, nil},
|
||||
appkit::NSImage,
|
||||
base::{id, nil},
|
||||
foundation::{NSDictionary, NSPoint, NSString},
|
||||
};
|
||||
use objc::runtime::Sel;
|
||||
|
|
@ -22,7 +23,9 @@ impl From<CursorIcon> for Cursor {
|
|||
CursorIcon::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"),
|
||||
CursorIcon::Copy => Cursor::Native("dragCopyCursor"),
|
||||
CursorIcon::Alias => Cursor::Native("dragLinkCursor"),
|
||||
CursorIcon::NotAllowed | CursorIcon::NoDrop => Cursor::Native("operationNotAllowedCursor"),
|
||||
CursorIcon::NotAllowed | CursorIcon::NoDrop => {
|
||||
Cursor::Native("operationNotAllowedCursor")
|
||||
},
|
||||
CursorIcon::ContextMenu => Cursor::Native("contextualMenuCursor"),
|
||||
CursorIcon::Crosshair => Cursor::Native("crosshairCursor"),
|
||||
CursorIcon::EResize => Cursor::Native("resizeRightCursor"),
|
||||
|
|
@ -52,7 +55,9 @@ impl From<CursorIcon> for Cursor {
|
|||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=522349
|
||||
// This is the wrong semantics for `Wait`, but it's the same as
|
||||
// what's used in Safari and Chrome.
|
||||
CursorIcon::Wait | CursorIcon::Progress => Cursor::Undocumented("busyButClickableCursor"),
|
||||
CursorIcon::Wait | CursorIcon::Progress => {
|
||||
Cursor::Undocumented("busyButClickableCursor")
|
||||
},
|
||||
|
||||
// For the rest, we can just snatch the cursors from WebKit...
|
||||
// They fit the style of the native cursors, and will seem
|
||||
|
|
@ -75,18 +80,18 @@ impl Cursor {
|
|||
match self {
|
||||
Cursor::Native(cursor_name) => {
|
||||
let sel = Sel::register(cursor_name);
|
||||
msg_send![class!(NSCursor), performSelector:sel]
|
||||
msg_send![class!(NSCursor), performSelector: sel]
|
||||
},
|
||||
Cursor::Undocumented(cursor_name) => {
|
||||
let class = class!(NSCursor);
|
||||
let sel = Sel::register(cursor_name);
|
||||
let sel = if msg_send![class, respondsToSelector:sel] {
|
||||
let sel = if msg_send![class, respondsToSelector: sel] {
|
||||
sel
|
||||
} else {
|
||||
warn!("Cursor `{}` appears to be invalid", cursor_name);
|
||||
sel!(arrowCursor)
|
||||
};
|
||||
msg_send![class, performSelector:sel]
|
||||
msg_send![class, performSelector: sel]
|
||||
},
|
||||
Cursor::WebKit(cursor_name) => load_webkit_cursor(cursor_name),
|
||||
}
|
||||
|
|
@ -104,27 +109,15 @@ pub unsafe fn load_webkit_cursor(cursor_name: &str) -> id {
|
|||
let key_x = NSString::alloc(nil).init_str("hotx");
|
||||
let key_y = NSString::alloc(nil).init_str("hoty");
|
||||
|
||||
let cursor_path: id = msg_send![cursor_root,
|
||||
stringByAppendingPathComponent:cursor_name
|
||||
];
|
||||
let pdf_path: id = msg_send![cursor_path,
|
||||
stringByAppendingPathComponent:cursor_pdf
|
||||
];
|
||||
let info_path: id = msg_send![cursor_path,
|
||||
stringByAppendingPathComponent:cursor_plist
|
||||
];
|
||||
let cursor_path: id = msg_send![cursor_root, stringByAppendingPathComponent: cursor_name];
|
||||
let pdf_path: id = msg_send![cursor_path, stringByAppendingPathComponent: cursor_pdf];
|
||||
let info_path: id = msg_send![cursor_path, stringByAppendingPathComponent: cursor_plist];
|
||||
|
||||
let image = NSImage::alloc(nil).initByReferencingFile_(pdf_path);
|
||||
let info = NSDictionary::dictionaryWithContentsOfFile_(
|
||||
nil,
|
||||
info_path,
|
||||
);
|
||||
let info = NSDictionary::dictionaryWithContentsOfFile_(nil, info_path);
|
||||
let x = info.valueForKey_(key_x);
|
||||
let y = info.valueForKey_(key_y);
|
||||
let point = NSPoint::new(
|
||||
msg_send![x, doubleValue],
|
||||
msg_send![y, doubleValue],
|
||||
);
|
||||
let point = NSPoint::new(msg_send![x, doubleValue], msg_send![y, doubleValue]);
|
||||
let cursor: id = msg_send![class!(NSCursor), alloc];
|
||||
msg_send![cursor,
|
||||
initWithImage:image
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
mod r#async;
|
||||
mod cursor;
|
||||
|
||||
pub use self::{r#async::*, cursor::*};
|
||||
pub use self::{cursor::*, r#async::*};
|
||||
|
||||
use std::ops::Deref;
|
||||
use std::ops::BitAnd;
|
||||
use std::ops::{BitAnd, Deref};
|
||||
|
||||
use cocoa::{
|
||||
appkit::{NSApp, NSWindowStyleMask},
|
||||
|
|
@ -12,7 +11,7 @@ use cocoa::{
|
|||
foundation::{NSAutoreleasePool, NSRect, NSUInteger},
|
||||
};
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::runtime::{BOOL, Class, Object, Sel, YES};
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
||||
|
||||
use crate::platform_impl::platform::ffi;
|
||||
|
||||
|
|
@ -21,8 +20,8 @@ use crate::platform_impl::platform::ffi;
|
|||
pub enum Never {}
|
||||
|
||||
pub fn has_flag<T>(bitset: T, flag: T) -> bool
|
||||
where T:
|
||||
Copy + PartialEq + BitAnd<T, Output = T>
|
||||
where
|
||||
T: Copy + PartialEq + BitAnd<T, Output = T>,
|
||||
{
|
||||
bitset & flag == flag
|
||||
}
|
||||
|
|
@ -48,7 +47,11 @@ impl IdRef {
|
|||
}
|
||||
|
||||
pub fn non_nil(self) -> Option<IdRef> {
|
||||
if self.0 == nil { None } else { Some(self) }
|
||||
if self.0 == nil {
|
||||
None
|
||||
} else {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,16 +97,16 @@ pub unsafe fn superclass<'a>(this: &'a Object) -> &'a Class {
|
|||
|
||||
pub unsafe fn create_input_context(view: id) -> IdRef {
|
||||
let input_context: id = msg_send![class!(NSTextInputContext), alloc];
|
||||
let input_context: id = msg_send![input_context, initWithClient:view];
|
||||
let input_context: id = msg_send![input_context, initWithClient: view];
|
||||
IdRef::new(input_context)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn open_emoji_picker() {
|
||||
let () = msg_send![NSApp(), orderFrontCharacterPalette:nil];
|
||||
let () = msg_send![NSApp(), orderFrontCharacterPalette: nil];
|
||||
}
|
||||
|
||||
pub extern fn yes(_: &Object, _: Sel) -> BOOL {
|
||||
pub extern "C" fn yes(_: &Object, _: Sel) -> BOOL {
|
||||
YES
|
||||
}
|
||||
|
||||
|
|
@ -120,4 +123,3 @@ pub unsafe fn toggle_style_mask(window: id, view: id, mask: NSWindowStyleMask, o
|
|||
// If we don't do this, key handling will break. Therefore, never call `setStyleMask` directly!
|
||||
window.makeFirstResponder_(view);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,39 @@
|
|||
use std::{
|
||||
boxed::Box, collections::VecDeque, os::raw::*, slice, str,
|
||||
boxed::Box,
|
||||
collections::VecDeque,
|
||||
os::raw::*,
|
||||
slice, str,
|
||||
sync::{Arc, Mutex, Weak},
|
||||
};
|
||||
|
||||
use cocoa::{
|
||||
appkit::{NSApp, NSEvent, NSEventModifierFlags, NSEventPhase, NSView, NSWindow},
|
||||
base::{id, nil}, foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger},
|
||||
base::{id, nil},
|
||||
foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger},
|
||||
};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
||||
};
|
||||
use objc::{declare::ClassDecl, runtime::{BOOL, Class, NO, Object, Protocol, Sel, YES}};
|
||||
|
||||
use crate::{
|
||||
event::{
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton,
|
||||
MouseScrollDelta, TouchPhase, VirtualKeyCode, WindowEvent,
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
VirtualKeyCode, WindowEvent,
|
||||
},
|
||||
platform_impl::platform::{
|
||||
app_state::AppState,
|
||||
event::{
|
||||
char_to_keycode, check_function_keys, event_mods, get_scancode, modifier_event,
|
||||
scancode_to_keycode,
|
||||
},
|
||||
ffi::*,
|
||||
util::{self, IdRef},
|
||||
window::get_window_id,
|
||||
DEVICE_ID,
|
||||
},
|
||||
window::WindowId,
|
||||
};
|
||||
use crate::platform_impl::platform::{
|
||||
app_state::AppState, DEVICE_ID,
|
||||
event::{check_function_keys, event_mods, modifier_event, char_to_keycode, get_scancode, scancode_to_keycode},
|
||||
util::{self, IdRef}, ffi::*, window::get_window_id,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Modifiers {
|
||||
|
|
@ -54,17 +67,18 @@ pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<util::Cursor>>) {
|
|||
// This is free'd in `dealloc`
|
||||
let state_ptr = Box::into_raw(Box::new(state)) as *mut c_void;
|
||||
let ns_view: id = msg_send![VIEW_CLASS.0, alloc];
|
||||
(IdRef::new(msg_send![ns_view, initWithWinit:state_ptr]), cursor_access)
|
||||
(
|
||||
IdRef::new(msg_send![ns_view, initWithWinit: state_ptr]),
|
||||
cursor_access,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn set_ime_position(ns_view: id, input_context: id, x: f64, y: f64) {
|
||||
let state_ptr: *mut c_void = *(*ns_view).get_mut_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
let content_rect = NSWindow::contentRectForFrameRect_(
|
||||
state.ns_window,
|
||||
NSWindow::frame(state.ns_window),
|
||||
);
|
||||
let content_rect =
|
||||
NSWindow::contentRectForFrameRect_(state.ns_window, NSWindow::frame(state.ns_window));
|
||||
let base_x = content_rect.origin.x as f64;
|
||||
let base_y = (content_rect.origin.y + content_rect.size.height) as f64;
|
||||
state.ime_spot = Some((base_x + x, base_y - y));
|
||||
|
|
@ -79,161 +93,148 @@ lazy_static! {
|
|||
static ref VIEW_CLASS: ViewClass = unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new("WinitView", superclass).unwrap();
|
||||
decl.add_method(
|
||||
sel!(dealloc),
|
||||
dealloc as extern fn(&Object, Sel),
|
||||
);
|
||||
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
||||
decl.add_method(
|
||||
sel!(initWithWinit:),
|
||||
init_with_winit as extern fn(&Object, Sel, *mut c_void) -> id,
|
||||
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(viewDidMoveToWindow),
|
||||
view_did_move_to_window as extern fn(&Object, Sel),
|
||||
view_did_move_to_window as extern "C" fn(&Object, Sel),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(drawRect:),
|
||||
draw_rect as extern fn(&Object, Sel, id),
|
||||
draw_rect as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(acceptsFirstResponder),
|
||||
accepts_first_responder as extern fn(&Object, Sel) -> BOOL,
|
||||
accepts_first_responder as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(touchBar),
|
||||
touch_bar as extern fn(&Object, Sel) -> BOOL,
|
||||
touch_bar as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(resetCursorRects),
|
||||
reset_cursor_rects as extern fn(&Object, Sel),
|
||||
reset_cursor_rects as extern "C" fn(&Object, Sel),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(hasMarkedText),
|
||||
has_marked_text as extern fn(&Object, Sel) -> BOOL,
|
||||
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(markedRange),
|
||||
marked_range as extern fn(&Object, Sel) -> NSRange,
|
||||
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(selectedRange),
|
||||
selected_range as extern fn(&Object, Sel) -> NSRange,
|
||||
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(setMarkedText:selectedRange:replacementRange:),
|
||||
set_marked_text as extern fn(&mut Object, Sel, id, NSRange, NSRange),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(unmarkText),
|
||||
unmark_text as extern fn(&Object, Sel),
|
||||
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!(validAttributesForMarkedText),
|
||||
valid_attributes_for_marked_text as extern fn(&Object, Sel) -> id,
|
||||
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(attributedSubstringForProposedRange:actualRange:),
|
||||
attributed_substring_for_proposed_range as extern fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
||||
attributed_substring_for_proposed_range
|
||||
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(insertText:replacementRange:),
|
||||
insert_text as extern fn(&Object, Sel, id, NSRange),
|
||||
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(characterIndexForPoint:),
|
||||
character_index_for_point as extern fn(&Object, Sel, NSPoint) -> NSUInteger,
|
||||
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> NSUInteger,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(firstRectForCharacterRange:actualRange:),
|
||||
first_rect_for_character_range as extern fn(&Object, Sel, NSRange, *mut c_void) -> NSRect,
|
||||
first_rect_for_character_range
|
||||
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> NSRect,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(doCommandBySelector:),
|
||||
do_command_by_selector as extern fn(&Object, Sel, Sel),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(keyDown:),
|
||||
key_down as extern fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(keyUp:),
|
||||
key_up as extern fn(&Object, Sel, id),
|
||||
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!(keyUp:), key_up as extern "C" fn(&Object, Sel, id));
|
||||
decl.add_method(
|
||||
sel!(flagsChanged:),
|
||||
flags_changed as extern fn(&Object, Sel, id),
|
||||
flags_changed as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(insertTab:),
|
||||
insert_tab as extern fn(&Object, Sel, id),
|
||||
insert_tab as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(insertBackTab:),
|
||||
insert_back_tab as extern fn(&Object, Sel, id),
|
||||
insert_back_tab as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseDown:),
|
||||
mouse_down as extern fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseUp:),
|
||||
mouse_up as extern 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!(rightMouseDown:),
|
||||
right_mouse_down as extern fn(&Object, Sel, id),
|
||||
right_mouse_down as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(rightMouseUp:),
|
||||
right_mouse_up as extern fn(&Object, Sel, id),
|
||||
right_mouse_up as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(otherMouseDown:),
|
||||
other_mouse_down as extern fn(&Object, Sel, id),
|
||||
other_mouse_down as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(otherMouseUp:),
|
||||
other_mouse_up as extern fn(&Object, Sel, id),
|
||||
other_mouse_up as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseMoved:),
|
||||
mouse_moved as extern fn(&Object, Sel, id),
|
||||
mouse_moved as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseDragged:),
|
||||
mouse_dragged as extern fn(&Object, Sel, id),
|
||||
mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(rightMouseDragged:),
|
||||
right_mouse_dragged as extern fn(&Object, Sel, id),
|
||||
right_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(otherMouseDragged:),
|
||||
other_mouse_dragged as extern fn(&Object, Sel, id),
|
||||
other_mouse_dragged as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseEntered:),
|
||||
mouse_entered as extern fn(&Object, Sel, id),
|
||||
mouse_entered as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(mouseExited:),
|
||||
mouse_exited as extern fn(&Object, Sel, id),
|
||||
mouse_exited as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(scrollWheel:),
|
||||
scroll_wheel as extern fn(&Object, Sel, id),
|
||||
scroll_wheel as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(pressureChangeWithEvent:),
|
||||
pressure_change_with_event as extern fn(&Object, Sel, id),
|
||||
pressure_change_with_event as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(_wantsKeyDownForEvent:),
|
||||
wants_key_down_for_event as extern fn(&Object, Sel, id) -> BOOL,
|
||||
wants_key_down_for_event as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(cancelOperation:),
|
||||
cancel_operation as extern fn(&Object, Sel, id),
|
||||
cancel_operation as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_ivar::<*mut c_void>("winitState");
|
||||
decl.add_ivar::<id>("markedText");
|
||||
|
|
@ -243,7 +244,7 @@ lazy_static! {
|
|||
};
|
||||
}
|
||||
|
||||
extern fn dealloc(this: &Object, _sel: Sel) {
|
||||
extern "C" fn dealloc(this: &Object, _sel: Sel) {
|
||||
unsafe {
|
||||
let state: *mut c_void = *this.get_ivar("winitState");
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
|
|
@ -252,21 +253,20 @@ extern fn dealloc(this: &Object, _sel: Sel) {
|
|||
}
|
||||
}
|
||||
|
||||
extern fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> id {
|
||||
extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> id {
|
||||
unsafe {
|
||||
let this: id = msg_send![this, init];
|
||||
if this != nil {
|
||||
(*this).set_ivar("winitState", state);
|
||||
let marked_text = <id as NSMutableAttributedString>::init(
|
||||
NSMutableAttributedString::alloc(nil),
|
||||
);
|
||||
let marked_text =
|
||||
<id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil));
|
||||
(*this).set_ivar("markedText", marked_text);
|
||||
}
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
extern fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
||||
extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
||||
trace!("Triggered `viewDidMoveToWindow`");
|
||||
unsafe {
|
||||
let rect: NSRect = msg_send![this, visibleRect];
|
||||
|
|
@ -280,7 +280,7 @@ extern fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
|||
trace!("Completed `viewDidMoveToWindow`");
|
||||
}
|
||||
|
||||
extern fn draw_rect(this: &Object, _sel: Sel, rect: id) {
|
||||
extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: id) {
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
|
@ -288,22 +288,22 @@ extern fn draw_rect(this: &Object, _sel: Sel, rect: id) {
|
|||
AppState::queue_redraw(WindowId(get_window_id(state.ns_window)));
|
||||
|
||||
let superclass = util::superclass(this);
|
||||
let () = msg_send![super(this, superclass), drawRect:rect];
|
||||
let () = msg_send![super(this, superclass), drawRect: rect];
|
||||
}
|
||||
}
|
||||
|
||||
extern fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
|
||||
extern "C" fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
|
||||
YES
|
||||
}
|
||||
|
||||
// This is necessary to prevent a beefy terminal error on MacBook Pros:
|
||||
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
|
||||
// TODO: Add an API extension for using `NSTouchBar`
|
||||
extern fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
|
||||
extern "C" fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
|
||||
NO
|
||||
}
|
||||
|
||||
extern fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
||||
extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
|
@ -317,8 +317,7 @@ extern fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
extern fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
||||
extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
||||
unsafe {
|
||||
trace!("Triggered `hasMarkedText`");
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
|
|
@ -327,7 +326,7 @@ extern fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
|||
}
|
||||
}
|
||||
|
||||
extern fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
||||
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
||||
unsafe {
|
||||
trace!("Triggered `markedRange`");
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
|
|
@ -341,13 +340,13 @@ extern fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
|||
}
|
||||
}
|
||||
|
||||
extern fn selected_range(_this: &Object, _sel: Sel) -> NSRange {
|
||||
extern "C" fn selected_range(_this: &Object, _sel: Sel) -> NSRange {
|
||||
trace!("Triggered `selectedRange`");
|
||||
trace!("Completed `selectedRange`");
|
||||
util::EMPTY_RANGE
|
||||
}
|
||||
|
||||
extern fn set_marked_text(
|
||||
extern "C" fn set_marked_text(
|
||||
this: &mut Object,
|
||||
_sel: Sel,
|
||||
string: id,
|
||||
|
|
@ -359,7 +358,7 @@ extern fn set_marked_text(
|
|||
let marked_text_ref: &mut id = this.get_mut_ivar("markedText");
|
||||
let _: () = msg_send![(*marked_text_ref), release];
|
||||
let marked_text = NSMutableAttributedString::alloc(nil);
|
||||
let has_attr = msg_send![string, isKindOfClass:class!(NSAttributedString)];
|
||||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)];
|
||||
if has_attr {
|
||||
marked_text.initWithAttributedString(string);
|
||||
} else {
|
||||
|
|
@ -370,7 +369,7 @@ extern fn set_marked_text(
|
|||
trace!("Completed `setMarkedText`");
|
||||
}
|
||||
|
||||
extern fn unmark_text(this: &Object, _sel: Sel) {
|
||||
extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
||||
trace!("Triggered `unmarkText`");
|
||||
unsafe {
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
|
|
@ -382,13 +381,13 @@ extern fn unmark_text(this: &Object, _sel: Sel) {
|
|||
trace!("Completed `unmarkText`");
|
||||
}
|
||||
|
||||
extern fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
||||
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
||||
trace!("Triggered `validAttributesForMarkedText`");
|
||||
trace!("Completed `validAttributesForMarkedText`");
|
||||
unsafe { msg_send![class!(NSArray), array] }
|
||||
}
|
||||
|
||||
extern fn attributed_substring_for_proposed_range(
|
||||
extern "C" fn attributed_substring_for_proposed_range(
|
||||
_this: &Object,
|
||||
_sel: Sel,
|
||||
_range: NSRange,
|
||||
|
|
@ -399,13 +398,13 @@ extern fn attributed_substring_for_proposed_range(
|
|||
nil
|
||||
}
|
||||
|
||||
extern fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
|
||||
extern "C" fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
|
||||
trace!("Triggered `characterIndexForPoint`");
|
||||
trace!("Completed `characterIndexForPoint`");
|
||||
0
|
||||
}
|
||||
|
||||
extern fn first_rect_for_character_range(
|
||||
extern "C" fn first_rect_for_character_range(
|
||||
this: &Object,
|
||||
_sel: Sel,
|
||||
_range: NSRange,
|
||||
|
|
@ -425,20 +424,17 @@ extern fn first_rect_for_character_range(
|
|||
(x, y)
|
||||
});
|
||||
trace!("Completed `firstRectForCharacterRange`");
|
||||
NSRect::new(
|
||||
NSPoint::new(x as _, y as _),
|
||||
NSSize::new(0.0, 0.0),
|
||||
)
|
||||
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(0.0, 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
extern fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||
extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||
trace!("Triggered `insertText`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
||||
let has_attr = msg_send![string, isKindOfClass:class!(NSAttributedString)];
|
||||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)];
|
||||
let characters = if has_attr {
|
||||
// This is a *mut NSAttributedString
|
||||
msg_send![string, string]
|
||||
|
|
@ -447,10 +443,8 @@ extern fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range:
|
|||
string
|
||||
};
|
||||
|
||||
let slice = slice::from_raw_parts(
|
||||
characters.UTF8String() as *const c_uchar,
|
||||
characters.len(),
|
||||
);
|
||||
let slice =
|
||||
slice::from_raw_parts(characters.UTF8String() as *const c_uchar, characters.len());
|
||||
let string = str::from_utf8_unchecked(slice);
|
||||
state.is_key_down = true;
|
||||
|
||||
|
|
@ -470,7 +464,7 @@ extern fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range:
|
|||
trace!("Completed `insertText`");
|
||||
}
|
||||
|
||||
extern fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
||||
extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
||||
trace!("Triggered `doCommandBySelector`");
|
||||
// Basically, we're sent this message whenever a keyboard event that doesn't generate a "human readable" character
|
||||
// happens, i.e. newlines, tabs, and Ctrl+C.
|
||||
|
|
@ -513,10 +507,8 @@ fn get_characters(event: id, ignore_modifiers: bool) -> String {
|
|||
};
|
||||
|
||||
assert_ne!(characters, nil);
|
||||
let slice = slice::from_raw_parts(
|
||||
characters.UTF8String() as *const c_uchar,
|
||||
characters.len(),
|
||||
);
|
||||
let slice =
|
||||
slice::from_raw_parts(characters.UTF8String() as *const c_uchar, characters.len());
|
||||
|
||||
let string = str::from_utf8_unchecked(slice);
|
||||
string.to_owned()
|
||||
|
|
@ -528,15 +520,15 @@ fn retrieve_keycode(event: id) -> Option<VirtualKeyCode> {
|
|||
#[inline]
|
||||
fn get_code(ev: id, raw: bool) -> Option<VirtualKeyCode> {
|
||||
let characters = get_characters(ev, raw);
|
||||
characters.chars().next().map_or(None, |c| char_to_keycode(c))
|
||||
characters
|
||||
.chars()
|
||||
.next()
|
||||
.map_or(None, |c| char_to_keycode(c))
|
||||
}
|
||||
|
||||
// Cmd switches Roman letters for Dvorak-QWERTY layout, so we try modified characters first.
|
||||
// If we don't get a match, then we fall back to unmodified characters.
|
||||
let code = get_code(event, false)
|
||||
.or_else(|| {
|
||||
get_code(event, true)
|
||||
});
|
||||
let code = get_code(event, false).or_else(|| get_code(event, true));
|
||||
|
||||
// We've checked all layout related keys, so fall through to scancode.
|
||||
// Reaching this code means that the key is layout-independent (e.g. Backspace, Return).
|
||||
|
|
@ -546,14 +538,11 @@ fn retrieve_keycode(event: id) -> Option<VirtualKeyCode> {
|
|||
// in characters property.
|
||||
code.or_else(|| {
|
||||
let scancode = get_scancode(event);
|
||||
scancode_to_keycode(scancode)
|
||||
.or_else(|| {
|
||||
check_function_keys(&get_characters(event, true))
|
||||
})
|
||||
scancode_to_keycode(scancode).or_else(|| check_function_keys(&get_characters(event, true)))
|
||||
})
|
||||
}
|
||||
|
||||
extern fn key_down(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn key_down(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `keyDown`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -601,14 +590,14 @@ extern fn key_down(this: &Object, _sel: Sel, event: id) {
|
|||
// Some keys (and only *some*, with no known reason) don't trigger `insertText`, while others do...
|
||||
// So, we don't give repeats the opportunity to trigger that, since otherwise our hack will cause some
|
||||
// keys to generate twice as many characters.
|
||||
let array: id = msg_send![class!(NSArray), arrayWithObject:event];
|
||||
let _: () = msg_send![this, interpretKeyEvents:array];
|
||||
let array: id = msg_send![class!(NSArray), arrayWithObject: event];
|
||||
let _: () = msg_send![this, interpretKeyEvents: array];
|
||||
}
|
||||
}
|
||||
trace!("Completed `keyDown`");
|
||||
}
|
||||
|
||||
extern fn key_up(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `keyUp`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -637,7 +626,7 @@ extern fn key_up(this: &Object, _sel: Sel, event: id) {
|
|||
trace!("Completed `keyUp`");
|
||||
}
|
||||
|
||||
extern fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `flagsChanged`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -691,31 +680,31 @@ extern fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
|||
trace!("Completed `flagsChanged`");
|
||||
}
|
||||
|
||||
extern fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
extern "C" fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
unsafe {
|
||||
let window: id = msg_send![this, window];
|
||||
let first_responder: id = msg_send![window, firstResponder];
|
||||
let this_ptr = this as *const _ as *mut _;
|
||||
if first_responder == this_ptr {
|
||||
let (): _ = msg_send![window, selectNextKeyView:this];
|
||||
let (): _ = msg_send![window, selectNextKeyView: this];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
extern "C" fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
unsafe {
|
||||
let window: id = msg_send![this, window];
|
||||
let first_responder: id = msg_send![window, firstResponder];
|
||||
let this_ptr = this as *const _ as *mut _;
|
||||
if first_responder == this_ptr {
|
||||
let (): _ = msg_send![window, selectPreviousKeyView:this];
|
||||
let (): _ = msg_send![window, selectPreviousKeyView: this];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allows us to receive Cmd-. (the shortcut for closing a dialog)
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
||||
extern fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||
trace!("Triggered `cancelOperation`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -764,27 +753,27 @@ fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: Elem
|
|||
}
|
||||
}
|
||||
|
||||
extern fn mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Left, ElementState::Released);
|
||||
}
|
||||
|
||||
extern fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Right, ElementState::Released);
|
||||
}
|
||||
|
||||
extern fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_click(this, event, MouseButton::Middle, ElementState::Released);
|
||||
}
|
||||
|
||||
|
|
@ -801,9 +790,10 @@ fn mouse_motion(this: &Object, event: id) {
|
|||
let view_rect = NSView::frame(view);
|
||||
|
||||
if view_point.x.is_sign_negative()
|
||||
|| view_point.y.is_sign_negative()
|
||||
|| view_point.x > view_rect.size.width
|
||||
|| view_point.y > view_rect.size.height {
|
||||
|| view_point.y.is_sign_negative()
|
||||
|| view_point.x > view_rect.size.width
|
||||
|| view_point.y > view_rect.size.height
|
||||
{
|
||||
// Point is outside of the client area (view)
|
||||
return;
|
||||
}
|
||||
|
|
@ -824,23 +814,23 @@ fn mouse_motion(this: &Object, event: id) {
|
|||
}
|
||||
}
|
||||
|
||||
extern fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_motion(this, event);
|
||||
}
|
||||
|
||||
extern fn mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_motion(this, event);
|
||||
}
|
||||
|
||||
extern fn right_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn right_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_motion(this, event);
|
||||
}
|
||||
|
||||
extern fn other_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn other_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_motion(this, event);
|
||||
}
|
||||
|
||||
extern fn mouse_entered(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn mouse_entered(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `mouseEntered`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -848,7 +838,9 @@ extern fn mouse_entered(this: &Object, _sel: Sel, event: id) {
|
|||
|
||||
let enter_event = Event::WindowEvent {
|
||||
window_id: WindowId(get_window_id(state.ns_window)),
|
||||
event: WindowEvent::CursorEntered { device_id: DEVICE_ID },
|
||||
event: WindowEvent::CursorEntered {
|
||||
device_id: DEVICE_ID,
|
||||
},
|
||||
};
|
||||
|
||||
let move_event = {
|
||||
|
|
@ -866,7 +858,7 @@ extern fn mouse_entered(this: &Object, _sel: Sel, event: id) {
|
|||
device_id: DEVICE_ID,
|
||||
position: (x, y).into(),
|
||||
modifiers: event_mods(event),
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -876,7 +868,7 @@ extern fn mouse_entered(this: &Object, _sel: Sel, event: id) {
|
|||
trace!("Completed `mouseEntered`");
|
||||
}
|
||||
|
||||
extern fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
||||
extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
||||
trace!("Triggered `mouseExited`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -884,7 +876,9 @@ extern fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
|||
|
||||
let window_event = Event::WindowEvent {
|
||||
window_id: WindowId(get_window_id(state.ns_window)),
|
||||
event: WindowEvent::CursorLeft { device_id: DEVICE_ID },
|
||||
event: WindowEvent::CursorLeft {
|
||||
device_id: DEVICE_ID,
|
||||
},
|
||||
};
|
||||
|
||||
AppState::queue_event(window_event);
|
||||
|
|
@ -892,7 +886,7 @@ extern fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
|||
trace!("Completed `mouseExited`");
|
||||
}
|
||||
|
||||
extern fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `scrollWheel`");
|
||||
unsafe {
|
||||
let delta = {
|
||||
|
|
@ -904,7 +898,9 @@ extern fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
|||
}
|
||||
};
|
||||
let phase = match event.phase() {
|
||||
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => TouchPhase::Started,
|
||||
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
|
||||
TouchPhase::Started
|
||||
},
|
||||
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
|
||||
_ => TouchPhase::Moved,
|
||||
};
|
||||
|
|
@ -933,7 +929,7 @@ extern fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
|||
trace!("Completed `scrollWheel`");
|
||||
}
|
||||
|
||||
extern fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
||||
extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `pressureChangeWithEvent`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
|
|
@ -959,6 +955,6 @@ extern fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
|||
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
|
||||
// Note that this *doesn't* help with any missing Cmd inputs.
|
||||
// https://github.com/chromium/chromium/blob/a86a8a6bcfa438fa3ac2eba6f02b3ad1f8e0756f/ui/views/cocoa/bridged_content_view.mm#L816
|
||||
extern fn wants_key_down_for_event(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||
extern "C" fn wants_key_down_for_event(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||
YES
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,44 @@
|
|||
use std::{
|
||||
collections::VecDeque, f64, os::raw::c_void,
|
||||
sync::{Arc, atomic::{Ordering, AtomicBool}, Mutex, Weak},
|
||||
collections::VecDeque,
|
||||
f64,
|
||||
os::raw::c_void,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex, Weak,
|
||||
},
|
||||
};
|
||||
|
||||
use cocoa::{
|
||||
appkit::{
|
||||
self, CGFloat, NSApp, NSApplication, NSApplicationActivationPolicy,
|
||||
NSColor, NSRequestUserAttentionType, NSScreen, NSView, NSWindow,
|
||||
NSWindowButton, NSWindowStyleMask, NSApplicationPresentationOptions
|
||||
NSApplicationPresentationOptions, NSColor, NSRequestUserAttentionType, NSScreen, NSView,
|
||||
NSWindow, NSWindowButton, NSWindowStyleMask,
|
||||
},
|
||||
base::{id, nil},
|
||||
foundation::{NSAutoreleasePool, NSDictionary, NSPoint, NSRect, NSSize, NSString},
|
||||
};
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::{runtime::{Class, Object, Sel, BOOL, YES, NO}, declare::ClassDecl};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dpi::{LogicalPosition, LogicalSize}, icon::Icon,
|
||||
dpi::{LogicalPosition, LogicalSize},
|
||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||
icon::Icon,
|
||||
monitor::MonitorHandle as RootMonitorHandle,
|
||||
window::{
|
||||
CursorIcon, WindowAttributes, WindowId as RootWindowId,
|
||||
platform::macos::{ActivationPolicy, WindowExtMacOS},
|
||||
platform_impl::platform::{
|
||||
app_state::AppState,
|
||||
ffi,
|
||||
monitor::{self, MonitorHandle},
|
||||
util::{self, IdRef},
|
||||
view::{self, new_view},
|
||||
window_delegate::new_delegate,
|
||||
OsError,
|
||||
},
|
||||
};
|
||||
use crate::platform::macos::{ActivationPolicy, WindowExtMacOS};
|
||||
use crate::platform_impl::platform::{
|
||||
OsError,
|
||||
app_state::AppState, ffi, monitor::{self, MonitorHandle},
|
||||
util::{self, IdRef}, view::{self, new_view},
|
||||
window_delegate::new_delegate,
|
||||
window::{CursorIcon, WindowAttributes, WindowId as RootWindowId},
|
||||
};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
|
@ -112,7 +122,8 @@ fn create_window(
|
|||
let frame = match screen {
|
||||
Some(screen) => appkit::NSScreen::frame(screen),
|
||||
None => {
|
||||
let (width, height) = attrs.inner_size
|
||||
let (width, height) = attrs
|
||||
.inner_size
|
||||
.map(|logical| (logical.width, logical.height))
|
||||
.unwrap_or_else(|| (800.0, 600.0));
|
||||
NSRect::new(NSPoint::new(0.0, 0.0), NSSize::new(width, height))
|
||||
|
|
@ -122,18 +133,16 @@ fn create_window(
|
|||
let mut masks = if !attrs.decorations && !screen.is_some() {
|
||||
// Resizable UnownedWindow without a titlebar or borders
|
||||
// if decorations is set to false, ignore pl_attrs
|
||||
NSWindowStyleMask::NSBorderlessWindowMask
|
||||
| NSWindowStyleMask::NSResizableWindowMask
|
||||
NSWindowStyleMask::NSBorderlessWindowMask | NSWindowStyleMask::NSResizableWindowMask
|
||||
} else if pl_attrs.titlebar_hidden {
|
||||
// if the titlebar is hidden, ignore other pl_attrs
|
||||
NSWindowStyleMask::NSBorderlessWindowMask |
|
||||
NSWindowStyleMask::NSResizableWindowMask
|
||||
NSWindowStyleMask::NSBorderlessWindowMask | NSWindowStyleMask::NSResizableWindowMask
|
||||
} else {
|
||||
// default case, resizable window with titlebar and titlebar buttons
|
||||
NSWindowStyleMask::NSClosableWindowMask |
|
||||
NSWindowStyleMask::NSMiniaturizableWindowMask |
|
||||
NSWindowStyleMask::NSResizableWindowMask |
|
||||
NSWindowStyleMask::NSTitledWindowMask
|
||||
NSWindowStyleMask::NSClosableWindowMask
|
||||
| NSWindowStyleMask::NSMiniaturizableWindowMask
|
||||
| NSWindowStyleMask::NSResizableWindowMask
|
||||
| NSWindowStyleMask::NSTitledWindowMask
|
||||
};
|
||||
|
||||
if !attrs.resizable {
|
||||
|
|
@ -171,7 +180,7 @@ fn create_window(
|
|||
NSWindowButton::NSWindowZoomButton,
|
||||
] {
|
||||
let button = ns_window.standardWindowButton_(*titlebar_button);
|
||||
let _: () = msg_send![button, setHidden:YES];
|
||||
let _: () = msg_send![button, setHidden: YES];
|
||||
}
|
||||
}
|
||||
if pl_attrs.movable_by_window_background {
|
||||
|
|
@ -179,7 +188,10 @@ fn create_window(
|
|||
}
|
||||
|
||||
if attrs.always_on_top {
|
||||
let _: () = msg_send![*ns_window, setLevel:ffi::NSWindowLevel::NSFloatingWindowLevel];
|
||||
let _: () = msg_send![
|
||||
*ns_window,
|
||||
setLevel: ffi::NSWindowLevel::NSFloatingWindowLevel
|
||||
];
|
||||
}
|
||||
|
||||
if let Some(increments) = pl_attrs.resize_increments {
|
||||
|
|
@ -206,8 +218,14 @@ lazy_static! {
|
|||
static ref WINDOW_CLASS: WindowClass = unsafe {
|
||||
let window_superclass = class!(NSWindow);
|
||||
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
|
||||
decl.add_method(sel!(canBecomeMainWindow), util::yes as extern fn(&Object, Sel) -> BOOL);
|
||||
decl.add_method(sel!(canBecomeKeyWindow), util::yes as extern fn(&Object, Sel) -> BOOL);
|
||||
decl.add_method(
|
||||
sel!(canBecomeMainWindow),
|
||||
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(canBecomeKeyWindow),
|
||||
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
WindowClass(decl.register())
|
||||
};
|
||||
}
|
||||
|
|
@ -242,14 +260,14 @@ impl From<WindowAttributes> for SharedState {
|
|||
// identical, resulting in a no-op.
|
||||
fullscreen: None,
|
||||
maximized: attribs.maximized,
|
||||
.. Default::default()
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnownedWindow {
|
||||
pub ns_window: IdRef, // never changes
|
||||
pub ns_view: IdRef, // never changes
|
||||
pub ns_view: IdRef, // never changes
|
||||
input_context: IdRef, // never changes
|
||||
pub shared_state: Arc<Mutex<SharedState>>,
|
||||
decorations: AtomicBool,
|
||||
|
|
@ -298,15 +316,20 @@ impl UnownedWindow {
|
|||
|
||||
ns_app.activateIgnoringOtherApps_(YES);
|
||||
|
||||
win_attribs.min_inner_size.map(|dim| set_min_inner_size(*ns_window, dim));
|
||||
win_attribs.max_inner_size.map(|dim| set_max_inner_size(*ns_window, dim));
|
||||
win_attribs
|
||||
.min_inner_size
|
||||
.map(|dim| set_min_inner_size(*ns_window, dim));
|
||||
win_attribs
|
||||
.max_inner_size
|
||||
.map(|dim| set_max_inner_size(*ns_window, dim));
|
||||
|
||||
use cocoa::foundation::NSArray;
|
||||
// register for drag and drop operations.
|
||||
let () = msg_send![*ns_window, registerForDraggedTypes:NSArray::arrayWithObject(
|
||||
nil,
|
||||
appkit::NSFilenamesPboardType,
|
||||
)];
|
||||
let () = msg_send![
|
||||
*ns_window,
|
||||
registerForDraggedTypes:
|
||||
NSArray::arrayWithObject(nil, appkit::NSFilenamesPboardType)
|
||||
];
|
||||
}
|
||||
|
||||
// Since `win_attribs` is put into a mutex below, we'll just copy these
|
||||
|
|
@ -364,19 +387,11 @@ impl UnownedWindow {
|
|||
}
|
||||
|
||||
fn set_style_mask_async(&self, mask: NSWindowStyleMask) {
|
||||
unsafe { util::set_style_mask_async(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
mask,
|
||||
) };
|
||||
unsafe { util::set_style_mask_async(*self.ns_window, *self.ns_view, mask) };
|
||||
}
|
||||
|
||||
fn set_style_mask_sync(&self, mask: NSWindowStyleMask) {
|
||||
unsafe { util::set_style_mask_sync(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
mask,
|
||||
) };
|
||||
unsafe { util::set_style_mask_sync(*self.ns_window, *self.ns_view, mask) };
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Id {
|
||||
|
|
@ -405,20 +420,19 @@ impl UnownedWindow {
|
|||
Ok((
|
||||
frame_rect.origin.x as f64,
|
||||
util::bottom_left_to_top_left(frame_rect),
|
||||
).into())
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
||||
let content_rect = unsafe {
|
||||
NSWindow::contentRectForFrameRect_(
|
||||
*self.ns_window,
|
||||
NSWindow::frame(*self.ns_window),
|
||||
)
|
||||
NSWindow::contentRectForFrameRect_(*self.ns_window, NSWindow::frame(*self.ns_window))
|
||||
};
|
||||
Ok((
|
||||
content_rect.origin.x as f64,
|
||||
util::bottom_left_to_top_left(content_rect),
|
||||
).into())
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn set_outer_position(&self, position: LogicalPosition) {
|
||||
|
|
@ -529,7 +543,10 @@ impl UnownedWindow {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_position(&self, cursor_position: LogicalPosition) -> Result<(), ExternalError> {
|
||||
pub fn set_cursor_position(
|
||||
&self,
|
||||
cursor_position: LogicalPosition,
|
||||
) -> Result<(), ExternalError> {
|
||||
let window_position = self.inner_position().unwrap();
|
||||
let point = appkit::CGPoint {
|
||||
x: (cursor_position.x + window_position.x) as CGFloat,
|
||||
|
|
@ -548,8 +565,8 @@ impl UnownedWindow {
|
|||
// we make it resizable temporalily.
|
||||
let curr_mask = unsafe { self.ns_window.styleMask() };
|
||||
|
||||
let required = NSWindowStyleMask::NSTitledWindowMask
|
||||
| NSWindowStyleMask::NSResizableWindowMask;
|
||||
let required =
|
||||
NSWindowStyleMask::NSTitledWindowMask | NSWindowStyleMask::NSResizableWindowMask;
|
||||
let needs_temp_mask = !curr_mask.contains(required);
|
||||
if needs_temp_mask {
|
||||
self.set_style_mask_sync(required);
|
||||
|
|
@ -566,7 +583,8 @@ impl UnownedWindow {
|
|||
}
|
||||
|
||||
fn saved_style(&self, shared_state: &mut SharedState) -> NSWindowStyleMask {
|
||||
let base_mask = shared_state.saved_style
|
||||
let base_mask = shared_state
|
||||
.saved_style
|
||||
.take()
|
||||
.unwrap_or_else(|| unsafe { self.ns_window.styleMask() });
|
||||
if shared_state.resizable {
|
||||
|
|
@ -620,7 +638,7 @@ impl UnownedWindow {
|
|||
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
|
||||
let shared_state_lock = self.shared_state.lock().unwrap();
|
||||
if shared_state_lock.is_simple_fullscreen {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
let not_fullscreen = {
|
||||
|
|
@ -639,12 +657,14 @@ impl UnownedWindow {
|
|||
current.is_none()
|
||||
};
|
||||
|
||||
unsafe { util::toggle_full_screen_async(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
not_fullscreen,
|
||||
Arc::downgrade(&self.shared_state),
|
||||
) };
|
||||
unsafe {
|
||||
util::toggle_full_screen_async(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
not_fullscreen,
|
||||
Arc::downgrade(&self.shared_state),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -664,7 +684,9 @@ impl UnownedWindow {
|
|||
|
||||
// If we're in fullscreen mode, we wait to apply decoration changes
|
||||
// until we're in `window_did_exit_fullscreen`.
|
||||
if fullscreen { return }
|
||||
if fullscreen {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_mask = {
|
||||
let mut new_mask = if decorations {
|
||||
|
|
@ -727,7 +749,9 @@ impl UnownedWindow {
|
|||
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
|
||||
let value = NSDictionary::valueForKey_(desc, *key);
|
||||
let display_id = msg_send![value, unsignedIntegerValue];
|
||||
RootMonitorHandle { inner: MonitorHandle::new(display_id) }
|
||||
RootMonitorHandle {
|
||||
inner: MonitorHandle::new(display_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -779,7 +803,10 @@ impl WindowExtMacOS for UnownedWindow {
|
|||
let is_simple_fullscreen = shared_state_lock.is_simple_fullscreen;
|
||||
|
||||
// Do nothing if native fullscreen is active.
|
||||
if is_native_fullscreen || (fullscreen && is_simple_fullscreen) || (!fullscreen && !is_simple_fullscreen) {
|
||||
if is_native_fullscreen
|
||||
|| (fullscreen && is_simple_fullscreen)
|
||||
|| (!fullscreen && !is_simple_fullscreen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -799,7 +826,12 @@ impl WindowExtMacOS for UnownedWindow {
|
|||
app.setPresentationOptions_(presentation_options);
|
||||
|
||||
// Hide the titlebar
|
||||
util::toggle_style_mask(*self.ns_window, *self.ns_view, NSWindowStyleMask::NSTitledWindowMask, false);
|
||||
util::toggle_style_mask(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
NSWindowStyleMask::NSTitledWindowMask,
|
||||
false,
|
||||
);
|
||||
|
||||
// Set the window frame to the screen frame size
|
||||
let screen = self.ns_window.screen();
|
||||
|
|
@ -807,8 +839,18 @@ impl WindowExtMacOS for UnownedWindow {
|
|||
NSWindow::setFrame_display_(*self.ns_window, screen_frame, YES);
|
||||
|
||||
// Fullscreen windows can't be resized, minimized, or moved
|
||||
util::toggle_style_mask(*self.ns_window, *self.ns_view, NSWindowStyleMask::NSMiniaturizableWindowMask, false);
|
||||
util::toggle_style_mask(*self.ns_window, *self.ns_view, NSWindowStyleMask::NSResizableWindowMask, false);
|
||||
util::toggle_style_mask(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
NSWindowStyleMask::NSMiniaturizableWindowMask,
|
||||
false,
|
||||
);
|
||||
util::toggle_style_mask(
|
||||
*self.ns_window,
|
||||
*self.ns_view,
|
||||
NSWindowStyleMask::NSResizableWindowMask,
|
||||
false,
|
||||
);
|
||||
NSWindow::setMovable_(*self.ns_window, NO);
|
||||
|
||||
true
|
||||
|
|
|
|||
|
|
@ -1,20 +1,33 @@
|
|||
use std::{f64, os::raw::c_void, sync::{Arc, Weak}};
|
||||
use std::{
|
||||
f64,
|
||||
os::raw::c_void,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
use cocoa::{
|
||||
appkit::{self, NSView, NSWindow}, base::{id, nil},
|
||||
appkit::{self, NSView, NSWindow},
|
||||
base::{id, nil},
|
||||
foundation::NSAutoreleasePool,
|
||||
};
|
||||
use objc::{runtime::{Class, Object, Sel, BOOL, YES, NO}, declare::ClassDecl};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||
};
|
||||
|
||||
use crate::{dpi::LogicalSize, event::{Event, WindowEvent}, window::WindowId};
|
||||
use crate::platform_impl::platform::{
|
||||
app_state::AppState, util::{self, IdRef},
|
||||
window::{get_window_id, UnownedWindow},
|
||||
use crate::{
|
||||
dpi::LogicalSize,
|
||||
event::{Event, WindowEvent},
|
||||
platform_impl::platform::{
|
||||
app_state::AppState,
|
||||
util::{self, IdRef},
|
||||
window::{get_window_id, UnownedWindow},
|
||||
},
|
||||
window::WindowId,
|
||||
};
|
||||
|
||||
pub struct WindowDelegateState {
|
||||
ns_window: IdRef, // never changes
|
||||
ns_view: IdRef, // never changes
|
||||
ns_view: IdRef, // never changes
|
||||
|
||||
window: Weak<UnownedWindow>,
|
||||
|
||||
|
|
@ -33,10 +46,7 @@ pub struct WindowDelegateState {
|
|||
}
|
||||
|
||||
impl WindowDelegateState {
|
||||
pub fn new(
|
||||
window: &Arc<UnownedWindow>,
|
||||
initial_fullscreen: bool,
|
||||
) -> Self {
|
||||
pub fn new(window: &Arc<UnownedWindow>, initial_fullscreen: bool) -> Self {
|
||||
let dpi_factor = window.hidpi_factor();
|
||||
|
||||
let mut delegate_state = WindowDelegateState {
|
||||
|
|
@ -57,11 +67,10 @@ impl WindowDelegateState {
|
|||
}
|
||||
|
||||
fn with_window<F, T>(&mut self, callback: F) -> Option<T>
|
||||
where F: FnOnce(&UnownedWindow) -> T
|
||||
where
|
||||
F: FnOnce(&UnownedWindow) -> T,
|
||||
{
|
||||
self.window
|
||||
.upgrade()
|
||||
.map(|ref window| callback(window))
|
||||
self.window.upgrade().map(|ref window| callback(window))
|
||||
}
|
||||
|
||||
pub fn emit_event(&mut self, event: WindowEvent) {
|
||||
|
|
@ -100,7 +109,7 @@ pub fn new_delegate(window: &Arc<UnownedWindow>, initial_fullscreen: bool) -> Id
|
|||
// This is free'd in `dealloc`
|
||||
let state_ptr = Box::into_raw(Box::new(state)) as *mut c_void;
|
||||
let delegate: id = msg_send![WINDOW_DELEGATE_CLASS.0, alloc];
|
||||
IdRef::new(msg_send![delegate, initWithWinit:state_ptr])
|
||||
IdRef::new(msg_send![delegate, initWithWinit: state_ptr])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,83 +122,81 @@ lazy_static! {
|
|||
let superclass = class!(NSResponder);
|
||||
let mut decl = ClassDecl::new("WinitWindowDelegate", superclass).unwrap();
|
||||
|
||||
decl.add_method(
|
||||
sel!(dealloc),
|
||||
dealloc as extern fn(&Object, Sel),
|
||||
);
|
||||
decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
|
||||
decl.add_method(
|
||||
sel!(initWithWinit:),
|
||||
init_with_winit as extern fn(&Object, Sel, *mut c_void) -> id,
|
||||
init_with_winit as extern "C" fn(&Object, Sel, *mut c_void) -> id,
|
||||
);
|
||||
|
||||
decl.add_method(
|
||||
sel!(windowShouldClose:),
|
||||
window_should_close as extern fn(&Object, Sel, id) -> BOOL,
|
||||
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowWillClose:),
|
||||
window_will_close as extern fn(&Object, Sel, id),
|
||||
window_will_close as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidResize:),
|
||||
window_did_resize as extern fn(&Object, Sel, id),
|
||||
window_did_resize as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidMove:),
|
||||
window_did_move as extern fn(&Object, Sel, id));
|
||||
window_did_move as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidChangeScreen:),
|
||||
window_did_change_screen as extern fn(&Object, Sel, id),
|
||||
window_did_change_screen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidChangeBackingProperties:),
|
||||
window_did_change_backing_properties as extern fn(&Object, Sel, id),
|
||||
window_did_change_backing_properties as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidBecomeKey:),
|
||||
window_did_become_key as extern fn(&Object, Sel, id),
|
||||
window_did_become_key as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidResignKey:),
|
||||
window_did_resign_key as extern fn(&Object, Sel, id),
|
||||
window_did_resign_key as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
decl.add_method(
|
||||
sel!(draggingEntered:),
|
||||
dragging_entered as extern fn(&Object, Sel, id) -> BOOL,
|
||||
dragging_entered as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(prepareForDragOperation:),
|
||||
prepare_for_drag_operation as extern fn(&Object, Sel, id) -> BOOL,
|
||||
prepare_for_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(performDragOperation:),
|
||||
perform_drag_operation as extern fn(&Object, Sel, id) -> BOOL,
|
||||
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(concludeDragOperation:),
|
||||
conclude_drag_operation as extern fn(&Object, Sel, id),
|
||||
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(draggingExited:),
|
||||
dragging_exited as extern fn(&Object, Sel, id),
|
||||
dragging_exited as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
decl.add_method(
|
||||
sel!(windowDidEnterFullScreen:),
|
||||
window_did_enter_fullscreen as extern fn(&Object, Sel, id),
|
||||
window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowWillEnterFullScreen:),
|
||||
window_will_enter_fullscreen as extern fn(&Object, Sel, id),
|
||||
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidExitFullScreen:),
|
||||
window_did_exit_fullscreen as extern fn(&Object, Sel, id),
|
||||
window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidFailToEnterFullScreen:),
|
||||
window_did_fail_to_enter_fullscreen as extern fn(&Object, Sel, id),
|
||||
window_did_fail_to_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
decl.add_ivar::<*mut c_void>("winitState");
|
||||
|
|
@ -207,47 +214,47 @@ fn with_state<F: FnOnce(&mut WindowDelegateState) -> T, T>(this: &Object, callba
|
|||
callback(state_ptr);
|
||||
}
|
||||
|
||||
extern fn dealloc(this: &Object, _sel: Sel) {
|
||||
extern "C" fn dealloc(this: &Object, _sel: Sel) {
|
||||
with_state(this, |state| unsafe {
|
||||
Box::from_raw(state as *mut WindowDelegateState);
|
||||
});
|
||||
}
|
||||
|
||||
extern fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> id {
|
||||
extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> id {
|
||||
unsafe {
|
||||
let this: id = msg_send![this, init];
|
||||
if this != nil {
|
||||
(*this).set_ivar("winitState", state);
|
||||
with_state(&*this, |state| {
|
||||
let () = msg_send![*state.ns_window, setDelegate:this];
|
||||
let () = msg_send![*state.ns_window, setDelegate: this];
|
||||
});
|
||||
}
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||
trace!("Triggered `windowShouldClose:`");
|
||||
with_state(this, |state| state.emit_event(WindowEvent::CloseRequested));
|
||||
trace!("Completed `windowShouldClose:`");
|
||||
NO
|
||||
}
|
||||
|
||||
extern fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowWillClose:`");
|
||||
with_state(this, |state| unsafe {
|
||||
// `setDelegate:` retains the previous value and then autoreleases it
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
// Since El Capitan, we need to be careful that delegate methods can't
|
||||
// be called after the window closes.
|
||||
let () = msg_send![*state.ns_window, setDelegate:nil];
|
||||
let () = msg_send![*state.ns_window, setDelegate: nil];
|
||||
pool.drain();
|
||||
state.emit_event(WindowEvent::Destroyed);
|
||||
});
|
||||
trace!("Completed `windowWillClose:`");
|
||||
}
|
||||
|
||||
extern fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidResize:`");
|
||||
with_state(this, |state| {
|
||||
state.emit_resize_event();
|
||||
|
|
@ -257,7 +264,7 @@ extern fn window_did_resize(this: &Object, _: Sel, _: id) {
|
|||
}
|
||||
|
||||
// This won't be triggered if the move was part of a resize.
|
||||
extern fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidMove:`");
|
||||
with_state(this, |state| {
|
||||
state.emit_move_event();
|
||||
|
|
@ -265,12 +272,10 @@ extern fn window_did_move(this: &Object, _: Sel, _: id) {
|
|||
trace!("Completed `windowDidMove:`");
|
||||
}
|
||||
|
||||
extern fn window_did_change_screen(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_change_screen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidChangeScreen:`");
|
||||
with_state(this, |state| {
|
||||
let dpi_factor = unsafe {
|
||||
NSWindow::backingScaleFactor(*state.ns_window)
|
||||
} as f64;
|
||||
let dpi_factor = unsafe { NSWindow::backingScaleFactor(*state.ns_window) } as f64;
|
||||
if state.previous_dpi_factor != dpi_factor {
|
||||
state.previous_dpi_factor = dpi_factor;
|
||||
state.emit_event(WindowEvent::HiDpiFactorChanged(dpi_factor));
|
||||
|
|
@ -281,12 +286,10 @@ extern fn window_did_change_screen(this: &Object, _: Sel, _: id) {
|
|||
}
|
||||
|
||||
// This will always be called before `window_did_change_screen`.
|
||||
extern fn window_did_change_backing_properties(this: &Object, _:Sel, _:id) {
|
||||
extern "C" fn window_did_change_backing_properties(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidChangeBackingProperties:`");
|
||||
with_state(this, |state| {
|
||||
let dpi_factor = unsafe {
|
||||
NSWindow::backingScaleFactor(*state.ns_window)
|
||||
} as f64;
|
||||
let dpi_factor = unsafe { NSWindow::backingScaleFactor(*state.ns_window) } as f64;
|
||||
if state.previous_dpi_factor != dpi_factor {
|
||||
state.previous_dpi_factor = dpi_factor;
|
||||
state.emit_event(WindowEvent::HiDpiFactorChanged(dpi_factor));
|
||||
|
|
@ -296,7 +299,7 @@ extern fn window_did_change_backing_properties(this: &Object, _:Sel, _:id) {
|
|||
trace!("Completed `windowDidChangeBackingProperties:`");
|
||||
}
|
||||
|
||||
extern fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidBecomeKey:`");
|
||||
with_state(this, |state| {
|
||||
// TODO: center the cursor if the window had mouse grab when it
|
||||
|
|
@ -306,7 +309,7 @@ extern fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
|||
trace!("Completed `windowDidBecomeKey:`");
|
||||
}
|
||||
|
||||
extern fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidResignKey:`");
|
||||
with_state(this, |state| {
|
||||
state.emit_event(WindowEvent::Focused(false));
|
||||
|
|
@ -315,11 +318,10 @@ extern fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
|||
}
|
||||
|
||||
/// Invoked when the dragged image enters destination bounds or frame
|
||||
extern fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
trace!("Triggered `draggingEntered:`");
|
||||
|
||||
use cocoa::appkit::NSPasteboard;
|
||||
use cocoa::foundation::NSFastEnumeration;
|
||||
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||
use std::path::PathBuf;
|
||||
|
||||
let pb: id = unsafe { msg_send![sender, draggingPasteboard] };
|
||||
|
|
@ -337,25 +339,24 @@ extern fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
|||
state.emit_event(WindowEvent::HoveredFile(PathBuf::from(path)));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
trace!("Completed `draggingEntered:`");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked when the image is released
|
||||
extern fn prepare_for_drag_operation(_: &Object, _: Sel, _: id) -> BOOL {
|
||||
extern "C" fn prepare_for_drag_operation(_: &Object, _: Sel, _: id) -> BOOL {
|
||||
trace!("Triggered `prepareForDragOperation:`");
|
||||
trace!("Completed `prepareForDragOperation:`");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked after the released image has been removed from the screen
|
||||
extern fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
extern "C" fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
trace!("Triggered `performDragOperation:`");
|
||||
|
||||
use cocoa::appkit::NSPasteboard;
|
||||
use cocoa::foundation::NSFastEnumeration;
|
||||
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||
use std::path::PathBuf;
|
||||
|
||||
let pb: id = unsafe { msg_send![sender, draggingPasteboard] };
|
||||
|
|
@ -373,38 +374,42 @@ extern fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL {
|
|||
state.emit_event(WindowEvent::DroppedFile(PathBuf::from(path)));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
trace!("Completed `performDragOperation:`");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked when the dragging operation is complete
|
||||
extern fn conclude_drag_operation(_: &Object, _: Sel, _: id) {
|
||||
extern "C" fn conclude_drag_operation(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `concludeDragOperation:`");
|
||||
trace!("Completed `concludeDragOperation:`");
|
||||
}
|
||||
|
||||
/// Invoked when the dragging operation is cancelled
|
||||
extern fn dragging_exited(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `draggingExited:`");
|
||||
with_state(this, |state| state.emit_event(WindowEvent::HoveredFileCancelled));
|
||||
with_state(this, |state| {
|
||||
state.emit_event(WindowEvent::HoveredFileCancelled)
|
||||
});
|
||||
trace!("Completed `draggingExited:`");
|
||||
}
|
||||
|
||||
/// Invoked when before enter fullscreen
|
||||
extern fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowWillEnterFullscreen:`");
|
||||
with_state(this, |state| state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_will_enter_fullscreen`");
|
||||
window.shared_state.lock().unwrap().maximized = window.is_zoomed();
|
||||
trace!("Unlocked shared state in `window_will_enter_fullscreen`");
|
||||
}));
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_will_enter_fullscreen`");
|
||||
window.shared_state.lock().unwrap().maximized = window.is_zoomed();
|
||||
trace!("Unlocked shared state in `window_will_enter_fullscreen`");
|
||||
})
|
||||
});
|
||||
trace!("Completed `windowWillEnterFullscreen:`");
|
||||
}
|
||||
|
||||
/// Invoked when entered fullscreen
|
||||
extern fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidEnterFullscreen:`");
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
|
|
@ -419,11 +424,13 @@ extern fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
|||
}
|
||||
|
||||
/// Invoked when exited fullscreen
|
||||
extern fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidExitFullscreen:`");
|
||||
with_state(this, |state| state.with_window(|window| {
|
||||
window.restore_state_from_fullscreen();
|
||||
}));
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
window.restore_state_from_fullscreen();
|
||||
})
|
||||
});
|
||||
trace!("Completed `windowDidExitFullscreen:`");
|
||||
}
|
||||
|
||||
|
|
@ -443,15 +450,17 @@ extern fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
|||
/// due to being in the midst of handling some other animation or user gesture.
|
||||
/// This method indicates that there was an error, and you should clean up any
|
||||
/// work you may have done to prepare to enter full-screen mode.
|
||||
extern fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidFailToEnterFullscreen:`");
|
||||
with_state(this, |state| {
|
||||
if state.initial_fullscreen {
|
||||
let _: () = unsafe { msg_send![*state.ns_window,
|
||||
performSelector:sel!(toggleFullScreen:)
|
||||
withObject:nil
|
||||
afterDelay: 0.5
|
||||
] };
|
||||
let _: () = unsafe {
|
||||
msg_send![*state.ns_window,
|
||||
performSelector:sel!(toggleFullScreen:)
|
||||
withObject:nil
|
||||
afterDelay: 0.5
|
||||
]
|
||||
};
|
||||
} else {
|
||||
state.with_window(|window| window.restore_state_from_fullscreen());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue