godot_content_view.mm 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. /**************************************************************************/
  2. /* godot_content_view.mm */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "godot_content_view.h"
  31. #include "display_server_macos.h"
  32. #include "key_mapping_macos.h"
  33. #include "main/main.h"
  34. @implementation GodotContentLayerDelegate
  35. - (id)init {
  36. self = [super init];
  37. window_id = DisplayServer::INVALID_WINDOW_ID;
  38. need_redraw = false;
  39. return self;
  40. }
  41. - (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
  42. window_id = wid;
  43. }
  44. - (void)setNeedRedraw:(bool)redraw {
  45. need_redraw = redraw;
  46. }
  47. - (void)displayLayer:(CALayer *)layer {
  48. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  49. if (OS::get_singleton()->get_main_loop() && ds->get_is_resizing() && need_redraw) {
  50. Main::force_redraw();
  51. if (!Main::is_iterating()) { // Avoid cyclic loop.
  52. Main::iteration();
  53. }
  54. need_redraw = false;
  55. }
  56. }
  57. @end
  58. @implementation GodotContentView
  59. - (void)setFrameSize:(NSSize)newSize {
  60. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  61. if (ds && ds->has_window(window_id)) {
  62. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  63. NSRect frameRect = [wd.window_object frame];
  64. if (wd.fs_transition || wd.initial_size) {
  65. self.layerContentsPlacement = NSViewLayerContentsPlacementScaleAxesIndependently;
  66. wd.initial_size = false;
  67. } else {
  68. bool left = (wd.last_frame_rect.origin.x != frameRect.origin.x);
  69. bool bottom = (wd.last_frame_rect.origin.y != frameRect.origin.y);
  70. bool right = (wd.last_frame_rect.origin.x + wd.last_frame_rect.size.width != frameRect.origin.x + frameRect.size.width);
  71. bool top = (wd.last_frame_rect.origin.y + wd.last_frame_rect.size.height != frameRect.origin.y + frameRect.size.height);
  72. if (left && top) {
  73. self.layerContentsPlacement = NSViewLayerContentsPlacementBottomRight;
  74. } else if (left && bottom) {
  75. self.layerContentsPlacement = NSViewLayerContentsPlacementTopRight;
  76. } else if (left) {
  77. self.layerContentsPlacement = NSViewLayerContentsPlacementRight;
  78. } else if (right && top) {
  79. self.layerContentsPlacement = NSViewLayerContentsPlacementBottomLeft;
  80. } else if (right && bottom) {
  81. self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
  82. } else if (right) {
  83. self.layerContentsPlacement = NSViewLayerContentsPlacementLeft;
  84. }
  85. }
  86. wd.last_frame_rect = frameRect;
  87. }
  88. [super setFrameSize:newSize];
  89. [layer_delegate setNeedRedraw:true];
  90. [self.layer setNeedsDisplay]; // Force "drawRect" call.
  91. }
  92. - (void)updateLayerDelegate {
  93. self.layer.delegate = layer_delegate;
  94. self.layer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
  95. self.layer.needsDisplayOnBoundsChange = YES;
  96. }
  97. - (id)init {
  98. self = [super init];
  99. layer_delegate = [[GodotContentLayerDelegate alloc] init];
  100. window_id = DisplayServer::INVALID_WINDOW_ID;
  101. tracking_area = nil;
  102. ime_input_event_in_progress = false;
  103. mouse_down_control = false;
  104. ignore_momentum_scroll = false;
  105. last_pen_inverted = false;
  106. [self updateTrackingAreas];
  107. self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
  108. self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
  109. [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeFileURL]];
  110. marked_text = [[NSMutableAttributedString alloc] init];
  111. return self;
  112. }
  113. - (void)setWindowID:(DisplayServerMacOS::WindowID)wid {
  114. window_id = wid;
  115. [layer_delegate setWindowID:window_id];
  116. }
  117. // MARK: Backing Layer
  118. - (CALayer *)makeBackingLayer {
  119. return [[CAMetalLayer class] layer];
  120. }
  121. - (BOOL)wantsUpdateLayer {
  122. return YES;
  123. }
  124. - (BOOL)isOpaque {
  125. return YES;
  126. }
  127. // MARK: IME
  128. - (BOOL)hasMarkedText {
  129. return (marked_text.length > 0);
  130. }
  131. - (NSRange)markedRange {
  132. return NSMakeRange(0, marked_text.length);
  133. }
  134. - (NSRange)selectedRange {
  135. static const NSRange kEmptyRange = { NSNotFound, 0 };
  136. return kEmptyRange;
  137. }
  138. - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {
  139. if ([aString isKindOfClass:[NSAttributedString class]]) {
  140. marked_text = [[NSMutableAttributedString alloc] initWithAttributedString:aString];
  141. } else {
  142. marked_text = [[NSMutableAttributedString alloc] initWithString:aString];
  143. }
  144. if (marked_text.length == 0) {
  145. [self unmarkText];
  146. return;
  147. }
  148. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  149. if (!ds || !ds->has_window(window_id)) {
  150. return;
  151. }
  152. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  153. if (wd.im_active) {
  154. ime_input_event_in_progress = true;
  155. ds->pop_last_key_event();
  156. ds->update_im_text(Point2i(selectedRange.location, selectedRange.length), String::utf8([[marked_text mutableString] UTF8String]));
  157. }
  158. }
  159. - (void)doCommandBySelector:(SEL)aSelector {
  160. [self tryToPerform:aSelector with:self];
  161. }
  162. - (void)unmarkText {
  163. if (ime_input_event_in_progress) {
  164. ime_suppress_next_keyup = true;
  165. }
  166. ime_input_event_in_progress = false;
  167. [[marked_text mutableString] setString:@""];
  168. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  169. if (!ds || !ds->has_window(window_id)) {
  170. return;
  171. }
  172. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  173. if (wd.im_active) {
  174. ds->update_im_text(Point2i(), String());
  175. }
  176. }
  177. - (NSArray *)validAttributesForMarkedText {
  178. return [NSArray array];
  179. }
  180. - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
  181. return nil;
  182. }
  183. - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint {
  184. return 0;
  185. }
  186. - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange {
  187. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  188. if (!ds || !ds->has_window(window_id)) {
  189. return NSMakeRect(0, 0, 0, 0);
  190. }
  191. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  192. const NSRect content_rect = [wd.window_view frame];
  193. const float scale = ds->screen_get_max_scale();
  194. NSRect point_in_window_rect = NSMakeRect(wd.im_position.x / scale, content_rect.size.height - (wd.im_position.y / scale) - 1, 0, 0);
  195. NSPoint point_on_screen = [wd.window_object convertRectToScreen:point_in_window_rect].origin;
  196. return NSMakeRect(point_on_screen.x, point_on_screen.y, 0, 0);
  197. }
  198. - (void)cancelComposition {
  199. [self unmarkText];
  200. [[NSTextInputContext currentInputContext] discardMarkedText];
  201. }
  202. - (void)insertText:(id)aString {
  203. [self insertText:aString replacementRange:NSMakeRange(0, 0)];
  204. }
  205. - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
  206. NSString *characters;
  207. if ([aString isKindOfClass:[NSAttributedString class]]) {
  208. characters = [aString string];
  209. } else {
  210. characters = (NSString *)aString;
  211. }
  212. NSCharacterSet *ctrl_chars = [NSCharacterSet controlCharacterSet];
  213. NSCharacterSet *wsnl_chars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
  214. if ([characters rangeOfCharacterFromSet:ctrl_chars].length && [characters rangeOfCharacterFromSet:wsnl_chars].length == 0) {
  215. [[NSTextInputContext currentInputContext] discardMarkedText];
  216. [self cancelComposition];
  217. return;
  218. }
  219. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  220. if (!ds || !ds->has_window(window_id)) {
  221. [self cancelComposition];
  222. return;
  223. }
  224. Char16String text;
  225. text.resize([characters length] + 1);
  226. [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
  227. String u32text;
  228. u32text.parse_utf16(text.ptr(), text.length());
  229. for (int i = 0; i < u32text.length(); i++) {
  230. const char32_t codepoint = u32text[i];
  231. if ((codepoint & 0xFF00) == 0xF700) {
  232. continue;
  233. }
  234. DisplayServerMacOS::KeyEvent ke;
  235. ke.window_id = window_id;
  236. ke.macos_state = 0;
  237. ke.pressed = true;
  238. ke.echo = false;
  239. ke.raw = false; // IME input event.
  240. ke.keycode = Key::NONE;
  241. ke.physical_keycode = Key::NONE;
  242. ke.key_label = Key::NONE;
  243. ke.unicode = fix_unicode(codepoint);
  244. ds->push_to_key_event_buffer(ke);
  245. }
  246. [self cancelComposition];
  247. }
  248. // MARK: Drag and drop
  249. - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
  250. return NSDragOperationCopy;
  251. }
  252. - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
  253. return NSDragOperationCopy;
  254. }
  255. - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
  256. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  257. if (!ds || !ds->has_window(window_id)) {
  258. return NO;
  259. }
  260. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  261. if (wd.drop_files_callback.is_valid()) {
  262. Vector<String> files;
  263. NSPasteboard *pboard = [sender draggingPasteboard];
  264. NSArray *items = pboard.pasteboardItems;
  265. for (NSPasteboardItem *item in items) {
  266. NSString *url = [item stringForType:NSPasteboardTypeFileURL];
  267. NSString *file = [NSURL URLWithString:url].path;
  268. files.push_back(String::utf8([file UTF8String]));
  269. }
  270. Variant v_files = files;
  271. const Variant *v_args[1] = { &v_files };
  272. Variant ret;
  273. Callable::CallError ce;
  274. wd.drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
  275. if (ce.error != Callable::CallError::CALL_OK) {
  276. 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)));
  277. }
  278. return YES;
  279. }
  280. return NO;
  281. }
  282. // MARK: Focus
  283. - (BOOL)canBecomeKeyView {
  284. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  285. if (!ds || !ds->has_window(window_id)) {
  286. return YES;
  287. }
  288. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  289. return !wd.no_focus;
  290. }
  291. - (BOOL)acceptsFirstResponder {
  292. return YES;
  293. }
  294. // MARK: Mouse
  295. - (void)cursorUpdate:(NSEvent *)event {
  296. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  297. if (!ds) {
  298. return;
  299. }
  300. ds->cursor_update_shape();
  301. }
  302. - (void)processMouseEvent:(NSEvent *)event index:(MouseButton)index pressed:(bool)pressed outofstream:(bool)outofstream {
  303. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  304. if (!ds || !ds->has_window(window_id)) {
  305. return;
  306. }
  307. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  308. Ref<InputEventMouseButton> mb;
  309. mb.instantiate();
  310. mb->set_window_id(window_id);
  311. if (outofstream) {
  312. ds->update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
  313. } else {
  314. ds->update_mouse_pos(wd, [event locationInWindow]);
  315. }
  316. ds->get_key_modifier_state([event modifierFlags], mb);
  317. mb->set_button_index(index);
  318. mb->set_pressed(pressed);
  319. mb->set_position(wd.mouse_pos);
  320. mb->set_global_position(wd.mouse_pos);
  321. mb->set_button_mask(ds->mouse_get_button_state());
  322. if (!outofstream && index == MouseButton::LEFT && pressed) {
  323. mb->set_double_click([event clickCount] == 2);
  324. }
  325. Input::get_singleton()->parse_input_event(mb);
  326. }
  327. - (void)mouseDown:(NSEvent *)event {
  328. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  329. if (ds && ds->has_window(window_id)) {
  330. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  331. wd.edge = DisplayServer::WINDOW_EDGE_MAX;
  332. }
  333. if (([event modifierFlags] & NSEventModifierFlagControl)) {
  334. mouse_down_control = true;
  335. [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false];
  336. } else {
  337. mouse_down_control = false;
  338. [self processMouseEvent:event index:MouseButton::LEFT pressed:true outofstream:false];
  339. }
  340. }
  341. - (void)mouseDragged:(NSEvent *)event {
  342. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  343. if (ds && ds->has_window(window_id)) {
  344. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  345. if (wd.edge != DisplayServer::WINDOW_EDGE_MAX) {
  346. Size2i max_size = wd.max_size / ds->screen_get_max_scale();
  347. Size2i min_size = wd.min_size / ds->screen_get_max_scale();
  348. NSRect frame = [wd.window_object frame];
  349. switch (wd.edge) {
  350. case DisplayServer::WINDOW_EDGE_TOP_LEFT: {
  351. int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width;
  352. int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height;
  353. [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES];
  354. } break;
  355. case DisplayServer::WINDOW_EDGE_TOP: {
  356. int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height;
  357. [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height + clamped_dy) display:YES];
  358. } break;
  359. case DisplayServer::WINDOW_EDGE_TOP_RIGHT: {
  360. int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width;
  361. int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height;
  362. [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES];
  363. } break;
  364. case DisplayServer::WINDOW_EDGE_LEFT: {
  365. int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width;
  366. [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y, frame.size.width + clamped_dx, frame.size.height) display:YES];
  367. } break;
  368. case DisplayServer::WINDOW_EDGE_RIGHT: {
  369. int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width;
  370. [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + clamped_dx, frame.size.height) display:YES];
  371. } break;
  372. case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: {
  373. int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width;
  374. int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height;
  375. [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y - clamped_dy, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES];
  376. } break;
  377. case DisplayServer::WINDOW_EDGE_BOTTOM: {
  378. int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height;
  379. [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y - clamped_dy, frame.size.width, frame.size.height + clamped_dy) display:YES];
  380. } break;
  381. case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: {
  382. int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width;
  383. int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height;
  384. [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y - clamped_dy, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES];
  385. } break;
  386. default:
  387. break;
  388. }
  389. return;
  390. }
  391. }
  392. [self mouseMoved:event];
  393. }
  394. - (void)mouseUp:(NSEvent *)event {
  395. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  396. if (ds && ds->has_window(window_id)) {
  397. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  398. wd.edge = DisplayServer::WINDOW_EDGE_MAX;
  399. }
  400. if (mouse_down_control) {
  401. [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false];
  402. } else {
  403. [self processMouseEvent:event index:MouseButton::LEFT pressed:false outofstream:false];
  404. }
  405. }
  406. - (void)mouseMoved:(NSEvent *)event {
  407. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  408. if (!ds || !ds->has_window(window_id)) {
  409. return;
  410. }
  411. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  412. NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
  413. NSPoint mpos = [event locationInWindow];
  414. if (ds->update_mouse_wrap(wd, delta, mpos, [event timestamp])) {
  415. return;
  416. }
  417. Ref<InputEventMouseMotion> mm;
  418. mm.instantiate();
  419. mm->set_window_id(window_id);
  420. mm->set_button_mask(ds->mouse_get_button_state());
  421. ds->update_mouse_pos(wd, mpos);
  422. mm->set_position(wd.mouse_pos);
  423. mm->set_pressure([event pressure]);
  424. NSEventSubtype subtype = [event subtype];
  425. if (subtype == NSEventSubtypeTabletPoint) {
  426. const NSPoint p = [event tilt];
  427. mm->set_tilt(Vector2(p.x, -p.y));
  428. mm->set_pen_inverted(last_pen_inverted);
  429. } else if (subtype == NSEventSubtypeTabletProximity) {
  430. // Check if using the eraser end of pen only on proximity event.
  431. last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser;
  432. mm->set_pen_inverted(last_pen_inverted);
  433. }
  434. mm->set_global_position(wd.mouse_pos);
  435. mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
  436. mm->set_screen_velocity(mm->get_velocity());
  437. const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * ds->screen_get_max_scale();
  438. mm->set_relative(relativeMotion);
  439. mm->set_relative_screen_position(relativeMotion);
  440. ds->get_key_modifier_state([event modifierFlags], mm);
  441. Input::get_singleton()->parse_input_event(mm);
  442. }
  443. - (void)rightMouseDown:(NSEvent *)event {
  444. [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false];
  445. }
  446. - (void)rightMouseDragged:(NSEvent *)event {
  447. [self mouseMoved:event];
  448. }
  449. - (void)rightMouseUp:(NSEvent *)event {
  450. [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false];
  451. }
  452. - (void)otherMouseDown:(NSEvent *)event {
  453. if ((int)[event buttonNumber] == 2) {
  454. [self processMouseEvent:event index:MouseButton::MIDDLE pressed:true outofstream:false];
  455. } else if ((int)[event buttonNumber] == 3) {
  456. [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:false];
  457. } else if ((int)[event buttonNumber] == 4) {
  458. [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:false];
  459. } else {
  460. return;
  461. }
  462. }
  463. - (void)otherMouseDragged:(NSEvent *)event {
  464. [self mouseMoved:event];
  465. }
  466. - (void)otherMouseUp:(NSEvent *)event {
  467. if ((int)[event buttonNumber] == 2) {
  468. [self processMouseEvent:event index:MouseButton::MIDDLE pressed:false outofstream:false];
  469. } else if ((int)[event buttonNumber] == 3) {
  470. [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:false];
  471. } else if ((int)[event buttonNumber] == 4) {
  472. [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:false];
  473. } else {
  474. return;
  475. }
  476. }
  477. - (void)swipeWithEvent:(NSEvent *)event {
  478. // Swipe gesture on Trackpad/Magic Mouse, or physical back/forward mouse buttons.
  479. if ([event phase] == NSEventPhaseEnded || [event phase] == NSEventPhaseChanged) {
  480. if (Math::is_equal_approx([event deltaX], 1.0)) {
  481. // Swipe left (back).
  482. [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:true outofstream:true];
  483. [self processMouseEvent:event index:MouseButton::MB_XBUTTON1 pressed:false outofstream:true];
  484. } else if (Math::is_equal_approx([event deltaX], -1.0)) {
  485. // Swipe right (forward).
  486. [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:true outofstream:true];
  487. [self processMouseEvent:event index:MouseButton::MB_XBUTTON2 pressed:false outofstream:true];
  488. }
  489. }
  490. }
  491. - (void)mouseExited:(NSEvent *)event {
  492. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  493. if (!ds || !ds->has_window(window_id)) {
  494. return;
  495. }
  496. if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
  497. ds->mouse_exit_window(window_id);
  498. }
  499. }
  500. - (void)mouseEntered:(NSEvent *)event {
  501. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  502. if (!ds || !ds->has_window(window_id)) {
  503. return;
  504. }
  505. if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_CAPTURED) {
  506. ds->mouse_enter_window(window_id);
  507. }
  508. ds->cursor_update_shape();
  509. }
  510. - (void)magnifyWithEvent:(NSEvent *)event {
  511. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  512. if (!ds || !ds->has_window(window_id)) {
  513. return;
  514. }
  515. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  516. Ref<InputEventMagnifyGesture> ev;
  517. ev.instantiate();
  518. ev->set_window_id(window_id);
  519. ds->get_key_modifier_state([event modifierFlags], ev);
  520. ds->update_mouse_pos(wd, [event locationInWindow]);
  521. ev->set_position(wd.mouse_pos);
  522. ev->set_factor([event magnification] + 1.0);
  523. Input::get_singleton()->parse_input_event(ev);
  524. }
  525. - (void)updateTrackingAreas {
  526. if (tracking_area != nil) {
  527. [self removeTrackingArea:tracking_area];
  528. }
  529. NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingCursorUpdate | NSTrackingInVisibleRect;
  530. tracking_area = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
  531. [self addTrackingArea:tracking_area];
  532. [super updateTrackingAreas];
  533. }
  534. // MARK: Keyboard
  535. - (void)keyDown:(NSEvent *)event {
  536. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  537. if (!ds || !ds->has_window(window_id)) {
  538. return;
  539. }
  540. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  541. ignore_momentum_scroll = true;
  542. // Ignore all input if IME input is in progress.
  543. if (!ime_input_event_in_progress) {
  544. NSString *characters = [event characters];
  545. NSUInteger length = [characters length];
  546. if (!wd.im_active && length > 0 && keycode_has_unicode(KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true))) {
  547. // Fallback unicode character handler used if IME is not active.
  548. Char16String text;
  549. text.resize([characters length] + 1);
  550. [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
  551. String u32text;
  552. u32text.parse_utf16(text.ptr(), text.length());
  553. DisplayServerMacOS::KeyEvent ke;
  554. ke.window_id = window_id;
  555. ke.macos_state = [event modifierFlags];
  556. ke.pressed = true;
  557. ke.echo = [event isARepeat];
  558. ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
  559. ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
  560. ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
  561. ke.raw = true;
  562. if (u32text.is_empty()) {
  563. ke.unicode = 0;
  564. ds->push_to_key_event_buffer(ke);
  565. }
  566. for (int i = 0; i < u32text.length(); i++) {
  567. const char32_t codepoint = u32text[i];
  568. ke.unicode = fix_unicode(codepoint);
  569. ds->push_to_key_event_buffer(ke);
  570. }
  571. } else {
  572. DisplayServerMacOS::KeyEvent ke;
  573. ke.window_id = window_id;
  574. ke.macos_state = [event modifierFlags];
  575. ke.pressed = true;
  576. ke.echo = [event isARepeat];
  577. ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
  578. ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
  579. ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
  580. ke.unicode = 0;
  581. ke.location = KeyMappingMacOS::translate_location([event keyCode]);
  582. ke.raw = false;
  583. ds->push_to_key_event_buffer(ke);
  584. }
  585. }
  586. // Pass events to IME handler
  587. if (wd.im_active) {
  588. [self interpretKeyEvents:[NSArray arrayWithObject:event]];
  589. }
  590. }
  591. - (void)flagsChanged:(NSEvent *)event {
  592. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  593. if (!ds || !ds->has_window(window_id)) {
  594. return;
  595. }
  596. ignore_momentum_scroll = true;
  597. DisplayServerMacOS::KeyEvent ke;
  598. ke.window_id = window_id;
  599. ke.echo = false;
  600. ke.raw = true;
  601. int key = [event keyCode];
  602. int mod = [event modifierFlags];
  603. if (key == 0x36 || key == 0x37) {
  604. if (mod & NSEventModifierFlagCommand) {
  605. mod &= ~NSEventModifierFlagCommand;
  606. ke.pressed = true;
  607. } else {
  608. ke.pressed = false;
  609. }
  610. } else if (key == 0x38 || key == 0x3c) {
  611. if (mod & NSEventModifierFlagShift) {
  612. mod &= ~NSEventModifierFlagShift;
  613. ke.pressed = true;
  614. } else {
  615. ke.pressed = false;
  616. }
  617. } else if (key == 0x3a || key == 0x3d) {
  618. if (mod & NSEventModifierFlagOption) {
  619. mod &= ~NSEventModifierFlagOption;
  620. ke.pressed = true;
  621. } else {
  622. ke.pressed = false;
  623. }
  624. } else if (key == 0x3b || key == 0x3e) {
  625. if (mod & NSEventModifierFlagControl) {
  626. mod &= ~NSEventModifierFlagControl;
  627. ke.pressed = true;
  628. } else {
  629. ke.pressed = false;
  630. }
  631. } else {
  632. return;
  633. }
  634. ke.macos_state = mod;
  635. ke.keycode = KeyMappingMacOS::remap_key(key, mod, false);
  636. ke.physical_keycode = KeyMappingMacOS::translate_key(key);
  637. ke.key_label = KeyMappingMacOS::remap_key(key, mod, true);
  638. ke.unicode = 0;
  639. ke.location = KeyMappingMacOS::translate_location(key);
  640. ds->push_to_key_event_buffer(ke);
  641. }
  642. - (void)keyUp:(NSEvent *)event {
  643. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  644. if (!ds || !ds->has_window(window_id)) {
  645. return;
  646. }
  647. // Ignore all input if IME input is in progress.
  648. if (ime_suppress_next_keyup) {
  649. ime_suppress_next_keyup = false;
  650. return;
  651. }
  652. if (!ime_input_event_in_progress) {
  653. DisplayServerMacOS::KeyEvent ke;
  654. ke.window_id = window_id;
  655. ke.macos_state = [event modifierFlags];
  656. ke.pressed = false;
  657. ke.echo = [event isARepeat];
  658. ke.keycode = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], false);
  659. ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]);
  660. ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true);
  661. ke.unicode = 0;
  662. ke.location = KeyMappingMacOS::translate_location([event keyCode]);
  663. ke.raw = true;
  664. ds->push_to_key_event_buffer(ke);
  665. }
  666. }
  667. // MARK: Scroll and pan
  668. - (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor {
  669. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  670. if (!ds || !ds->has_window(window_id)) {
  671. return;
  672. }
  673. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  674. MouseButtonMask mask = mouse_button_to_mask(button);
  675. Ref<InputEventMouseButton> sc;
  676. sc.instantiate();
  677. sc->set_window_id(window_id);
  678. ds->get_key_modifier_state([event modifierFlags], sc);
  679. sc->set_button_index(button);
  680. sc->set_factor(factor);
  681. sc->set_pressed(true);
  682. sc->set_position(wd.mouse_pos);
  683. sc->set_global_position(wd.mouse_pos);
  684. BitField<MouseButtonMask> scroll_mask = ds->mouse_get_button_state();
  685. scroll_mask.set_flag(mask);
  686. sc->set_button_mask(scroll_mask);
  687. Input::get_singleton()->parse_input_event(sc);
  688. sc.instantiate();
  689. sc->set_window_id(window_id);
  690. sc->set_button_index(button);
  691. sc->set_factor(factor);
  692. sc->set_pressed(false);
  693. sc->set_position(wd.mouse_pos);
  694. sc->set_global_position(wd.mouse_pos);
  695. scroll_mask.clear_flag(mask);
  696. sc->set_button_mask(scroll_mask);
  697. Input::get_singleton()->parse_input_event(sc);
  698. }
  699. - (void)processPanEvent:(NSEvent *)event dx:(double)dx dy:(double)dy {
  700. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  701. if (!ds || !ds->has_window(window_id)) {
  702. return;
  703. }
  704. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  705. Ref<InputEventPanGesture> pg;
  706. pg.instantiate();
  707. pg->set_window_id(window_id);
  708. ds->get_key_modifier_state([event modifierFlags], pg);
  709. pg->set_position(wd.mouse_pos);
  710. pg->set_delta(Vector2(-dx, -dy));
  711. Input::get_singleton()->parse_input_event(pg);
  712. }
  713. - (void)scrollWheel:(NSEvent *)event {
  714. DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
  715. if (!ds || !ds->has_window(window_id)) {
  716. return;
  717. }
  718. DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
  719. ds->update_mouse_pos(wd, [event locationInWindow]);
  720. double delta_x = [event scrollingDeltaX];
  721. double delta_y = [event scrollingDeltaY];
  722. if ([event hasPreciseScrollingDeltas]) {
  723. delta_x *= 0.03;
  724. delta_y *= 0.03;
  725. }
  726. if ([event momentumPhase] != NSEventPhaseNone) {
  727. if (ignore_momentum_scroll) {
  728. return;
  729. }
  730. } else {
  731. ignore_momentum_scroll = false;
  732. }
  733. if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) {
  734. [self processPanEvent:event dx:delta_x dy:delta_y];
  735. } else {
  736. if (fabs(delta_x)) {
  737. [self processScrollEvent:event button:(0 > delta_x ? MouseButton::WHEEL_RIGHT : MouseButton::WHEEL_LEFT) factor:fabs(delta_x * 0.3)];
  738. }
  739. if (fabs(delta_y)) {
  740. [self processScrollEvent:event button:(0 < delta_y ? MouseButton::WHEEL_UP : MouseButton::WHEEL_DOWN) factor:fabs(delta_y * 0.3)];
  741. }
  742. }
  743. }
  744. @end