millennium-core 1.0.0-beta.3

Cross-platform window management library for Millennium
Documentation
// Copyright 2022 pyke.io
//           2019-2021 Tauri Programme within The Commons Conservancy
//                     [https://tauri.studio/]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{
	boxed::Box,
	collections::{HashSet, VecDeque},
	os::raw::*,
	ptr, slice, str,
	sync::{Arc, Mutex, Weak}
};

use cocoa::{
	appkit::{NSApp, NSEvent, NSEventModifierFlags, NSEventPhase, NSView, NSWindow},
	base::{id, nil},
	foundation::{NSInteger, NSPoint, NSRect, NSSize, NSString, NSUInteger}
};
use objc::{
	declare::ClassDecl,
	runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES}
};

use crate::{
	dpi::{LogicalPosition, LogicalSize},
	event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent},
	keyboard::{KeyCode, ModifiersState},
	platform_impl::platform::{
		app_state::AppState,
		event::{code_to_key, create_key_event, event_mods, get_scancode, EventWrapper},
		ffi::*,
		util::{self, IdRef},
		window::get_window_id,
		DEVICE_ID
	},
	window::WindowId
};

pub struct CursorState {
	pub visible: bool,
	pub cursor: util::Cursor
}

impl Default for CursorState {
	fn default() -> Self {
		Self {
			visible: true,
			cursor: Default::default()
		}
	}
}

pub(super) struct ViewState {
	ns_window: id,
	pub cursor_state: Arc<Mutex<CursorState>>,
	ime_spot: Option<(f64, f64)>,

	/// This is true when we are currently modifying a marked text
	/// using ime. When the text gets commited, this is set to false.
	in_ime_preedit: bool,

	/// This is used to detect if a key-press causes an ime event.
	/// If a key-press does not cause an ime event, that means
	/// that the key-press cancelled the ime session. (Except arrow keys)
	key_triggered_ime: bool,
	// Not Needed Anymore
	// raw_characters: Option<String>,
	is_key_down: bool,
	pub(super) modifiers: ModifiersState,
	phys_modifiers: HashSet<KeyCode>,
	tracking_rect: Option<NSInteger>
}

impl ViewState {
	fn get_scale_factor(&self) -> f64 {
		(unsafe { NSWindow::backingScaleFactor(self.ns_window) }) as f64
	}
}

pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<CursorState>>) {
	let cursor_state = Default::default();
	let cursor_access = Arc::downgrade(&cursor_state);
	let state = ViewState {
		ns_window,
		cursor_state,
		ime_spot: None,
		in_ime_preedit: false,
		key_triggered_ime: false,
		is_key_down: false,
		modifiers: Default::default(),
		phys_modifiers: Default::default(),
		tracking_rect: None
	};
	unsafe {
		// 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, initWithMillennium: 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("millenniumState");
	let state = &mut *(state_ptr as *mut ViewState);
	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));
	let _: () = msg_send![input_context, invalidateCharacterCoordinates];
}

fn is_arrow_key(keycode: KeyCode) -> bool {
	matches!(keycode, KeyCode::ArrowUp | KeyCode::ArrowDown | KeyCode::ArrowLeft | KeyCode::ArrowRight)
}

/// `view` must be the reference to the `MillenniumView` class
///
/// Returns the mutable reference to the `markedText` field.
unsafe fn clear_marked_text(view: &mut Object) -> &mut id {
	let marked_text_ref: &mut id = view.get_mut_ivar("markedText");
	let () = msg_send![(*marked_text_ref), release];
	*marked_text_ref = NSMutableAttributedString::alloc(nil);
	marked_text_ref
}

struct ViewClass(*const Class);
unsafe impl Send for ViewClass {}
unsafe impl Sync for ViewClass {}

