|
| 1 | +use cocoa::{appkit, base::id}; |
| 2 | +use objc::{declare::ClassDecl, runtime::{Class, Object, Sel}}; |
| 3 | + |
| 4 | +use platform_impl::platform::util; |
| 5 | + |
| 6 | +pub struct AppClass(pub *const Class); |
| 7 | +unsafe impl Send for AppClass {} |
| 8 | +unsafe impl Sync for AppClass {} |
| 9 | + |
| 10 | +lazy_static! { |
| 11 | + pub static ref APP_CLASS: AppClass = unsafe { |
| 12 | + let superclass = class!(NSApplication); |
| 13 | + let mut decl = ClassDecl::new("WinitApp", superclass).unwrap(); |
| 14 | + |
| 15 | + decl.add_method( |
| 16 | + sel!(sendEvent:), |
| 17 | + send_event as extern fn(&Object, Sel, id), |
| 18 | + ); |
| 19 | + |
| 20 | + AppClass(decl.register()) |
| 21 | + }; |
| 22 | +} |
| 23 | + |
| 24 | +// Normally, holding Cmd + any key never sends us a `keyUp` event for that key. |
| 25 | +// Overriding `sendEvent:` like this fixes that. (https://stackoverflow.com/a/15294196) |
| 26 | +// Fun fact: Firefox still has this bug! (https://bugzilla.mozilla.org/show_bug.cgi?id=1299553) |
| 27 | +extern fn send_event(this: &Object, _sel: Sel, event: id) { |
| 28 | + unsafe { |
| 29 | + use self::appkit::NSEvent; |
| 30 | + // For posterity, there are some undocumented event types |
| 31 | + // (https://github.com/servo/cocoa-rs/issues/155) |
| 32 | + // but that doesn't really matter here. |
| 33 | + let event_type = event.eventType(); |
| 34 | + let modifier_flags = event.modifierFlags(); |
| 35 | + if event_type == appkit::NSKeyUp && util::has_flag( |
| 36 | + modifier_flags, |
| 37 | + appkit::NSEventModifierFlags::NSCommandKeyMask, |
| 38 | + ) { |
| 39 | + let key_window: id = msg_send![this, keyWindow]; |
| 40 | + let _: () = msg_send![key_window, sendEvent:event]; |
| 41 | + } else { |
| 42 | + let superclass = util::superclass(this); |
| 43 | + let _: () = msg_send![super(this, superclass), sendEvent:event]; |
| 44 | + } |
| 45 | + } |
| 46 | +} |
0 commit comments