123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826 |
- /**************************************************************************/
- /* godot_content_view.mm */
- /**************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* https://godotengine.org */
- /**************************************************************************/
- /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
- /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /**************************************************************************/
- #include "godot_content_view.h"
- #include "display_server_macos.h"
- #include "key_mapping_macos.h"
- #include "main/main.h"
- @implementation GodotContentLayerDelegate
- - (id)init {
- self = [super init];
- window_id = DisplayServer::INVALID_WINDOW_ID;
- need_redraw = false;
- return self;
- }
- - (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
- window_id = wid;
- }
- - (void)setNeedRedraw:(bool)redraw {
- need_redraw = redraw;
- }
- - (void)displayLayer:(CALayer *)layer {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (OS::get_singleton()->get_main_loop() && ds->get_is_resizing() && need_redraw) {
- Main::force_redraw();
- if (!Main::is_iterating()) { // Avoid cyclic loop.
- Main::iteration();
- }
- need_redraw = false;
- }
- }
- @end
- @implementation GodotContentView
- - (void)setFrameSize:(NSSize)newSize {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (ds && ds->has_window(window_id)) {
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- NSRect frameRect = [wd.window_object frame];
- if (wd.fs_transition || wd.initial_size) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementScaleAxesIndependently;
- wd.initial_size = false;
- } else {
- bool left = (wd.last_frame_rect.origin.x != frameRect.origin.x);
- bool bottom = (wd.last_frame_rect.origin.y != frameRect.origin.y);
- bool right = (wd.last_frame_rect.origin.x + wd.last_frame_rect.size.width != frameRect.origin.x + frameRect.size.width);
- bool top = (wd.last_frame_rect.origin.y + wd.last_frame_rect.size.height != frameRect.origin.y + frameRect.size.height);
- if (left && top) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementBottomRight;
- } else if (left && bottom) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementTopRight;
- } else if (left) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementRight;
- } else if (right && top) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementBottomLeft;
- } else if (right && bottom) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
- } else if (right) {
- self.layerContentsPlacement = NSViewLayerContentsPlacementLeft;
- }
- }
- wd.last_frame_rect = frameRect;
- }
- [super setFrameSize:newSize];
- [layer_delegate setNeedRedraw:true];
- [self.layer setNeedsDisplay]; // Force "drawRect" call.
- }
- - (void)updateLayerDelegate {
- self.layer.delegate = layer_delegate;
- self.layer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
- self.layer.needsDisplayOnBoundsChange = YES;
- }
- - (id)init {
- self = [super init];
- layer_delegate = [[GodotContentLayerDelegate alloc] init];
- window_id = DisplayServer::INVALID_WINDOW_ID;
- tracking_area = nil;
- ime_input_event_in_progress = false;
- mouse_down_control = false;
- ignore_momentum_scroll = false;
- last_pen_inverted = false;
- [self updateTrackingAreas];
- self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
- self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
- [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeFileURL]];
- marked_text = [[NSMutableAttributedString alloc] init];
- return self;
- }
- - (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
- window_id = wid;
- [layer_delegate setWindowID:window_id];
- }
- // MARK: Backing Layer
- - (CALayer *)makeBackingLayer {
- return [[CAMetalLayer class] layer];
- }
- - (BOOL)wantsUpdateLayer {
- return YES;
- }
- - (BOOL)isOpaque {
- return YES;
- }
- // MARK: IME
- - (BOOL)hasMarkedText {
- return (marked_text.length > 0);
- }
- - (NSRange)markedRange {
- return NSMakeRange(0, marked_text.length);
- }
- - (NSRange)selectedRange {
- static const NSRange kEmptyRange = { NSNotFound, 0 };
- return kEmptyRange;
- }
- - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {
- if ([aString isKindOfClass:[NSAttributedString class]]) {
- marked_text = [[NSMutableAttributedString alloc] initWithAttributedString:aString];
- } else {
- marked_text = [[NSMutableAttributedString alloc] initWithString:aString];
- }
- if (marked_text.length == 0) {
- [self unmarkText];
- return;
- }
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- if (wd.im_active) {
- ime_input_event_in_progress = true;
- ds->pop_last_key_event();
- ds->update_im_text(Point2i(selectedRange.location, selectedRange.length), String::utf8([[marked_text mutableString] UTF8String]));
- }
- }
- - (void)doCommandBySelector:(SEL)aSelector {
- [self tryToPerform:aSelector with:self];
- }
- - (void)unmarkText {
- if (ime_input_event_in_progress) {
- ime_suppress_next_keyup = true;
- }
- ime_input_event_in_progress = false;
- [[marked_text mutableString] setString:@""];
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- if (wd.im_active) {
- ds->update_im_text(Point2i(), String());
- }
- }
- - (NSArray *)validAttributesForMarkedText {
- return [NSArray array];
- }
- - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
- return nil;
- }
- - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint {
- return 0;
- }
- - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return NSMakeRect(0, 0, 0, 0);
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- const NSRect content_rect = [wd.window_view frame];
- const float scale = ds->screen_get_max_scale();
- NSRect point_in_window_rect = NSMakeRect(wd.im_position.x / scale, content_rect.size.height - (wd.im_position.y / scale) - 1, 0, 0);
- NSPoint point_on_screen = [wd.window_object convertRectToScreen:point_in_window_rect].origin;
- return NSMakeRect(point_on_screen.x, point_on_screen.y, 0, 0);
- }
- - (void)cancelComposition {
- [self unmarkText];
- [[NSTextInputContext currentInputContext] discardMarkedText];
- }
- - (void)insertText:(id)aString {
- [self insertText:aString replacementRange:NSMakeRange(0, 0)];
- }
- - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
- NSString *characters;
- if ([aString isKindOfClass:[NSAttributedString class]]) {
- characters = [aString string];
- } else {
- characters = (NSString *)aString;
- }
- NSCharacterSet *ctrl_chars = [NSCharacterSet controlCharacterSet];
- NSCharacterSet *wsnl_chars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
- if ([characters rangeOfCharacterFromSet:ctrl_chars].length && [characters rangeOfCharacterFromSet:wsnl_chars].length == 0) {
- [[NSTextInputContext currentInputContext] discardMarkedText];
- [self cancelComposition];
- return;
- }
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- [self cancelComposition];
- return;
- }
- Char16String text;
- text.resize([characters length] + 1);
- [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
- String u32text;
- u32text.parse_utf16(text.ptr(), text.length());
- for (int i = 0; i < u32text.length(); i++) {
- const char32_t codepoint = u32text[i];
- if ((codepoint & 0xFF00) == 0xF700) {
- continue;
- }
- DisplayServerMacOS::KeyEvent ke;
- ke.window_id = window_id;
- ke.macos_state = 0;
- ke.pressed = true;
- ke.echo = false;
- ke.raw = false; // IME input event.
- ke.keycode = Key::NONE;
- ke.physical_keycode = Key::NONE;
- ke.key_label = Key::NONE;
- ke.unicode = fix_unicode(codepoint);
- ds->push_to_key_event_buffer(ke);
- }
- [self cancelComposition];
- }
- // MARK: Drag and drop
- - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
- return NSDragOperationCopy;
- }
- - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
- return NSDragOperationCopy;
- }
- - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return NO;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- if (wd.drop_files_callback.is_valid()) {
- Vector<String> files;
- NSPasteboard *pboard = [sender draggingPasteboard];
- NSArray *items = pboard.pasteboardItems;
- for (NSPasteboardItem *item in items) {
- NSString *url = [item stringForType:NSPasteboardTypeFileURL];
- NSString *file = [NSURL URLWithString:url].path;
- files.push_back(String::utf8([file UTF8String]));
- }
- Variant v_files = files;
- const Variant *v_args[1] = { &v_files };
- Variant ret;
- Callable::CallError ce;
- wd.drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- ERR_FAIL_V_MSG(NO, vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(wd.drop_files_callback, v_args, 1, ce)));
- }
- return YES;
- }
- return NO;
- }
- // MARK: Focus
- - (BOOL)canBecomeKeyView {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return YES;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- return !wd.no_focus;
- }
- - (BOOL)acceptsFirstResponder {
- return YES;
- }
- // MARK: Mouse
- - (void)cursorUpdate:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds) {
- return;
- }
- ds->cursor_update_shape();
- }
- - (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed outofstream:(bool)outofstream {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- Ref<InputEventMouseButton> mb;
- mb.instantiate();
- mb->set_window_id(window_id);
- if (outofstream) {
- ds->update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
- } else {
- ds->update_mouse_pos(wd, [event locationInWindow]);
- }
- ds->get_key_modifier_state([event modifierFlags], mb);
- mb->set_button_index(index);
- mb->set_pressed(pressed);
- mb->set_position(wd.mouse_pos);
- mb->set_global_position(wd.mouse_pos);
- mb->set_button_mask(ds->mouse_get_button_state());
- if (!outofstream && index == MouseButton::LEFT && pressed) {
- mb->set_double_click([event clickCount] == 2);
- }
- Input::get_singleton()->parse_input_event(mb);
- }
- - (void)mouseDown:(NSEvent *)event {
- if (([event modifierFlags] & NSEventModifierFlagControl)) {
- mouse_down_control = true;
- [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false];
- } else {
- mouse_down_control = false;
- [self processMouseEvent:event index:MouseButton::LEFT pressed:true outofstream:false];
- }
- }
- - (void)mouseDragged:(NSEvent *)event {
- [self mouseMoved:event];
- }
- - (void)mouseUp:(NSEvent *)event {
- if (mouse_down_control) {
- [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false];
- } else {
- [self processMouseEvent:event index:MouseButton::LEFT pressed:false outofstream:false];
- }
- }
- - (void)mouseMoved:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
- NSPoint mpos = [event locationInWindow];
- if (ds->update_mouse_wrap(wd, delta, mpos, [event timestamp])) {
- return;
- }
- Ref<InputEventMouseMotion> mm;
- mm.instantiate();
- mm->set_window_id(window_id);
- mm->set_button_mask(ds->mouse_get_button_state());
- ds->update_mouse_pos(wd, mpos);
- mm->set_position(wd.mouse_pos);
- mm->set_pressure([event pressure]);
- NSEventSubtype subtype = [event subtype];
- if (subtype == NSEventSubtypeTabletPoint) {
- const NSPoint p = [event tilt];
- mm->set_tilt(Vector2(p.x, -p.y));
- mm->set_pen_inverted(last_pen_inverted);
- } else if (subtype == NSEventSubtypeTabletProximity) {
- // Check if using the eraser end of pen only on proximity event.
- last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser;
- mm->set_pen_inverted(last_pen_inverted);
- }
- mm->set_global_position(wd.mouse_pos);
- mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
- mm->set_screen_velocity(mm->get_velocity());
- const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * ds->screen_get_max_scale();
- mm->set_relative(relativeMotion);
- mm->set_relative_screen_position(relativeMotion);
- ds->get_key_modifier_state([event modifierFlags], mm);
- Input::get_singleton()->parse_input_event(mm);
- }
- - (void)rightMouseDown:(NSEvent *)event {
- [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false];
- }
- - (void)rightMouseDragged:(NSEvent *)event {
- [self mouseMoved:event];
- }
- - (void)rightMouseUp:(NSEvent *)event {
- [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false];
- }
- - (void)otherMouseDown:(NSEvent *)event {
- if ((int)[event buttonNumber] == 2) {
- [self processMouseEvent:event index:MouseButton::MIDDLE pressed:true outofstream:false];
- } else if ((int)[event buttonNumber] == 3) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:false];
- } else if ((int)[event buttonNumber] == 4) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:false];
- } else {
- return;
- }
- }
- - (void)otherMouseDragged:(NSEvent *)event {
- [self mouseMoved:event];
- }
- - (void)otherMouseUp:(NSEvent *)event {
- if ((int)[event buttonNumber] == 2) {
- [self processMouseEvent:event index:MouseButton::MIDDLE pressed:false outofstream:false];
- } else if ((int)[event buttonNumber] == 3) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:false];
- } else if ((int)[event buttonNumber] == 4) {
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:false];
- } else {
- return;
- }
- }
- - (void)swipeWithEvent:(NSEvent *)event {
- // Swipe gesture on Trackpad/Magic Mouse, or physical back/forward mouse buttons.
- if ([event phase] == NSEventPhaseEnded || [event phase] == NSEventPhaseChanged) {
- if (Math::is_equal_approx([event deltaX], 1.0)) {
- // Swipe left (back).
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:true];
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:true];
- } else if (Math::is_equal_approx([event deltaX], -1.0)) {
- // Swipe right (forward).
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:true];
- [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:true];
- }
- }
- }
- - (void)mouseExited:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
- ds->mouse_exit_window(window_id);
- }
- }
- - (void)mouseEntered:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
- ds->mouse_enter_window(window_id);
- }
- ds->cursor_update_shape();
- }
- - (void)magnifyWithEvent:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- Ref<InputEventMagnifyGesture> ev;
- ev.instantiate();
- ev->set_window_id(window_id);
- ds->get_key_modifier_state([event modifierFlags], ev);
- ds->update_mouse_pos(wd, [event locationInWindow]);
- ev->set_position(wd.mouse_pos);
- ev->set_factor([event magnification] + 1.0);
- Input::get_singleton()->parse_input_event(ev);
- }
- - (void)updateTrackingAreas {
- if (tracking_area != nil) {
- [self removeTrackingArea:tracking_area];
- }
- NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingCursorUpdate | NSTrackingInVisibleRect;
- tracking_area = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
- [self addTrackingArea:tracking_area];
- [super updateTrackingAreas];
- }
- // MARK: Keyboard
- - (void)keyDown:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- ignore_momentum_scroll = true;
- // Ignore all input if IME input is in progress.
- if (!ime_input_event_in_progress) {
- NSString *characters = [event characters];
- NSUInteger length = [characters length];
- if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true))) {
- // Fallback unicode character handler used if IME is not active.
- Char16String text;
- text.resize([characters length] + 1);
- [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
- String u32text;
- u32text.parse_utf16(text.ptr(), text.length());
- DisplayServerMacOS::KeyEvent ke;
- ke.window_id = window_id;
- ke.macos_state = [event modifierFlags];
- ke.pressed = true;
- ke.echo = [event isARepeat];
- ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
- ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
- ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
- ke.raw = true;
- if (u32text.is_empty()) {
- ke.unicode = 0;
- ds->push_to_key_event_buffer(ke);
- }
- for (int i = 0; i < u32text.length(); i++) {
- const char32_t codepoint = u32text[i];
- ke.unicode = fix_unicode(codepoint);
- ds->push_to_key_event_buffer(ke);
- }
- } else {
- DisplayServerMacOS::KeyEvent ke;
- ke.window_id = window_id;
- ke.macos_state = [event modifierFlags];
- ke.pressed = true;
- ke.echo = [event isARepeat];
- ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
- ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
- ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
- ke.unicode = 0;
- ke.location = KeyMappingMacOS::translate_location([event keyCode]);
- ke.raw = false;
- ds->push_to_key_event_buffer(ke);
- }
- }
- // Pass events to IME handler
- if (wd.im_active) {
- [self interpretKeyEvents:[NSArray arrayWithObject:event]];
- }
- }
- - (void)flagsChanged:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- ignore_momentum_scroll = true;
- DisplayServerMacOS::KeyEvent ke;
- ke.window_id = window_id;
- ke.echo = false;
- ke.raw = true;
- int key = [event keyCode];
- int mod = [event modifierFlags];
- if (key == 0x36 || key == 0x37) {
- if (mod & NSEventModifierFlagCommand) {
- mod &= ~NSEventModifierFlagCommand;
- ke.pressed = true;
- } else {
- ke.pressed = false;
- }
- } else if (key == 0x38 || key == 0x3c) {
- if (mod & NSEventModifierFlagShift) {
- mod &= ~NSEventModifierFlagShift;
- ke.pressed = true;
- } else {
- ke.pressed = false;
- }
- } else if (key == 0x3a || key == 0x3d) {
- if (mod & NSEventModifierFlagOption) {
- mod &= ~NSEventModifierFlagOption;
- ke.pressed = true;
- } else {
- ke.pressed = false;
- }
- } else if (key == 0x3b || key == 0x3e) {
- if (mod & NSEventModifierFlagControl) {
- mod &= ~NSEventModifierFlagControl;
- ke.pressed = true;
- } else {
- ke.pressed = false;
- }
- } else {
- return;
- }
- ke.macos_state = mod;
- ke.keycode = KeyMappingMacOS::remap_key(key, mod, false);
- ke.physical_keycode = KeyMappingMacOS::translate_key(key);
- ke.key_label = KeyMappingMacOS::remap_key(key, mod, true);
- ke.unicode = 0;
- ke.location = KeyMappingMacOS::translate_location(key);
- ds->push_to_key_event_buffer(ke);
- }
- - (void)keyUp:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- // Ignore all input if IME input is in progress.
- if (ime_suppress_next_keyup) {
- ime_suppress_next_keyup = false;
- return;
- }
- if (!ime_input_event_in_progress) {
- DisplayServerMacOS::KeyEvent ke;
- ke.window_id = window_id;
- ke.macos_state = [event modifierFlags];
- ke.pressed = false;
- ke.echo = [event isARepeat];
- ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
- ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
- ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
- ke.unicode = 0;
- ke.location = KeyMappingMacOS::translate_location([event keyCode]);
- ke.raw = true;
- ds->push_to_key_event_buffer(ke);
- }
- }
- // MARK: Scroll and pan
- - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- MouseButtonMask mask = mouse_button_to_mask(button);
- Ref<InputEventMouseButton> sc;
- sc.instantiate();
- sc->set_window_id(window_id);
- ds->get_key_modifier_state([event modifierFlags], sc);
- sc->set_button_index(button);
- sc->set_factor(factor);
- sc->set_pressed(true);
- sc->set_position(wd.mouse_pos);
- sc->set_global_position(wd.mouse_pos);
- BitField<MouseButtonMask> scroll_mask = ds->mouse_get_button_state();
- scroll_mask.set_flag(mask);
- sc->set_button_mask(scroll_mask);
- Input::get_singleton()->parse_input_event(sc);
- sc.instantiate();
- sc->set_window_id(window_id);
- sc->set_button_index(button);
- sc->set_factor(factor);
- sc->set_pressed(false);
- sc->set_position(wd.mouse_pos);
- sc->set_global_position(wd.mouse_pos);
- scroll_mask.clear_flag(mask);
- sc->set_button_mask(scroll_mask);
- Input::get_singleton()->parse_input_event(sc);
- }
- - (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- Ref<InputEventPanGesture> pg;
- pg.instantiate();
- pg->set_window_id(window_id);
- ds->get_key_modifier_state([event modifierFlags], pg);
- pg->set_position(wd.mouse_pos);
- pg->set_delta(Vector2(-dx, -dy));
- Input::get_singleton()->parse_input_event(pg);
- }
- - (void)scrollWheel:(NSEvent *)event {
- DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
- if (!ds || !ds->has_window(window_id)) {
- return;
- }
- DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- ds->update_mouse_pos(wd, [event locationInWindow]);
- double delta_x = [event scrollingDeltaX];
- double delta_y = [event scrollingDeltaY];
- if ([event hasPreciseScrollingDeltas]) {
- delta_x *= 0.03;
- delta_y *= 0.03;
- }
- if ([event momentumPhase] != NSEventPhaseNone) {
- if (ignore_momentum_scroll) {
- return;
- }
- } else {
- ignore_momentum_scroll = false;
- }
- if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) {
- [self processPanEvent:event dx:delta_x dy:delta_y];
- } else {
- if (fabs(delta_x)) {
- [self processScrollEvent:event button:(0 > delta_x ? MouseButton::WHEEL_RIGHT : MouseButton::WHEEL_LEFT) factor:fabs(delta_x * 0.3)];
- }
- if (fabs(delta_y)) {
- [self processScrollEvent:event button:(0 < delta_y ? MouseButton::WHEEL_UP : MouseButton::WHEEL_DOWN) factor:fabs(delta_y * 0.3)];
- }
- }
- }
- @end
|