lazy_static! {
	static ref VIEW_CLASS: ViewClass = unsafe {
		let superclass = class!(NSView);
		let mut decl = ClassDecl::new("MillenniumView", superclass).unwrap();
		decl.add_method(sel!(dealloc), dealloc as extern "C" fn(&Object, Sel));
		decl.add_method(sel!(initWithMillennium:), init_with_millennium as extern "C" fn(&Object, Sel, *mut c_void) -> id);
		decl.add_method(sel!(viewDidMoveToWindow), view_did_move_to_window as extern "C" fn(&Object, Sel));
		decl.add_method(sel!(drawRect:), draw_rect as extern "C" fn(&Object, Sel, NSRect));
		decl.add_method(sel!(acceptsFirstResponder), accepts_first_responder as extern "C" fn(&Object, Sel) -> BOOL);
		decl.add_method(sel!(touchBar), touch_bar as extern "C" fn(&Object, Sel) -> BOOL);
		decl.add_method(sel!(resetCursorRects), reset_cursor_rects as extern "C" fn(&Object, Sel));
		decl.add_method(sel!(hasMarkedText), has_marked_text as extern "C" fn(&Object, Sel) -> BOOL);
		decl.add_method(sel!(markedRange), marked_range as extern "C" fn(&Object, Sel) -> NSRange);
		decl.add_method(sel!(selectedRange), selected_range as extern "C" fn(&Object, Sel) -> NSRange);
		decl.add_method(sel!(setMarkedText:selectedRange:replacementRange:), set_marked_text as extern "C" fn(&mut Object, Sel, id, NSRange, NSRange));
		decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&mut Object, Sel));
		decl.add_method(sel!(validAttributesForMarkedText), 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 "C" fn(&Object, Sel, NSRange, *mut c_void) -> id
		);
		decl.add_method(sel!(insertText:replacementRange:), insert_text as extern "C" fn(&Object, Sel, id, NSRange));
		decl.add_method(sel!(characterIndexForPoint:), 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 "C" fn(&Object, Sel, NSRange, *mut c_void) -> NSRect
		);
		decl.add_method(sel!(doCommandBySelector:), do_command_by_selector as extern "C" fn(&Object, Sel, Sel));
		decl.add_method(sel!(keyDown:), key_down as extern "C" fn(&mut 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 "C" fn(&Object, Sel, id));
		decl.add_method(sel!(insertTab:), insert_tab as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(insertBackTab:), insert_back_tab as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(mouseDown:), 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 "C" fn(&Object, Sel, id));
		decl.add_method(sel!(rightMouseUp:), right_mouse_up as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(otherMouseDown:), other_mouse_down as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(otherMouseUp:), other_mouse_up as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(mouseMoved:), mouse_moved as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(mouseDragged:), mouse_dragged as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(rightMouseDragged:), right_mouse_dragged as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(otherMouseDragged:), other_mouse_dragged as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(mouseEntered:), mouse_entered as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(mouseExited:), mouse_exited as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(scrollWheel:), scroll_wheel as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(pressureChangeWithEvent:), pressure_change_with_event as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(_wantsKeyDownForEvent:), wants_key_down_for_event as extern "C" fn(&Object, Sel, id) -> BOOL);
		decl.add_method(sel!(cancelOperation:), cancel_operation as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(frameDidChange:), frame_did_change as extern "C" fn(&Object, Sel, id));
		decl.add_method(sel!(acceptsFirstMouse:), accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL);
		decl.add_ivar::<*mut c_void>("millenniumState");
		decl.add_ivar::<id>("markedText");
		let protocol = Protocol::get("NSTextInputClient").unwrap();
		decl.add_protocol(protocol);
		ViewClass(decl.register())
	};
}

extern "C" fn dealloc(this: &Object, _sel: Sel) {
	unsafe {
		let state: *mut c_void = *this.get_ivar("millenniumState");
		let marked_text: id = *this.get_ivar("markedText");
		let _: () = msg_send![marked_text, release];
		Box::from_raw(state as *mut ViewState);
	}
}

extern "C" fn init_with_millennium(this: &Object, _sel: Sel, state: *mut c_void) -> id {
	unsafe {
		let this: id = msg_send![this, init];
		if this != nil {
			(*this).set_ivar("millenniumState", state);
			let marked_text = <id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil));
			(*this).set_ivar("markedText", marked_text);
			let _: () = msg_send![this, setPostsFrameChangedNotifications: YES];

			let notification_center: &Object = msg_send![class!(NSNotificationCenter), defaultCenter];
			let notification_name = NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification");
			let _: () = msg_send![
				notification_center,
				addObserver: this
				selector: sel!(frameDidChange:)
				name: notification_name
				object: this
			];
		}
		this
	}
}

extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
	trace!("Triggered `viewDidMoveToWindow`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		if let Some(tracking_rect) = state.tracking_rect.take() {
			let _: () = msg_send![this, removeTrackingRect: tracking_rect];
		}

		let rect: NSRect = msg_send![this, visibleRect];
		let tracking_rect: NSInteger = msg_send![this,
			addTrackingRect:rect
			owner:this
			userData:ptr::null_mut::<c_void>()
			assumeInside:NO
		];
		state.tracking_rect = Some(tracking_rect);
	}
	trace!("Completed `viewDidMoveToWindow`");
}

extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		if let Some(tracking_rect) = state.tracking_rect.take() {
			let _: () = msg_send![this, removeTrackingRect: tracking_rect];
		}

		let rect: NSRect = msg_send![this, visibleRect];
		let tracking_rect: NSInteger = msg_send![this,
			addTrackingRect:rect
			owner:this
			userData:ptr::null_mut::<c_void>()
			assumeInside:NO
		];

		// Emit resize event here rather than from windowDidResize because:
		// 1. When a new window is created as a tab, the frame size may change without a window resize occurring.
		// 2. Even when a window resize does occur on a new tabbed window, it contains the wrong size (includes tab height).
		let logical_size = LogicalSize::new(rect.size.width as f64, rect.size.height as f64);
		let size = logical_size.to_physical::<u32>(state.get_scale_factor());
		AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::Resized(size)
		}));

		state.tracking_rect = Some(tracking_rect);
	}
}

extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) {
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		AppState::handle_redraw(WindowId(get_window_id(state.ns_window)));

		let superclass = util::superclass(this);
		let () = msg_send![super(this, superclass), drawRect: rect];
	}
}

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 "C" fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
	NO
}

extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let bounds: NSRect = msg_send![this, bounds];
		let cursor_state = state.cursor_state.lock().unwrap();
		let cursor = if cursor_state.visible { cursor_state.cursor.load() } else { util::invisible_cursor() };
		let _: () = msg_send![this,
			addCursorRect:bounds
			cursor:cursor
		];
	}
}

extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
	unsafe {
		trace!("Triggered `hasMarkedText`");
		let marked_text: id = *this.get_ivar("markedText");
		trace!("Completed `hasMarkedText`");
		(marked_text.length() > 0) as BOOL
	}
}

extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
	unsafe {
		trace!("Triggered `markedRange`");
		let marked_text: id = *this.get_ivar("markedText");
		let length = marked_text.length();
		trace!("Completed `markedRange`");
		if length > 0 { NSRange::new(0, length - 1) } else { util::EMPTY_RANGE }
	}
}

extern "C" fn selected_range(_this: &Object, _sel: Sel) -> NSRange {
	trace!("Triggered `selectedRange`");
	trace!("Completed `selectedRange`");
	util::EMPTY_RANGE
}

/// An IME pre-edit operation happened, changing the text that's
/// currently being pre-edited. This more or less corresponds to
/// the `compositionupdate` event on the web.
extern "C" fn set_marked_text(this: &mut Object, _sel: Sel, string: id, _selected_range: NSRange, _replacement_range: NSRange) {
	trace!("Triggered `setMarkedText`");
	unsafe {
		let marked_text_ref = clear_marked_text(this);
		let has_attr: BOOL = msg_send![string, isKindOfClass: class!(NSAttributedString)];
		if has_attr != NO {
			marked_text_ref.initWithAttributedString(string);
		} else {
			marked_text_ref.initWithString(string);
		};

		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);
		state.in_ime_preedit = true;
		state.key_triggered_ime = true;
	}
	trace!("Completed `setMarkedText`");
}

extern "C" fn unmark_text(this: &mut Object, _sel: Sel) {
	trace!("Triggered `unmarkText`");
	unsafe {
		clear_marked_text(this);
		let input_context: id = msg_send![this, inputContext];
		let _: () = msg_send![input_context, discardMarkedText];
	}
	trace!("Completed `unmarkText`");
}

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 "C" fn attributed_substring_for_proposed_range(
	_this: &Object,
	_sel: Sel,
	_range: NSRange,
	_actual_range: *mut c_void // *mut NSRange
) -> id {
	trace!("Triggered `attributedSubstringForProposedRange`");
	trace!("Completed `attributedSubstringForProposedRange`");
	nil
}

extern "C" fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
	trace!("Triggered `characterIndexForPoint`");
	trace!("Completed `characterIndexForPoint`");
	0
}

