use objc2_app_kit::{NSEvent, NSEventModifierFlags, NSEventType}; use super::{Factor, Platform, WinRef}; pub struct WinEvent<'a>(pub &'a NSEvent); impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, win: WinRef<'_>) -> Option { fn other(evt: &NSEvent) -> types::Button { let id = unsafe { evt.buttonNumber() }; let id = id % 255; let id = id as u8; types::Button::Mouse(id) } let evt = self.0; let (button, phase) = match unsafe { self.0.r#type() } { NSEventType::LeftMouseDown => (types::Button::Left, types::Phase::Start), NSEventType::LeftMouseUp => (types::Button::Left, types::Phase::End), NSEventType::LeftMouseDragged => (types::Button::Left, types::Phase::Update), NSEventType::RightMouseDown => (types::Button::Right, types::Phase::Start), NSEventType::RightMouseUp => (types::Button::Right, types::Phase::End), NSEventType::RightMouseDragged => (types::Button::Right, types::Phase::Update), NSEventType::OtherMouseDown => (other(evt), types::Phase::Start), NSEventType::OtherMouseUp => (other(evt), types::Phase::End), NSEventType::OtherMouseDragged => (other(evt), types::Phase::Update), NSEventType::MouseMoved => (types::Button::Left, types::Phase::Update), _ => return None, }; let point = { let point = unsafe { evt.locationInWindow() }; let point = win.1.convertPoint_fromView(point, None); let factor = Factor::from(win.0); (factor.to_f32(point.x), factor.to_f32(point.y)) }; let metas = conv_metas(evt); Some(types::EvtMouse::new(button, phase, point, metas)) } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, win: WinRef<'_>) -> Option { let event_type = unsafe { self.0.r#type() }; match event_type { NSEventType::ScrollWheel => { let (x, y) = unsafe { (self.0.scrollingDeltaX(), self.0.scrollingDeltaY()) }; Some(if unsafe { self.0.hasPreciseScrollingDeltas() } { let factor = Factor::from(win.0); types::EvtWheel::Pixel(factor.to_f32(x), factor.to_f32(y), 0.) } else { types::EvtWheel::Line(x as f32, y as f32, 0.) }) } _ => None, } } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: WinRef<'_>) -> Option { let evt = self.0; let state = match unsafe { evt.r#type() } { NSEventType::KeyDown => types::State::Down, NSEventType::KeyUp => types::State::Up, _ => return None, }; let code = conv_code(evt); let key = conv_key(evt, code); let location = code.into(); let metas = conv_metas(evt); let repeat = unsafe { evt.isARepeat() }; let composing = false; Some(types::EvtKey::new(key, code, state, location, metas, repeat, composing)) } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: WinRef<'_>) -> Option { None } } fn conv_metas(evt: &NSEvent) -> types::Metas { let mut metas = types::Metas::EMPTY; let flags = unsafe { evt.modifierFlags() }; use NSEventModifierFlags as F; if flags.contains(F::NSEventModifierFlagShift) { metas.insert(types::Metas::SHIFT); } if flags.contains(F::NSEventModifierFlagControl) { metas.insert(types::Metas::CONTROL); } if flags.contains(F::NSEventModifierFlagOption) { metas.insert(types::Metas::ALT); } if flags.contains(F::NSEventModifierFlagCommand) { metas.insert(types::Metas::META); } metas } fn conv_key(evt: &NSEvent, code: types::Code) -> types::Key { if let Some(chars) = unsafe { evt.characters() } { return types::Key::Character(chars.to_string().into()); } if let Some(chars) = unsafe { evt.charactersIgnoringModifiers() } { return types::Key::Character(chars.to_string().into()); } code.into() } fn conv_code(evt: &NSEvent) -> types::Code { let scancode = unsafe { evt.keyCode() }; use types::Code as KeyCode; match scancode { 0x00 => KeyCode::KeyA, 0x01 => KeyCode::KeyS, 0x02 => KeyCode::KeyD, 0x03 => KeyCode::KeyF, 0x04 => KeyCode::KeyH, 0x05 => KeyCode::KeyG, 0x06 => KeyCode::KeyZ, 0x07 => KeyCode::KeyX, 0x08 => KeyCode::KeyC, 0x09 => KeyCode::KeyV, // 0x0a => World 1, 0x0b => KeyCode::KeyB, 0x0c => KeyCode::KeyQ, 0x0d => KeyCode::KeyW, 0x0e => KeyCode::KeyE, 0x0f => KeyCode::KeyR, 0x10 => KeyCode::KeyY, 0x11 => KeyCode::KeyT, 0x12 => KeyCode::Digit1, 0x13 => KeyCode::Digit2, 0x14 => KeyCode::Digit3, 0x15 => KeyCode::Digit4, 0x16 => KeyCode::Digit6, 0x17 => KeyCode::Digit5, 0x18 => KeyCode::Equal, 0x19 => KeyCode::Digit9, 0x1a => KeyCode::Digit7, 0x1b => KeyCode::Minus, 0x1c => KeyCode::Digit8, 0x1d => KeyCode::Digit0, 0x1e => KeyCode::BracketRight, 0x1f => KeyCode::KeyO, 0x20 => KeyCode::KeyU, 0x21 => KeyCode::BracketLeft, 0x22 => KeyCode::KeyI, 0x23 => KeyCode::KeyP, 0x24 => KeyCode::Enter, 0x25 => KeyCode::KeyL, 0x26 => KeyCode::KeyJ, 0x27 => KeyCode::Quote, 0x28 => KeyCode::KeyK, 0x29 => KeyCode::Semicolon, 0x2a => KeyCode::Backslash, 0x2b => KeyCode::Comma, 0x2c => KeyCode::Slash, 0x2d => KeyCode::KeyN, 0x2e => KeyCode::KeyM, 0x2f => KeyCode::Period, 0x30 => KeyCode::Tab, 0x31 => KeyCode::Space, 0x32 => KeyCode::Backquote, 0x33 => KeyCode::Backspace, // 0x34 => unknown, 0x35 => KeyCode::Escape, 0x36 => KeyCode::MetaRight, 0x37 => KeyCode::MetaLeft, 0x38 => KeyCode::ShiftLeft, 0x39 => KeyCode::CapsLock, 0x3a => KeyCode::AltLeft, 0x3b => KeyCode::ControlLeft, 0x3c => KeyCode::ShiftRight, 0x3d => KeyCode::AltRight, 0x3e => KeyCode::ControlRight, 0x3f => KeyCode::Fn, 0x40 => KeyCode::F17, 0x41 => KeyCode::NumpadDecimal, // 0x42 -> unknown, 0x43 => KeyCode::NumpadMultiply, // 0x44 => unknown, 0x45 => KeyCode::NumpadAdd, // 0x46 => unknown, 0x47 => KeyCode::NumLock, // 0x48 => KeyCode::NumpadClear, // TODO: (Artur) for me, kVK_VolumeUp is 0x48 // macOS 10.11 // /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/ // Versions/A/Headers/Events.h 0x49 => KeyCode::AudioVolumeUp, 0x4a => KeyCode::AudioVolumeDown, 0x4b => KeyCode::NumpadDivide, 0x4c => KeyCode::NumpadEnter, // 0x4d => unknown, 0x4e => KeyCode::NumpadSubtract, 0x4f => KeyCode::F18, 0x50 => KeyCode::F19, 0x51 => KeyCode::NumpadEqual, 0x52 => KeyCode::Numpad0, 0x53 => KeyCode::Numpad1, 0x54 => KeyCode::Numpad2, 0x55 => KeyCode::Numpad3, 0x56 => KeyCode::Numpad4, 0x57 => KeyCode::Numpad5, 0x58 => KeyCode::Numpad6, 0x59 => KeyCode::Numpad7, 0x5a => KeyCode::F20, 0x5b => KeyCode::Numpad8, 0x5c => KeyCode::Numpad9, 0x5d => KeyCode::IntlYen, // 0x5e => JIS Ro, // 0x5f => unknown, 0x60 => KeyCode::F5, 0x61 => KeyCode::F6, 0x62 => KeyCode::F7, 0x63 => KeyCode::F3, 0x64 => KeyCode::F8, 0x65 => KeyCode::F9, // 0x66 => JIS Eisuu (macOS), 0x67 => KeyCode::F11, // 0x68 => JIS Kanna (macOS), 0x69 => KeyCode::F13, 0x6a => KeyCode::F16, 0x6b => KeyCode::F14, // 0x6c => unknown, 0x6d => KeyCode::F10, // 0x6e => unknown, 0x6f => KeyCode::F12, // 0x70 => unknown, 0x71 => KeyCode::F15, 0x72 => KeyCode::Insert, 0x73 => KeyCode::Home, 0x74 => KeyCode::PageUp, 0x75 => KeyCode::Delete, 0x76 => KeyCode::F4, 0x77 => KeyCode::End, 0x78 => KeyCode::F2, 0x79 => KeyCode::PageDown, 0x7a => KeyCode::F1, 0x7b => KeyCode::ArrowLeft, 0x7c => KeyCode::ArrowRight, 0x7d => KeyCode::ArrowDown, 0x7e => KeyCode::ArrowUp, // 0x7f => unknown, // 0xA is the caret (^) an macOS's German QERTZ layout. This key is at the same location as // backquote (`) on Windows' US layout. 0xa => KeyCode::Backquote, _ => KeyCode::Unidentified(scancode as _), } }