event.rs

  1use crate::{geometry::vector::vec2f, keymap::Keystroke, platform::Event};
  2use cocoa::{
  3    appkit::{NSEvent, NSEventModifierFlags, NSEventType},
  4    base::{id, nil, YES},
  5    foundation::NSString as _,
  6};
  7use std::{ffi::CStr, os::raw::c_char};
  8
  9impl Event {
 10    pub unsafe fn from_native(native_event: id, window_height: Option<f32>) -> Option<Self> {
 11        let event_type = native_event.eventType();
 12
 13        // Filter out event types that aren't in the NSEventType enum.
 14        // See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
 15        match event_type as u64 {
 16            0 | 21 | 32 | 33 | 35 | 36 | 37 => {
 17                return None;
 18            }
 19            _ => {}
 20        }
 21
 22        match event_type {
 23            NSEventType::NSKeyDown => {
 24                let modifiers = native_event.modifierFlags();
 25                let unmodified_chars = native_event.charactersIgnoringModifiers();
 26                let unmodified_chars = CStr::from_ptr(unmodified_chars.UTF8String() as *mut c_char)
 27                    .to_str()
 28                    .unwrap();
 29
 30                let unmodified_chars = if let Some(first_char) = unmodified_chars.chars().next() {
 31                    use cocoa::appkit::*;
 32                    const BACKSPACE_KEY: u16 = 0x7f;
 33                    const ENTER_KEY: u16 = 0x0d;
 34                    const ESCAPE_KEY: u16 = 0x1b;
 35                    const TAB_KEY: u16 = 0x09;
 36
 37                    #[allow(non_upper_case_globals)]
 38                    match first_char as u16 {
 39                        BACKSPACE_KEY => "backspace",
 40                        ENTER_KEY => "enter",
 41                        ESCAPE_KEY => "escape",
 42                        TAB_KEY => "tab",
 43
 44                        NSUpArrowFunctionKey => "up",
 45                        NSDownArrowFunctionKey => "down",
 46                        NSLeftArrowFunctionKey => "left",
 47                        NSRightArrowFunctionKey => "right",
 48                        NSPageUpFunctionKey => "pageup",
 49                        NSPageDownFunctionKey => "pagedown",
 50                        NSDeleteFunctionKey => "delete",
 51                        NSF1FunctionKey => "f1",
 52                        NSF2FunctionKey => "f2",
 53                        NSF3FunctionKey => "f3",
 54                        NSF4FunctionKey => "f4",
 55                        NSF5FunctionKey => "f5",
 56                        NSF6FunctionKey => "f6",
 57                        NSF7FunctionKey => "f7",
 58                        NSF8FunctionKey => "f8",
 59                        NSF9FunctionKey => "f9",
 60                        NSF10FunctionKey => "f10",
 61                        NSF11FunctionKey => "f11",
 62                        NSF12FunctionKey => "f12",
 63
 64                        _ => unmodified_chars,
 65                    }
 66                } else {
 67                    return None;
 68                };
 69
 70                let chars = native_event.characters();
 71                let chars = CStr::from_ptr(chars.UTF8String() as *mut c_char)
 72                    .to_str()
 73                    .unwrap()
 74                    .into();
 75
 76                Some(Self::KeyDown {
 77                    keystroke: Keystroke {
 78                        ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
 79                        alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
 80                        shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
 81                        cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
 82                        key: unmodified_chars.into(),
 83                    },
 84                    chars,
 85                    is_held: native_event.isARepeat() == YES,
 86                })
 87            }
 88            NSEventType::NSLeftMouseDown => {
 89                window_height.map(|window_height| Self::LeftMouseDown {
 90                    position: vec2f(
 91                        native_event.locationInWindow().x as f32,
 92                        window_height - native_event.locationInWindow().y as f32,
 93                    ),
 94                    cmd: native_event
 95                        .modifierFlags()
 96                        .contains(NSEventModifierFlags::NSCommandKeyMask),
 97                })
 98            }
 99            NSEventType::NSLeftMouseUp => window_height.map(|window_height| Self::LeftMouseUp {
100                position: vec2f(
101                    native_event.locationInWindow().x as f32,
102                    window_height - native_event.locationInWindow().y as f32,
103                ),
104            }),
105            NSEventType::NSLeftMouseDragged => {
106                window_height.map(|window_height| Self::LeftMouseDragged {
107                    position: vec2f(
108                        native_event.locationInWindow().x as f32,
109                        window_height - native_event.locationInWindow().y as f32,
110                    ),
111                })
112            }
113            NSEventType::NSScrollWheel => window_height.map(|window_height| Self::ScrollWheel {
114                position: vec2f(
115                    native_event.locationInWindow().x as f32,
116                    window_height - native_event.locationInWindow().y as f32,
117                ),
118                delta: vec2f(
119                    native_event.scrollingDeltaX() as f32,
120                    native_event.scrollingDeltaY() as f32,
121                ),
122                precise: native_event.hasPreciseScrollingDeltas() == YES,
123            }),
124            NSEventType::NSMouseMoved => window_height.map(|window_height| Self::MouseMoved {
125                position: vec2f(
126                    native_event.locationInWindow().x as f32,
127                    window_height - native_event.locationInWindow().y as f32,
128                ),
129                left_mouse_down: NSEvent::pressedMouseButtons(nil) & 1 != 0,
130            }),
131            _ => None,
132        }
133    }
134}