extern "C" fn first_rect_for_character_range(
	this: &Object,
	_sel: Sel,
	_range: NSRange,
	_actual_range: *mut c_void // *mut NSRange
) -> NSRect {
	unsafe {
		trace!("Triggered `firstRectForCharacterRange`");
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);
		let (x, y) = state.ime_spot.unwrap_or_else(|| {
			let content_rect = NSWindow::contentRectForFrameRect_(state.ns_window, NSWindow::frame(state.ns_window));
			let x = content_rect.origin.x;
			let y = util::bottom_left_to_top_left(content_rect);
			(x, y)
		});
		trace!("Completed `firstRectForCharacterRange`");
		NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(0.0, 0.0))
	}
}

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("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let has_attr: BOOL = msg_send![string, isKindOfClass: class!(NSAttributedString)];
		let characters = if has_attr != NO {
			// This is a *mut NSAttributedString
			msg_send![string, string]
		} else {
			// This is already a *mut NSString
			string
		};

		let slice = slice::from_raw_parts(characters.UTF8String() as *const c_uchar, characters.len());
		let string: String = str::from_utf8_unchecked(slice).chars().filter(|c| !is_corporate_character(*c)).collect();
		state.is_key_down = true;

		// We don't need this now, but it's here if that changes.
		// let event: id = msg_send![NSApp(), currentEvent];

		AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::ReceivedImeText(string)
		}));
		if state.in_ime_preedit {
			state.in_ime_preedit = false;
			state.key_triggered_ime = true;
		}
	}
	trace!("Completed `insertText`");
}

extern "C" fn do_command_by_selector(_this: &Object, _sel: Sel, _command: Sel) {
	trace!("Triggered `doCommandBySelector`");
	// TODO: (Artur) all these inputs seem to trigger a key event with the correct
	// text content so this is not needed anymore, it seems.

	// 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.

	trace!("Completed `doCommandBySelector`");
}

// As defined in: https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
fn is_corporate_character(c: char) -> bool {
	#[allow(clippy::match_like_matches_macro)]
	match c {
		'\u{F700}'..='\u{F747}'
		| '\u{F802}'..='\u{F84F}'
		| '\u{F850}'
		| '\u{F85C}'
		| '\u{F85D}'
		| '\u{F85F}'
		| '\u{F860}'..='\u{F86B}'
		| '\u{F870}'..='\u{F8FF}' => true,
		_ => false
	}
}

// Update `state.modifiers` if `event` has something different
fn update_potentially_stale_modifiers(state: &mut ViewState, event: id) {
	let event_modifiers = event_mods(event);
	if state.modifiers != event_modifiers {
		state.modifiers = event_modifiers;

		AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::ModifiersChanged(state.modifiers)
		}));
	}
}

extern "C" fn key_down(this: &mut Object, _sel: Sel, event: id) {
	trace!("Triggered `keyDown`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);
		let window_id = WindowId(get_window_id(state.ns_window));

		// keyboard refactor: don't seems to be needed anymore
		// let characters = get_characters(event, false);
		// state.raw_characters = Some(characters);

		let is_repeat: BOOL = msg_send![event, isARepeat];
		let is_repeat = is_repeat == YES;

		update_potentially_stale_modifiers(state, event);

		let pass_along = !is_repeat || !state.is_key_down;
		if pass_along {
			// See below for why we do this.
			clear_marked_text(this);
			state.key_triggered_ime = false;

			// 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];
		}
		// The `interpretKeyEvents` above, may invoke `set_marked_text` or
		// `insert_text`, if the event corresponds to an IME event.
		let in_ime = state.key_triggered_ime;
		let key_event = create_key_event(event, true, is_repeat, in_ime, None);
		let is_arrow_key = is_arrow_key(key_event.physical_key);
		if pass_along {
			// The `interpretKeyEvents` above, may invoke `set_marked_text` or
			// `insert_text`, if the event corresponds to an IME event.
			// If `set_marked_text` or `insert_text` were not invoked, then the IME was
			// deactivated, and we should cancel the IME session.
			// When using arrow keys in an IME window, the input context won't invoke the
			// IME related methods, so in that case we shouldn't cancel the IME session.
			let is_preediting: bool = state.in_ime_preedit;
			if is_preediting && !state.key_triggered_ime && !is_arrow_key {
				// In this case we should cancel the IME session.
				let () = msg_send![this, unmarkText];
				state.in_ime_preedit = false;
			}
		}
		let window_event = Event::WindowEvent {
			window_id,
			event: WindowEvent::KeyboardInput {
				device_id: DEVICE_ID,
				event: key_event,
				is_synthetic: false
			}
		};
		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `keyDown`");
}

extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
	trace!("Triggered `keyUp`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		state.is_key_down = false;

		update_potentially_stale_modifiers(state, event);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::KeyboardInput {
				device_id: DEVICE_ID,
				event: create_key_event(event, false, false, false, None),
				is_synthetic: false
			}
		};
		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `keyUp`");
}

