* WIP - Make EL2 DPI changes and implement on Windows (#895) * Modify DPI API publicly and on Windows * Add generic Position and make dpi creation functions const * Make examples work * Fix fullscreen windows not appearing * Replace Logical coordinates in window events with Physical coordinates * Update HiDpiFactorChanged * Document to_static * fix app_state errors * fixes hidpi related errors in window_delegate * fix bad merge * dpi_factor edits in window_delegate * fixes type and lifetime errors in window and window_delegate * applies fmt * complies with @aleksijuvani requested changes * modifies Handler lifetimes * fixes lifetime isues, adds propper handling for HiDpiChanged * applies fmt * restore original lifetimes * solution is somewhere out there * applies fmt * pass as references * resolves issue with HANDLER * crate visible type error * fixes visibility issues * applies fmt * deals with warnings * simplifies new_inner_size setting algorthm * moves proxy instead of referencing it and removes double deref from proxy.ns_window * makes @Osspial tests (https://github.com/rust-windowing/winit/pull/997\#discussion_r301852354) pass * complies with @aleksijuvani suggested changes * makes max window size std::f32::MAX Changes from rebasing: * fixes compile errors * applies fmt * reimplements HiDpiFactorChanged after #1173 merge * uses EventWrappers
303 lines
10 KiB
Rust
303 lines
10 KiB
Rust
use std::os::raw::c_ushort;
|
|
|
|
use cocoa::{
|
|
appkit::{NSEvent, NSEventModifierFlags},
|
|
base::id,
|
|
};
|
|
|
|
use crate::{
|
|
dpi::LogicalSize,
|
|
event::{ElementState, Event, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent},
|
|
platform_impl::platform::{
|
|
util::{IdRef, Never},
|
|
DEVICE_ID,
|
|
},
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub enum EventWrapper {
|
|
StaticEvent(Event<'static, Never>),
|
|
EventProxy(EventProxy),
|
|
}
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
pub enum EventProxy {
|
|
HiDpiFactorChangedProxy {
|
|
ns_window: IdRef,
|
|
suggested_size: LogicalSize,
|
|
hidpi_factor: f64,
|
|
},
|
|
}
|
|
|
|
pub fn char_to_keycode(c: char) -> Option<VirtualKeyCode> {
|
|
// We only translate keys that are affected by keyboard layout.
|
|
//
|
|
// Note that since keys are translated in a somewhat "dumb" way (reading character)
|
|
// there is a concern that some combination, i.e. Cmd+char, causes the wrong
|
|
// letter to be received, and so we receive the wrong key.
|
|
//
|
|
// Implementation reference: https://github.com/WebKit/webkit/blob/82bae82cf0f329dbe21059ef0986c4e92fea4ba6/Source/WebCore/platform/cocoa/KeyEventCocoa.mm#L626
|
|
Some(match c {
|
|
'a' | 'A' => VirtualKeyCode::A,
|
|
'b' | 'B' => VirtualKeyCode::B,
|
|
'c' | 'C' => VirtualKeyCode::C,
|
|
'd' | 'D' => VirtualKeyCode::D,
|
|
'e' | 'E' => VirtualKeyCode::E,
|
|
'f' | 'F' => VirtualKeyCode::F,
|
|
'g' | 'G' => VirtualKeyCode::G,
|
|
'h' | 'H' => VirtualKeyCode::H,
|
|
'i' | 'I' => VirtualKeyCode::I,
|
|
'j' | 'J' => VirtualKeyCode::J,
|
|
'k' | 'K' => VirtualKeyCode::K,
|
|
'l' | 'L' => VirtualKeyCode::L,
|
|
'm' | 'M' => VirtualKeyCode::M,
|
|
'n' | 'N' => VirtualKeyCode::N,
|
|
'o' | 'O' => VirtualKeyCode::O,
|
|
'p' | 'P' => VirtualKeyCode::P,
|
|
'q' | 'Q' => VirtualKeyCode::Q,
|
|
'r' | 'R' => VirtualKeyCode::R,
|
|
's' | 'S' => VirtualKeyCode::S,
|
|
't' | 'T' => VirtualKeyCode::T,
|
|
'u' | 'U' => VirtualKeyCode::U,
|
|
'v' | 'V' => VirtualKeyCode::V,
|
|
'w' | 'W' => VirtualKeyCode::W,
|
|
'x' | 'X' => VirtualKeyCode::X,
|
|
'y' | 'Y' => VirtualKeyCode::Y,
|
|
'z' | 'Z' => VirtualKeyCode::Z,
|
|
'1' | '!' => VirtualKeyCode::Key1,
|
|
'2' | '@' => VirtualKeyCode::Key2,
|
|
'3' | '#' => VirtualKeyCode::Key3,
|
|
'4' | '$' => VirtualKeyCode::Key4,
|
|
'5' | '%' => VirtualKeyCode::Key5,
|
|
'6' | '^' => VirtualKeyCode::Key6,
|
|
'7' | '&' => VirtualKeyCode::Key7,
|
|
'8' | '*' => VirtualKeyCode::Key8,
|
|
'9' | '(' => VirtualKeyCode::Key9,
|
|
'0' | ')' => VirtualKeyCode::Key0,
|
|
'=' | '+' => VirtualKeyCode::Equals,
|
|
'-' | '_' => VirtualKeyCode::Minus,
|
|
']' | '}' => VirtualKeyCode::RBracket,
|
|
'[' | '{' => VirtualKeyCode::LBracket,
|
|
'\'' | '"' => VirtualKeyCode::Apostrophe,
|
|
';' | ':' => VirtualKeyCode::Semicolon,
|
|
'\\' | '|' => VirtualKeyCode::Backslash,
|
|
',' | '<' => VirtualKeyCode::Comma,
|
|
'/' | '?' => VirtualKeyCode::Slash,
|
|
'.' | '>' => VirtualKeyCode::Period,
|
|
'`' | '~' => VirtualKeyCode::Grave,
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
pub fn scancode_to_keycode(scancode: c_ushort) -> Option<VirtualKeyCode> {
|
|
Some(match scancode {
|
|
0x00 => VirtualKeyCode::A,
|
|
0x01 => VirtualKeyCode::S,
|
|
0x02 => VirtualKeyCode::D,
|
|
0x03 => VirtualKeyCode::F,
|
|
0x04 => VirtualKeyCode::H,
|
|
0x05 => VirtualKeyCode::G,
|
|
0x06 => VirtualKeyCode::Z,
|
|
0x07 => VirtualKeyCode::X,
|
|
0x08 => VirtualKeyCode::C,
|
|
0x09 => VirtualKeyCode::V,
|
|
//0x0a => World 1,
|
|
0x0b => VirtualKeyCode::B,
|
|
0x0c => VirtualKeyCode::Q,
|
|
0x0d => VirtualKeyCode::W,
|
|
0x0e => VirtualKeyCode::E,
|
|
0x0f => VirtualKeyCode::R,
|
|
0x10 => VirtualKeyCode::Y,
|
|
0x11 => VirtualKeyCode::T,
|
|
0x12 => VirtualKeyCode::Key1,
|
|
0x13 => VirtualKeyCode::Key2,
|
|
0x14 => VirtualKeyCode::Key3,
|
|
0x15 => VirtualKeyCode::Key4,
|
|
0x16 => VirtualKeyCode::Key6,
|
|
0x17 => VirtualKeyCode::Key5,
|
|
0x18 => VirtualKeyCode::Equals,
|
|
0x19 => VirtualKeyCode::Key9,
|
|
0x1a => VirtualKeyCode::Key7,
|
|
0x1b => VirtualKeyCode::Minus,
|
|
0x1c => VirtualKeyCode::Key8,
|
|
0x1d => VirtualKeyCode::Key0,
|
|
0x1e => VirtualKeyCode::RBracket,
|
|
0x1f => VirtualKeyCode::O,
|
|
0x20 => VirtualKeyCode::U,
|
|
0x21 => VirtualKeyCode::LBracket,
|
|
0x22 => VirtualKeyCode::I,
|
|
0x23 => VirtualKeyCode::P,
|
|
0x24 => VirtualKeyCode::Return,
|
|
0x25 => VirtualKeyCode::L,
|
|
0x26 => VirtualKeyCode::J,
|
|
0x27 => VirtualKeyCode::Apostrophe,
|
|
0x28 => VirtualKeyCode::K,
|
|
0x29 => VirtualKeyCode::Semicolon,
|
|
0x2a => VirtualKeyCode::Backslash,
|
|
0x2b => VirtualKeyCode::Comma,
|
|
0x2c => VirtualKeyCode::Slash,
|
|
0x2d => VirtualKeyCode::N,
|
|
0x2e => VirtualKeyCode::M,
|
|
0x2f => VirtualKeyCode::Period,
|
|
0x30 => VirtualKeyCode::Tab,
|
|
0x31 => VirtualKeyCode::Space,
|
|
0x32 => VirtualKeyCode::Grave,
|
|
0x33 => VirtualKeyCode::Back,
|
|
//0x34 => unkown,
|
|
0x35 => VirtualKeyCode::Escape,
|
|
0x36 => VirtualKeyCode::RWin,
|
|
0x37 => VirtualKeyCode::LWin,
|
|
0x38 => VirtualKeyCode::LShift,
|
|
//0x39 => Caps lock,
|
|
0x3a => VirtualKeyCode::LAlt,
|
|
0x3b => VirtualKeyCode::LControl,
|
|
0x3c => VirtualKeyCode::RShift,
|
|
0x3d => VirtualKeyCode::RAlt,
|
|
0x3e => VirtualKeyCode::RControl,
|
|
//0x3f => Fn key,
|
|
0x40 => VirtualKeyCode::F17,
|
|
0x41 => VirtualKeyCode::Decimal,
|
|
//0x42 -> unkown,
|
|
0x43 => VirtualKeyCode::Multiply,
|
|
//0x44 => unkown,
|
|
0x45 => VirtualKeyCode::Add,
|
|
//0x46 => unkown,
|
|
0x47 => VirtualKeyCode::Numlock,
|
|
//0x48 => KeypadClear,
|
|
0x49 => VirtualKeyCode::VolumeUp,
|
|
0x4a => VirtualKeyCode::VolumeDown,
|
|
0x4b => VirtualKeyCode::Divide,
|
|
0x4c => VirtualKeyCode::NumpadEnter,
|
|
//0x4d => unkown,
|
|
0x4e => VirtualKeyCode::Subtract,
|
|
0x4f => VirtualKeyCode::F18,
|
|
0x50 => VirtualKeyCode::F19,
|
|
0x51 => VirtualKeyCode::NumpadEquals,
|
|
0x52 => VirtualKeyCode::Numpad0,
|
|
0x53 => VirtualKeyCode::Numpad1,
|
|
0x54 => VirtualKeyCode::Numpad2,
|
|
0x55 => VirtualKeyCode::Numpad3,
|
|
0x56 => VirtualKeyCode::Numpad4,
|
|
0x57 => VirtualKeyCode::Numpad5,
|
|
0x58 => VirtualKeyCode::Numpad6,
|
|
0x59 => VirtualKeyCode::Numpad7,
|
|
0x5a => VirtualKeyCode::F20,
|
|
0x5b => VirtualKeyCode::Numpad8,
|
|
0x5c => VirtualKeyCode::Numpad9,
|
|
0x5d => VirtualKeyCode::Yen,
|
|
//0x5e => JIS Ro,
|
|
//0x5f => unkown,
|
|
0x60 => VirtualKeyCode::F5,
|
|
0x61 => VirtualKeyCode::F6,
|
|
0x62 => VirtualKeyCode::F7,
|
|
0x63 => VirtualKeyCode::F3,
|
|
0x64 => VirtualKeyCode::F8,
|
|
0x65 => VirtualKeyCode::F9,
|
|
//0x66 => JIS Eisuu (macOS),
|
|
0x67 => VirtualKeyCode::F11,
|
|
//0x68 => JIS Kanna (macOS),
|
|
0x69 => VirtualKeyCode::F13,
|
|
0x6a => VirtualKeyCode::F16,
|
|
0x6b => VirtualKeyCode::F14,
|
|
//0x6c => unkown,
|
|
0x6d => VirtualKeyCode::F10,
|
|
//0x6e => unkown,
|
|
0x6f => VirtualKeyCode::F12,
|
|
//0x70 => unkown,
|
|
0x71 => VirtualKeyCode::F15,
|
|
0x72 => VirtualKeyCode::Insert,
|
|
0x73 => VirtualKeyCode::Home,
|
|
0x74 => VirtualKeyCode::PageUp,
|
|
0x75 => VirtualKeyCode::Delete,
|
|
0x76 => VirtualKeyCode::F4,
|
|
0x77 => VirtualKeyCode::End,
|
|
0x78 => VirtualKeyCode::F2,
|
|
0x79 => VirtualKeyCode::PageDown,
|
|
0x7a => VirtualKeyCode::F1,
|
|
0x7b => VirtualKeyCode::Left,
|
|
0x7c => VirtualKeyCode::Right,
|
|
0x7d => VirtualKeyCode::Down,
|
|
0x7e => VirtualKeyCode::Up,
|
|
//0x7f => unkown,
|
|
0xa => VirtualKeyCode::Caret,
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
// While F1-F20 have scancodes we can match on, we have to check against UTF-16
|
|
// constants for the rest.
|
|
// https://developer.apple.com/documentation/appkit/1535851-function-key_unicodes?preferredLanguage=occ
|
|
pub fn check_function_keys(string: &str) -> Option<VirtualKeyCode> {
|
|
if let Some(ch) = string.encode_utf16().next() {
|
|
return Some(match ch {
|
|
0xf718 => VirtualKeyCode::F21,
|
|
0xf719 => VirtualKeyCode::F22,
|
|
0xf71a => VirtualKeyCode::F23,
|
|
0xf71b => VirtualKeyCode::F24,
|
|
_ => return None,
|
|
});
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
pub fn event_mods(event: id) -> ModifiersState {
|
|
let flags = unsafe { NSEvent::modifierFlags(event) };
|
|
let mut m = ModifiersState::empty();
|
|
m.set(
|
|
ModifiersState::SHIFT,
|
|
flags.contains(NSEventModifierFlags::NSShiftKeyMask),
|
|
);
|
|
m.set(
|
|
ModifiersState::CTRL,
|
|
flags.contains(NSEventModifierFlags::NSControlKeyMask),
|
|
);
|
|
m.set(
|
|
ModifiersState::ALT,
|
|
flags.contains(NSEventModifierFlags::NSAlternateKeyMask),
|
|
);
|
|
m.set(
|
|
ModifiersState::LOGO,
|
|
flags.contains(NSEventModifierFlags::NSCommandKeyMask),
|
|
);
|
|
m
|
|
}
|
|
|
|
pub fn get_scancode(event: cocoa::base::id) -> c_ushort {
|
|
// In AppKit, `keyCode` refers to the position (scancode) of a key rather than its character,
|
|
// 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] }
|
|
}
|
|
|
|
pub unsafe fn modifier_event(
|
|
ns_event: id,
|
|
keymask: NSEventModifierFlags,
|
|
was_key_pressed: bool,
|
|
) -> Option<WindowEvent<'static>> {
|
|
if !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 {
|
|
ElementState::Pressed
|
|
};
|
|
|
|
let scancode = get_scancode(ns_event);
|
|
let virtual_keycode = scancode_to_keycode(scancode);
|
|
Some(WindowEvent::KeyboardInput {
|
|
device_id: DEVICE_ID,
|
|
input: KeyboardInput {
|
|
state,
|
|
scancode: scancode as _,
|
|
virtual_keycode,
|
|
modifiers: event_mods(ns_event),
|
|
},
|
|
is_synthetic: false,
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
}
|