extern "C" fn flags_changed(this: &Object, _sel: Sel, ns_event: id) {
	use KeyCode::{AltLeft, AltRight, ControlLeft, ControlRight, ShiftLeft, ShiftRight, SuperLeft, SuperRight};

	trace!("Triggered `flagsChanged`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let scancode = get_scancode(ns_event);

		// We'll correct the `is_press` and the `key_override` below.
		let event = create_key_event(ns_event, false, false, false, Some(KeyCode::SuperLeft));
		let mut events = VecDeque::with_capacity(4);

		macro_rules! process_event {
			($millennium_flag:expr, $ns_flag:expr, $target_key:expr) => {
				let ns_event_contains_keymask = NSEvent::modifierFlags(ns_event).contains($ns_flag);
				let mut actual_key = KeyCode::from_scancode(scancode as u32);
				let was_pressed = state.phys_modifiers.contains(&actual_key);
				let mut is_pressed = ns_event_contains_keymask;
				let matching_keys;
				if actual_key == KeyCode::KeyA {
					// When switching keyboard layout using Ctrl+Space, the Ctrl release event
					// has `KeyA` as its keycode which would produce an incorrect key event.
					// To avoid this, we detect this scenario and override the key with one
					// that should be reasonable
					actual_key = $target_key;
					matching_keys = true;
				} else {
					matching_keys = actual_key == $target_key;
					if matching_keys && is_pressed && was_pressed {
						// If we received a modifier flags changed event AND the key that triggered
						// it was already pressed then this must mean that this event indicates the
						// release of that key.
						is_pressed = false;
					}
				}
				if matching_keys {
					if is_pressed != was_pressed {
						let mut event = event.clone();
						event.state = if is_pressed { ElementState::Pressed } else { ElementState::Released };
						event.physical_key = actual_key;
						event.logical_key = code_to_key(event.physical_key, scancode);
						events.push_back(WindowEvent::KeyboardInput {
							device_id: DEVICE_ID,
							event,
							is_synthetic: false
						});
						if is_pressed {
							state.phys_modifiers.insert($target_key);
						} else {
							state.phys_modifiers.remove(&$target_key);
						}
						if ns_event_contains_keymask {
							state.modifiers.insert($millennium_flag);
						} else {
							state.modifiers.remove($millennium_flag);
						}
					}
				}
			};
		}
		process_event!(ModifiersState::SHIFT, NSEventModifierFlags::NSShiftKeyMask, ShiftLeft);
		process_event!(ModifiersState::SHIFT, NSEventModifierFlags::NSShiftKeyMask, ShiftRight);
		process_event!(ModifiersState::CONTROL, NSEventModifierFlags::NSControlKeyMask, ControlLeft);
		process_event!(ModifiersState::CONTROL, NSEventModifierFlags::NSControlKeyMask, ControlRight);
		process_event!(ModifiersState::ALT, NSEventModifierFlags::NSAlternateKeyMask, AltLeft);
		process_event!(ModifiersState::ALT, NSEventModifierFlags::NSAlternateKeyMask, AltRight);
		process_event!(ModifiersState::SUPER, NSEventModifierFlags::NSCommandKeyMask, SuperLeft);
		process_event!(ModifiersState::SUPER, NSEventModifierFlags::NSCommandKeyMask, SuperRight);

		let window_id = WindowId(get_window_id(state.ns_window));

		for event in events {
			AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { window_id, event }));
		}

		AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
			window_id,
			event: WindowEvent::ModifiersChanged(state.modifiers)
		}));
	}
	trace!("Completed `flagsChanged`");
}

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];
		}
	}
}

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];
		}
	}
}

// Allows us to receive Cmd-. (the shortcut for closing a dialog)
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
	trace!("Triggered `cancelOperation`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let event: id = msg_send![NSApp(), currentEvent];
		update_potentially_stale_modifiers(state, event);

		let scancode = 0x2f;
		let key = KeyCode::from_scancode(scancode);
		debug_assert_eq!(key, KeyCode::Period);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::KeyboardInput {
				device_id: DEVICE_ID,
				event: create_key_event(event, true, false, false, Some(key)),
				is_synthetic: false
			}
		};
		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `cancelOperation`");
}

fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: ElementState) {
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		update_potentially_stale_modifiers(state, event);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::MouseInput {
				device_id: DEVICE_ID,
				state: button_state,
				button,
				modifiers: event_mods(event)
			}
		};

		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
}

extern "C" fn mouse_down(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
}

extern "C" fn mouse_up(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Left, ElementState::Released);
}

extern "C" fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
}

extern "C" fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Right, ElementState::Released);
}

extern "C" fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
}

extern "C" fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
	mouse_click(this, event, MouseButton::Middle, ElementState::Released);
}

fn mouse_motion(this: &Object, event: id) {
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		// We have to do this to have access to the `NSView` trait...
		let view: id = this as *const _ as *mut _;

		let window_point = event.locationInWindow();
		let view_point = view.convertPoint_fromView_(window_point, nil);
		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 {
			let mouse_buttons_down: NSUInteger = msg_send![class!(NSEvent), pressedMouseButtons];
			if mouse_buttons_down == 0 {
				// Point is outside of the client area (view) and no buttons are pressed
				return;
			}
		}

		let x = view_point.x as f64;
		let y = view_rect.size.height as f64 - view_point.y as f64;
		let logical_position = LogicalPosition::new(x, y);

		update_potentially_stale_modifiers(state, event);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::CursorMoved {
				device_id: DEVICE_ID,
				position: logical_position.to_physical(state.get_scale_factor()),
				modifiers: event_mods(event)
			}
		};

		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
}

extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
}

extern "C" fn mouse_dragged(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
}

extern "C" fn right_mouse_dragged(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
}

extern "C" fn other_mouse_dragged(this: &Object, _sel: Sel, event: id) {
	mouse_motion(this, event);
}

extern "C" fn mouse_entered(this: &Object, _sel: Sel, _event: id) {
	trace!("Triggered `mouseEntered`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let enter_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::CursorEntered { device_id: DEVICE_ID }
		};

		AppState::queue_event(EventWrapper::StaticEvent(enter_event));
	}
	trace!("Completed `mouseEntered`");
}

extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
	trace!("Triggered `mouseExited`");
	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::CursorLeft { device_id: DEVICE_ID }
		};

		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `mouseExited`");
}

extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
	trace!("Triggered `scrollWheel`");

	mouse_motion(this, event);

	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let delta = {
			// macOS horizontal sign convention is the inverse of millennium.
			let (x, y) = (event.scrollingDeltaX() * -1.0, event.scrollingDeltaY());
			if event.hasPreciseScrollingDeltas() == YES {
				let delta = LogicalPosition::new(x, y).to_physical(state.get_scale_factor());
				MouseScrollDelta::PixelDelta(delta)
			} else {
				MouseScrollDelta::LineDelta(x as f32, y as f32)
			}
		};
		let phase = match event.phase() {
			NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => TouchPhase::Started,
			NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
			_ => TouchPhase::Moved
		};

		let device_event = Event::DeviceEvent {
			device_id: DEVICE_ID,
			event: DeviceEvent::MouseWheel { delta }
		};

		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		update_potentially_stale_modifiers(state, event);

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::MouseWheel {
				device_id: DEVICE_ID,
				delta,
				phase,
				modifiers: event_mods(event)
			}
		};

		AppState::queue_event(EventWrapper::StaticEvent(device_event));
		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `scrollWheel`");
}

extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
	trace!("Triggered `pressureChangeWithEvent`");

	mouse_motion(this, event);

	unsafe {
		let state_ptr: *mut c_void = *this.get_ivar("millenniumState");
		let state = &mut *(state_ptr as *mut ViewState);

		let pressure = event.pressure();
		let stage = event.stage();

		let window_event = Event::WindowEvent {
			window_id: WindowId(get_window_id(state.ns_window)),
			event: WindowEvent::TouchpadPressure {
				device_id: DEVICE_ID,
				pressure,
				stage
			}
		};

		AppState::queue_event(EventWrapper::StaticEvent(window_event));
	}
	trace!("Completed `pressureChangeWithEvent`");
}

// 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 "C" fn wants_key_down_for_event(_this: &Object, _sel: Sel, _event: id) -> BOOL {
	YES
}

extern "C" fn accepts_first_mouse(_this: &Object, _sel: Sel, _event: id) -> BOOL {
	YES
}