Wise&mystical  1.0
Project about Europe
Loading...
Searching...
No Matches
cocoa_window.m
Go to the documentation of this file.
1//========================================================================
2// GLFW 3.4 macOS - www.glfw.org
3//------------------------------------------------------------------------
4// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
5//
6// This software is provided 'as-is', without any express or implied
7// warranty. In no event will the authors be held liable for any damages
8// arising from the use of this software.
9//
10// Permission is granted to anyone to use this software for any purpose,
11// including commercial applications, and to alter it and redistribute it
12// freely, subject to the following restrictions:
13//
14// 1. The origin of this software must not be misrepresented; you must not
15// claim that you wrote the original software. If you use this software
16// in a product, an acknowledgment in the product documentation would
17// be appreciated but is not required.
18//
19// 2. Altered source versions must be plainly marked as such, and must not
20// be misrepresented as being the original software.
21//
22// 3. This notice may not be removed or altered from any source
23// distribution.
24//
25//========================================================================
26// It is fine to use C99 in this file because it will not be built with VS
27//========================================================================
28
29#include "internal.h"
30
31#include <float.h>
32#include <string.h>
33
34// Returns the style mask corresponding to the window settings
35//
36static NSUInteger getStyleMask(_GLFWwindow* window)
37{
38 NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
39
40 if (window->monitor || !window->decorated)
41 styleMask |= NSWindowStyleMaskBorderless;
42 else
43 {
44 styleMask |= NSWindowStyleMaskTitled |
46
47 if (window->resizable)
48 styleMask |= NSWindowStyleMaskResizable;
49 }
50
51 return styleMask;
52}
53
54// Returns whether the cursor is in the content area of the specified window
55//
56static GLFWbool cursorInContentArea(_GLFWwindow* window)
57{
58 const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
59 return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
60}
61
62// Hides the cursor if not already hidden
63//
64static void hideCursor(_GLFWwindow* window)
65{
66 if (!_glfw.ns.cursorHidden)
67 {
68 [NSCursor hide];
69 _glfw.ns.cursorHidden = GLFW_TRUE;
70 }
71}
72
73// Shows the cursor if not already shown
74//
75static void showCursor(_GLFWwindow* window)
76{
77 if (_glfw.ns.cursorHidden)
78 {
79 [NSCursor unhide];
80 _glfw.ns.cursorHidden = GLFW_FALSE;
81 }
82}
83
84// Updates the cursor image according to its cursor mode
85//
86static void updateCursorImage(_GLFWwindow* window)
87{
88 if (window->cursorMode == GLFW_CURSOR_NORMAL)
89 {
90 showCursor(window);
91
92 if (window->cursor)
93 [(NSCursor*) window->cursor->ns.object set];
94 else
95 [[NSCursor arrowCursor] set];
96 }
97 else
98 hideCursor(window);
99}
100
101// Apply chosen cursor mode to a focused window
102//
103static void updateCursorMode(_GLFWwindow* window)
104{
105 if (window->cursorMode == GLFW_CURSOR_DISABLED)
106 {
107 _glfw.ns.disabledCursorWindow = window;
109 &_glfw.ns.restoreCursorPosX,
110 &_glfw.ns.restoreCursorPosY);
112 CGAssociateMouseAndMouseCursorPosition(false);
113 }
114 else if (_glfw.ns.disabledCursorWindow == window)
115 {
116 _glfw.ns.disabledCursorWindow = NULL;
117 CGAssociateMouseAndMouseCursorPosition(true);
119 _glfw.ns.restoreCursorPosX,
120 _glfw.ns.restoreCursorPosY);
121 }
122
123 if (cursorInContentArea(window))
124 updateCursorImage(window);
125}
126
127// Make the specified window and its video mode active on its monitor
128//
129static void acquireMonitor(_GLFWwindow* window)
130{
131 _glfwSetVideoModeNS(window->monitor, &window->videoMode);
132 const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
133 const NSRect frame = NSMakeRect(bounds.origin.x,
134 _glfwTransformYNS(bounds.origin.y + bounds.size.height - 1),
135 bounds.size.width,
136 bounds.size.height);
137
138 [window->ns.object setFrame:frame display:YES];
139
140 _glfwInputMonitorWindow(window->monitor, window);
141}
142
143// Remove the window and restore the original video mode
144//
145static void releaseMonitor(_GLFWwindow* window)
146{
147 if (window->monitor->window != window)
148 return;
149
152}
153
154// Translates macOS key modifiers into GLFW ones
155//
156static int translateFlags(NSUInteger flags)
157{
158 int mods = 0;
159
160 if (flags & NSEventModifierFlagShift)
161 mods |= GLFW_MOD_SHIFT;
162 if (flags & NSEventModifierFlagControl)
163 mods |= GLFW_MOD_CONTROL;
164 if (flags & NSEventModifierFlagOption)
165 mods |= GLFW_MOD_ALT;
166 if (flags & NSEventModifierFlagCommand)
167 mods |= GLFW_MOD_SUPER;
168 if (flags & NSEventModifierFlagCapsLock)
169 mods |= GLFW_MOD_CAPS_LOCK;
170
171 return mods;
172}
173
174// Translates a macOS keycode to a GLFW keycode
175//
176static int translateKey(unsigned int key)
177{
178 if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
179 return GLFW_KEY_UNKNOWN;
180
181 return _glfw.ns.keycodes[key];
182}
183
184// Translate a GLFW keycode to a Cocoa modifier flag
185//
186static NSUInteger translateKeyToModifierFlag(int key)
187{
188 switch (key)
189 {
204 }
205
206 return 0;
207}
208
209// Defines a constant for empty ranges in NSTextInputClient
210//
211static const NSRange kEmptyRange = { NSNotFound, 0 };
212
213
214//------------------------------------------------------------------------
215// Delegate for window related notifications
216//------------------------------------------------------------------------
217
218@interface GLFWWindowDelegate : NSObject
219{
221}
222
223- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
224
225@end
226
227@implementation GLFWWindowDelegate
228
229- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
230{
231 self = [super init];
232 if (self != nil)
233 window = initWindow;
234
235 return self;
236}
237
238- (BOOL)windowShouldClose:(id)sender
239{
241 return NO;
242}
243
244- (void)windowDidResize:(NSNotification *)notification
245{
247 [window->context.nsgl.object update];
248
249 if (_glfw.ns.disabledCursorWindow == window)
251
252 const int maximized = [window->ns.object isZoomed];
253 if (window->ns.maximized != maximized)
254 {
255 window->ns.maximized = maximized;
257 }
258
259 const NSRect contentRect = [window->ns.view frame];
260 const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
261
262 if (fbRect.size.width != window->ns.fbWidth ||
263 fbRect.size.height != window->ns.fbHeight)
264 {
265 window->ns.fbWidth = fbRect.size.width;
266 window->ns.fbHeight = fbRect.size.height;
267 _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
268 }
269
270 if (contentRect.size.width != window->ns.width ||
271 contentRect.size.height != window->ns.height)
272 {
273 window->ns.width = contentRect.size.width;
274 window->ns.height = contentRect.size.height;
275 _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
276 }
277}
278
279- (void)windowDidMove:(NSNotification *)notification
280{
282 [window->context.nsgl.object update];
283
284 if (_glfw.ns.disabledCursorWindow == window)
286
287 int x, y;
290}
291
292- (void)windowDidMiniaturize:(NSNotification *)notification
293{
294 if (window->monitor)
295 releaseMonitor(window);
296
298}
299
300- (void)windowDidDeminiaturize:(NSNotification *)notification
301{
302 if (window->monitor)
303 acquireMonitor(window);
304
306}
307
308- (void)windowDidBecomeKey:(NSNotification *)notification
309{
310 if (_glfw.ns.disabledCursorWindow == window)
312
314 updateCursorMode(window);
315}
316
317- (void)windowDidResignKey:(NSNotification *)notification
318{
321
323}
324
325- (void)windowDidChangeOcclusionState:(NSNotification* )notification
326{
327 if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
328 window->ns.occluded = GLFW_FALSE;
329 else
330 window->ns.occluded = GLFW_TRUE;
331}
332
333@end
334
335
336//------------------------------------------------------------------------
337// Content view class for the GLFW window
338//------------------------------------------------------------------------
339
340@interface GLFWContentView : NSView <NSTextInputClient>
341{
343 NSTrackingArea* trackingArea;
344 NSMutableAttributedString* markedText;
346
347- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
348
349@end
350
351@implementation GLFWContentView
352
353- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
354{
355 self = [super init];
356 if (self != nil)
357 {
358 window = initWindow;
359 trackingArea = nil;
360 markedText = [[NSMutableAttributedString alloc] init];
361
362 [self updateTrackingAreas];
363 // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
364 // on 10.7 without having been deprecated yet
365 [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
366 }
367
368 return self;
369}
370
371- (void)dealloc
372{
373 [trackingArea release];
374 [markedText release];
375 [super dealloc];
376}
377
378- (BOOL)isOpaque
379{
380 return [window->ns.object isOpaque];
381}
382
383- (BOOL)canBecomeKeyView
384{
385 return YES;
386}
387
388- (BOOL)acceptsFirstResponder
389{
390 return YES;
391}
392
393- (BOOL)wantsUpdateLayer
394{
395 return YES;
396}
397
398- (void)updateLayer
399{
401 [window->context.nsgl.object update];
402
404}
405
406- (void)cursorUpdate:(NSEvent *)event
407{
408 updateCursorImage(window);
409}
410
411- (BOOL)acceptsFirstMouse:(NSEvent *)event
412{
413 return YES;
414}
415
416- (void)mouseDown:(NSEvent *)event
417{
421 translateFlags([event modifierFlags]));
422}
423
424- (void)mouseDragged:(NSEvent *)event
425{
426 [self mouseMoved:event];
427}
428
429- (void)mouseUp:(NSEvent *)event
430{
434 translateFlags([event modifierFlags]));
435}
436
437- (void)mouseMoved:(NSEvent *)event
438{
440 {
441 const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;
442 const double dy = [event deltaY] - window->ns.cursorWarpDeltaY;
443
447 }
448 else
449 {
450 const NSRect contentRect = [window->ns.view frame];
451 // NOTE: The returned location uses base 0,1 not 0,0
452 const NSPoint pos = [event locationInWindow];
453
454 _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
455 }
456
457 window->ns.cursorWarpDeltaX = 0;
458 window->ns.cursorWarpDeltaY = 0;
459}
460
461- (void)rightMouseDown:(NSEvent *)event
462{
466 translateFlags([event modifierFlags]));
467}
468
469- (void)rightMouseDragged:(NSEvent *)event
470{
471 [self mouseMoved:event];
472}
473
474- (void)rightMouseUp:(NSEvent *)event
475{
479 translateFlags([event modifierFlags]));
480}
481
482- (void)otherMouseDown:(NSEvent *)event
483{
485 (int) [event buttonNumber],
487 translateFlags([event modifierFlags]));
488}
489
490- (void)otherMouseDragged:(NSEvent *)event
491{
492 [self mouseMoved:event];
493}
494
495- (void)otherMouseUp:(NSEvent *)event
496{
498 (int) [event buttonNumber],
500 translateFlags([event modifierFlags]));
501}
502
503- (void)mouseExited:(NSEvent *)event
504{
506 showCursor(window);
507
509}
510
511- (void)mouseEntered:(NSEvent *)event
512{
514 hideCursor(window);
515
517}
518
519- (void)viewDidChangeBackingProperties
520{
521 const NSRect contentRect = [window->ns.view frame];
522 const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
523
524 if (fbRect.size.width != window->ns.fbWidth ||
525 fbRect.size.height != window->ns.fbHeight)
526 {
527 window->ns.fbWidth = fbRect.size.width;
528 window->ns.fbHeight = fbRect.size.height;
529 _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
530 }
531
532 const float xscale = fbRect.size.width / contentRect.size.width;
533 const float yscale = fbRect.size.height / contentRect.size.height;
534
535 if (xscale != window->ns.xscale || yscale != window->ns.yscale)
536 {
537 window->ns.xscale = xscale;
538 window->ns.yscale = yscale;
539 _glfwInputWindowContentScale(window, xscale, yscale);
540
541 if (window->ns.retina && window->ns.layer)
542 [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
543 }
544}
545
546- (void)drawRect:(NSRect)rect
547{
549}
550
551- (void)updateTrackingAreas
552{
553 if (trackingArea != nil)
554 {
555 [self removeTrackingArea:trackingArea];
556 [trackingArea release];
557 }
558
559 const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
560 NSTrackingActiveInKeyWindow |
561 NSTrackingEnabledDuringMouseDrag |
562 NSTrackingCursorUpdate |
563 NSTrackingInVisibleRect |
564 NSTrackingAssumeInside;
565
566 trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
567 options:options
568 owner:self
569 userInfo:nil];
570
571 [self addTrackingArea:trackingArea];
572 [super updateTrackingAreas];
573}
574
575- (void)keyDown:(NSEvent *)event
576{
577 const int key = translateKey([event keyCode]);
578 const int mods = translateFlags([event modifierFlags]);
579
580 _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
581
582 [self interpretKeyEvents:@[event]];
583}
584
585- (void)flagsChanged:(NSEvent *)event
586{
587 int action;
588 const unsigned int modifierFlags =
589 [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
590 const int key = translateKey([event keyCode]);
591 const int mods = translateFlags(modifierFlags);
592 const NSUInteger keyFlag = translateKeyToModifierFlag(key);
593
594 if (keyFlag & modifierFlags)
595 {
596 if (window->keys[key] == GLFW_PRESS)
597 action = GLFW_RELEASE;
598 else
599 action = GLFW_PRESS;
600 }
601 else
602 action = GLFW_RELEASE;
603
604 _glfwInputKey(window, key, [event keyCode], action, mods);
605}
606
607- (void)keyUp:(NSEvent *)event
608{
609 const int key = translateKey([event keyCode]);
610 const int mods = translateFlags([event modifierFlags]);
611 _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
612}
613
614- (void)scrollWheel:(NSEvent *)event
615{
616 double deltaX = [event scrollingDeltaX];
617 double deltaY = [event scrollingDeltaY];
618
619 if ([event hasPreciseScrollingDeltas])
620 {
621 deltaX *= 0.1;
622 deltaY *= 0.1;
623 }
624
625 if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0)
626 _glfwInputScroll(window, deltaX, deltaY);
627}
628
629- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
630{
631 // HACK: We don't know what to say here because we don't know what the
632 // application wants to do with the paths
633 return NSDragOperationGeneric;
634}
635
636- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
637{
638 const NSRect contentRect = [window->ns.view frame];
639 // NOTE: The returned location uses base 0,1 not 0,0
640 const NSPoint pos = [sender draggingLocation];
641 _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
642
643 NSPasteboard* pasteboard = [sender draggingPasteboard];
644 NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
645 NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
646 options:options];
647 const NSUInteger count = [urls count];
648 if (count)
649 {
650 char** paths = calloc(count, sizeof(char*));
651
652 for (NSUInteger i = 0; i < count; i++)
653 paths[i] = _glfw_strdup([urls[i] fileSystemRepresentation]);
654
655 _glfwInputDrop(window, (int) count, (const char**) paths);
656
657 for (NSUInteger i = 0; i < count; i++)
658 free(paths[i]);
659 free(paths);
660 }
661
662 return YES;
663}
664
665- (BOOL)hasMarkedText
666{
667 return [markedText length] > 0;
668}
669
670- (NSRange)markedRange
671{
672 if ([markedText length] > 0)
673 return NSMakeRange(0, [markedText length] - 1);
674 else
675 return kEmptyRange;
676}
677
678- (NSRange)selectedRange
679{
680 return kEmptyRange;
681}
682
683- (void)setMarkedText:(id)string
684 selectedRange:(NSRange)selectedRange
685 replacementRange:(NSRange)replacementRange
686{
687 [markedText release];
688 if ([string isKindOfClass:[NSAttributedString class]])
689 markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
690 else
691 markedText = [[NSMutableAttributedString alloc] initWithString:string];
692}
693
694- (void)unmarkText
695{
696 [[markedText mutableString] setString:@""];
697}
698
699- (NSArray*)validAttributesForMarkedText
700{
701 return [NSArray array];
702}
703
704- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
705 actualRange:(NSRangePointer)actualRange
706{
707 return nil;
708}
709
710- (NSUInteger)characterIndexForPoint:(NSPoint)point
711{
712 return 0;
713}
714
715- (NSRect)firstRectForCharacterRange:(NSRange)range
716 actualRange:(NSRangePointer)actualRange
717{
718 const NSRect frame = [window->ns.view frame];
719 return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0);
720}
721
722- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
723{
724 NSString* characters;
725 NSEvent* event = [NSApp currentEvent];
726 const int mods = translateFlags([event modifierFlags]);
727 const int plain = !(mods & GLFW_MOD_SUPER);
728
729 if ([string isKindOfClass:[NSAttributedString class]])
730 characters = [string string];
731 else
732 characters = (NSString*) string;
733
734 NSRange range = NSMakeRange(0, [characters length]);
735 while (range.length)
736 {
737 uint32_t codepoint = 0;
738
739 if ([characters getBytes:&codepoint
740 maxLength:sizeof(codepoint)
741 usedLength:NULL
742 encoding:NSUTF32StringEncoding
743 options:0
744 range:range
745 remainingRange:&range])
746 {
747 if (codepoint >= 0xf700 && codepoint <= 0xf7ff)
748 continue;
749
750 _glfwInputChar(window, codepoint, mods, plain);
751 }
752 }
753}
754
755- (void)doCommandBySelector:(SEL)selector
756{
757}
758
759@end
760
761
762//------------------------------------------------------------------------
763// GLFW window class
764//------------------------------------------------------------------------
765
766@interface GLFWWindow : NSWindow {}
767@end
768
769@implementation GLFWWindow
770
771- (BOOL)canBecomeKeyWindow
772{
773 // Required for NSWindowStyleMaskBorderless windows
774 return YES;
775}
776
777- (BOOL)canBecomeMainWindow
778{
779 return YES;
780}
781
782@end
783
784
785// Create the Cocoa window
786//
787static GLFWbool createNativeWindow(_GLFWwindow* window,
788 const _GLFWwndconfig* wndconfig,
789 const _GLFWfbconfig* fbconfig)
790{
791 window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
792 if (window->ns.delegate == nil)
793 {
795 "Cocoa: Failed to create window delegate");
796 return GLFW_FALSE;
797 }
798
799 NSRect contentRect;
800
801 if (window->monitor)
802 {
803 GLFWvidmode mode;
804 int xpos, ypos;
805
806 _glfwPlatformGetVideoMode(window->monitor, &mode);
807 _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
808
809 contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
810 }
811 else
812 contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
813
814 window->ns.object = [[GLFWWindow alloc]
815 initWithContentRect:contentRect
816 styleMask:getStyleMask(window)
817 backing:NSBackingStoreBuffered
818 defer:NO];
819
820 if (window->ns.object == nil)
821 {
822 _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window");
823 return GLFW_FALSE;
824 }
825
826 if (window->monitor)
827 [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
828 else
829 {
830 [(NSWindow*) window->ns.object center];
831 _glfw.ns.cascadePoint =
832 NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
833 NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
834
835 if (wndconfig->resizable)
836 {
837 const NSWindowCollectionBehavior behavior =
838 NSWindowCollectionBehaviorFullScreenPrimary |
839 NSWindowCollectionBehaviorManaged;
840 [window->ns.object setCollectionBehavior:behavior];
841 }
842
843 if (wndconfig->floating)
844 [window->ns.object setLevel:NSFloatingWindowLevel];
845
846 if (wndconfig->maximized)
847 [window->ns.object zoom:nil];
848 }
849
850 if (strlen(wndconfig->ns.frameName))
851 [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)];
852
853 window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
854 window->ns.retina = wndconfig->ns.retina;
855
856 if (fbconfig->transparent)
857 {
858 [window->ns.object setOpaque:NO];
859 [window->ns.object setHasShadow:NO];
860 [window->ns.object setBackgroundColor:[NSColor clearColor]];
861 }
862
863 [window->ns.object setContentView:window->ns.view];
864 [window->ns.object makeFirstResponder:window->ns.view];
865 [window->ns.object setTitle:@(wndconfig->title)];
866 [window->ns.object setDelegate:window->ns.delegate];
867 [window->ns.object setAcceptsMouseMovedEvents:YES];
868 [window->ns.object setRestorable:NO];
869
870#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
871 if ([window->ns.object respondsToSelector:@selector(setTabbingMode:)])
872 [window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed];
873#endif
874
875 _glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
876 _glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
877
878 return GLFW_TRUE;
879}
880
881
885
886// Transforms a y-coordinate between the CG display and NS screen spaces
887//
888float _glfwTransformYNS(float y)
890 return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1;
891}
892
893
897
899 const _GLFWwndconfig* wndconfig,
900 const _GLFWctxconfig* ctxconfig,
901 const _GLFWfbconfig* fbconfig)
902{
903 @autoreleasepool {
904
905 if (!createNativeWindow(window, wndconfig, fbconfig))
906 return GLFW_FALSE;
907
908 if (ctxconfig->client != GLFW_NO_API)
909 {
910 if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
911 {
912 if (!_glfwInitNSGL())
913 return GLFW_FALSE;
914 if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
915 return GLFW_FALSE;
916 }
917 else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
918 {
919 // EGL implementation on macOS use CALayer* EGLNativeWindowType so we
920 // need to get the layer for EGL window surface creation.
921 [window->ns.view setWantsLayer:YES];
922 window->ns.layer = [window->ns.view layer];
923
924 if (!_glfwInitEGL())
925 return GLFW_FALSE;
926 if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
927 return GLFW_FALSE;
928 }
929 else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
930 {
931 if (!_glfwInitOSMesa())
932 return GLFW_FALSE;
933 if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
934 return GLFW_FALSE;
935 }
936 }
937
938 if (window->monitor)
939 {
942 acquireMonitor(window);
943 }
944
945 return GLFW_TRUE;
946
947 } // autoreleasepool
948}
949
952 @autoreleasepool {
953
954 if (_glfw.ns.disabledCursorWindow == window)
955 _glfw.ns.disabledCursorWindow = NULL;
956
957 [window->ns.object orderOut:nil];
958
959 if (window->monitor)
960 releaseMonitor(window);
961
962 if (window->context.destroy)
963 window->context.destroy(window);
964
965 [window->ns.object setDelegate:nil];
966 [window->ns.delegate release];
967 window->ns.delegate = nil;
968
969 [window->ns.view release];
970 window->ns.view = nil;
971
972 [window->ns.object close];
973 window->ns.object = nil;
974
975 // HACK: Allow Cocoa to catch up before returning
977
978 } // autoreleasepool
979}
980
981void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
983 @autoreleasepool {
984 NSString* string = @(title);
985 [window->ns.object setTitle:string];
986 // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
987 // if the window lacks NSWindowStyleMaskTitled
988 [window->ns.object setMiniwindowTitle:string];
989 } // autoreleasepool
990}
991
993 int count, const GLFWimage* images)
994{
996 "Cocoa: Regular windows do not have icons on macOS");
997}
998
999void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
1001 @autoreleasepool {
1002
1003 const NSRect contentRect =
1004 [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
1005
1006 if (xpos)
1007 *xpos = contentRect.origin.x;
1008 if (ypos)
1009 *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height - 1);
1010
1011 } // autoreleasepool
1012}
1013
1014void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
1016 @autoreleasepool {
1017
1018 const NSRect contentRect = [window->ns.view frame];
1019 const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height - 1), 0, 0);
1020 const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
1021 [window->ns.object setFrameOrigin:frameRect.origin];
1022
1023 } // autoreleasepool
1024}
1025
1026void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
1028 @autoreleasepool {
1029
1030 const NSRect contentRect = [window->ns.view frame];
1031
1032 if (width)
1033 *width = contentRect.size.width;
1034 if (height)
1035 *height = contentRect.size.height;
1036
1037 } // autoreleasepool
1038}
1039
1040void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
1042 @autoreleasepool {
1043
1044 if (window->monitor)
1045 {
1046 if (window->monitor->window == window)
1047 acquireMonitor(window);
1048 }
1049 else
1050 {
1051 NSRect contentRect =
1052 [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
1053 contentRect.origin.y += contentRect.size.height - height;
1054 contentRect.size = NSMakeSize(width, height);
1055 [window->ns.object setFrame:[window->ns.object frameRectForContentRect:contentRect]
1056 display:YES];
1057 }
1058
1059 } // autoreleasepool
1060}
1061
1063 int minwidth, int minheight,
1064 int maxwidth, int maxheight)
1065{
1066 @autoreleasepool {
1067
1068 if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
1069 [window->ns.object setContentMinSize:NSMakeSize(0, 0)];
1070 else
1071 [window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)];
1072
1073 if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
1074 [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];
1075 else
1076 [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];
1077
1078 } // autoreleasepool
1079}
1080
1081void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
1083 @autoreleasepool {
1084 if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
1085 [window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
1086 else
1087 [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
1088 } // autoreleasepool
1089}
1090
1091void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
1093 @autoreleasepool {
1094
1095 const NSRect contentRect = [window->ns.view frame];
1096 const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
1097
1098 if (width)
1099 *width = (int) fbRect.size.width;
1100 if (height)
1101 *height = (int) fbRect.size.height;
1102
1103 } // autoreleasepool
1104}
1105
1107 int* left, int* top,
1108 int* right, int* bottom)
1109{
1110 @autoreleasepool {
1111
1112 const NSRect contentRect = [window->ns.view frame];
1113 const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect];
1114
1115 if (left)
1116 *left = contentRect.origin.x - frameRect.origin.x;
1117 if (top)
1118 *top = frameRect.origin.y + frameRect.size.height -
1119 contentRect.origin.y - contentRect.size.height;
1120 if (right)
1121 *right = frameRect.origin.x + frameRect.size.width -
1122 contentRect.origin.x - contentRect.size.width;
1123 if (bottom)
1124 *bottom = contentRect.origin.y - frameRect.origin.y;
1125
1126 } // autoreleasepool
1127}
1128
1130 float* xscale, float* yscale)
1131{
1132 @autoreleasepool {
1133
1134 const NSRect points = [window->ns.view frame];
1135 const NSRect pixels = [window->ns.view convertRectToBacking:points];
1136
1137 if (xscale)
1138 *xscale = (float) (pixels.size.width / points.size.width);
1139 if (yscale)
1140 *yscale = (float) (pixels.size.height / points.size.height);
1141
1142 } // autoreleasepool
1143}
1144
1147 @autoreleasepool {
1148 [window->ns.object miniaturize:nil];
1149 } // autoreleasepool
1150}
1151
1154 @autoreleasepool {
1155 if ([window->ns.object isMiniaturized])
1156 [window->ns.object deminiaturize:nil];
1157 else if ([window->ns.object isZoomed])
1158 [window->ns.object zoom:nil];
1159 } // autoreleasepool
1160}
1161
1164 @autoreleasepool {
1165 if (![window->ns.object isZoomed])
1166 [window->ns.object zoom:nil];
1167 } // autoreleasepool
1168}
1169
1172 @autoreleasepool {
1173 [window->ns.object orderFront:nil];
1174 } // autoreleasepool
1175}
1176
1179 @autoreleasepool {
1180 [window->ns.object orderOut:nil];
1181 } // autoreleasepool
1182}
1183
1186 @autoreleasepool {
1187 [NSApp requestUserAttention:NSInformationalRequest];
1188 } // autoreleasepool
1189}
1190
1193 @autoreleasepool {
1194 // Make us the active application
1195 // HACK: This is here to prevent applications using only hidden windows from
1196 // being activated, but should probably not be done every time any
1197 // window is shown
1198 [NSApp activateIgnoringOtherApps:YES];
1199 [window->ns.object makeKeyAndOrderFront:nil];
1200 } // autoreleasepool
1201}
1202
1205 int xpos, int ypos,
1206 int width, int height,
1207 int refreshRate)
1208{
1209 @autoreleasepool {
1210
1211 if (window->monitor == monitor)
1212 {
1213 if (monitor)
1214 {
1215 if (monitor->window == window)
1216 acquireMonitor(window);
1217 }
1218 else
1219 {
1220 const NSRect contentRect =
1221 NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height);
1222 const NSRect frameRect =
1223 [window->ns.object frameRectForContentRect:contentRect
1224 styleMask:getStyleMask(window)];
1225
1226 [window->ns.object setFrame:frameRect display:YES];
1227 }
1228
1229 return;
1230 }
1231
1232 if (window->monitor)
1233 releaseMonitor(window);
1234
1235 _glfwInputWindowMonitor(window, monitor);
1236
1237 // HACK: Allow the state cached in Cocoa to catch up to reality
1238 // TODO: Solve this in a less terrible way
1240
1241 const NSUInteger styleMask = getStyleMask(window);
1242 [window->ns.object setStyleMask:styleMask];
1243 // HACK: Changing the style mask can cause the first responder to be cleared
1244 [window->ns.object makeFirstResponder:window->ns.view];
1245
1246 if (window->monitor)
1247 {
1248 [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
1249 [window->ns.object setHasShadow:NO];
1250
1251 acquireMonitor(window);
1252 }
1253 else
1254 {
1255 NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1),
1256 width, height);
1257 NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
1258 styleMask:styleMask];
1259 [window->ns.object setFrame:frameRect display:YES];
1260
1261 if (window->numer != GLFW_DONT_CARE &&
1262 window->denom != GLFW_DONT_CARE)
1263 {
1264 [window->ns.object setContentAspectRatio:NSMakeSize(window->numer,
1265 window->denom)];
1266 }
1267
1268 if (window->minwidth != GLFW_DONT_CARE &&
1269 window->minheight != GLFW_DONT_CARE)
1270 {
1271 [window->ns.object setContentMinSize:NSMakeSize(window->minwidth,
1272 window->minheight)];
1273 }
1274
1275 if (window->maxwidth != GLFW_DONT_CARE &&
1276 window->maxheight != GLFW_DONT_CARE)
1277 {
1278 [window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,
1279 window->maxheight)];
1280 }
1281
1282 if (window->floating)
1283 [window->ns.object setLevel:NSFloatingWindowLevel];
1284 else
1285 [window->ns.object setLevel:NSNormalWindowLevel];
1286
1287 [window->ns.object setHasShadow:YES];
1288 // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
1289 // title property but the miniwindow title property is unaffected
1290 [window->ns.object setTitle:[window->ns.object miniwindowTitle]];
1291 }
1292
1293 } // autoreleasepool
1294}
1295
1298 @autoreleasepool {
1299 return [window->ns.object isKeyWindow];
1300 } // autoreleasepool
1301}
1302
1305 @autoreleasepool {
1306 return [window->ns.object isMiniaturized];
1307 } // autoreleasepool
1308}
1309
1312 @autoreleasepool {
1313 return [window->ns.object isVisible];
1314 } // autoreleasepool
1315}
1316
1319 @autoreleasepool {
1320 return [window->ns.object isZoomed];
1321 } // autoreleasepool
1322}
1323
1326 @autoreleasepool {
1327
1328 const NSPoint point = [NSEvent mouseLocation];
1329
1330 if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
1331 [window->ns.object windowNumber])
1332 {
1333 return GLFW_FALSE;
1334 }
1335
1336 return NSMouseInRect(point,
1337 [window->ns.object convertRectToScreen:[window->ns.view frame]], NO);
1338
1339 } // autoreleasepool
1340}
1341
1344 @autoreleasepool {
1345 return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
1346 } // autoreleasepool
1347}
1348
1351 @autoreleasepool {
1352 [window->ns.object setStyleMask:getStyleMask(window)];
1353 } // autoreleasepool
1354}
1355
1358 @autoreleasepool {
1359 [window->ns.object setStyleMask:getStyleMask(window)];
1360 [window->ns.object makeFirstResponder:window->ns.view];
1361 } // autoreleasepool
1362}
1363
1366 @autoreleasepool {
1367 if (enabled)
1368 [window->ns.object setLevel:NSFloatingWindowLevel];
1369 else
1370 [window->ns.object setLevel:NSNormalWindowLevel];
1371 } // autoreleasepool
1372}
1373
1376 @autoreleasepool {
1377 [window->ns.object setIgnoresMouseEvents:enabled];
1378 }
1379}
1380
1383 @autoreleasepool {
1384 return (float) [window->ns.object alphaValue];
1385 } // autoreleasepool
1386}
1387
1388void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
1390 @autoreleasepool {
1391 [window->ns.object setAlphaValue:opacity];
1392 } // autoreleasepool
1393}
1394
1398 "Cocoa: Raw mouse motion not yet implemented");
1399}
1400
1403 return GLFW_FALSE;
1404}
1405
1406void _glfwPlatformPollEvents(void)
1408 @autoreleasepool {
1409
1410 for (;;)
1411 {
1412 NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
1413 untilDate:[NSDate distantPast]
1414 inMode:NSDefaultRunLoopMode
1415 dequeue:YES];
1416 if (event == nil)
1417 break;
1418
1419 [NSApp sendEvent:event];
1420 }
1421
1422 } // autoreleasepool
1423}
1424
1425void _glfwPlatformWaitEvents(void)
1427 @autoreleasepool {
1428
1429 // I wanted to pass NO to dequeue:, and rely on PollEvents to
1430 // dequeue and send. For reasons not at all clear to me, passing
1431 // NO to dequeue: causes this method never to return.
1432 NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
1433 untilDate:[NSDate distantFuture]
1434 inMode:NSDefaultRunLoopMode
1435 dequeue:YES];
1436 [NSApp sendEvent:event];
1437
1439
1440 } // autoreleasepool
1441}
1442
1443void _glfwPlatformWaitEventsTimeout(double timeout)
1445 @autoreleasepool {
1446
1447 NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
1448 NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
1449 untilDate:date
1450 inMode:NSDefaultRunLoopMode
1451 dequeue:YES];
1452 if (event)
1453 [NSApp sendEvent:event];
1454
1456
1457 } // autoreleasepool
1458}
1459
1462 @autoreleasepool {
1463
1464 NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
1465 location:NSMakePoint(0, 0)
1466 modifierFlags:0
1467 timestamp:0
1468 windowNumber:0
1469 context:nil
1470 subtype:0
1471 data1:0
1472 data2:0];
1473 [NSApp postEvent:event atStart:YES];
1474
1475 } // autoreleasepool
1476}
1477
1478void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
1480 @autoreleasepool {
1481
1482 const NSRect contentRect = [window->ns.view frame];
1483 // NOTE: The returned location uses base 0,1 not 0,0
1484 const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
1485
1486 if (xpos)
1487 *xpos = pos.x;
1488 if (ypos)
1489 *ypos = contentRect.size.height - pos.y;
1490
1491 } // autoreleasepool
1492}
1493
1494void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
1496 @autoreleasepool {
1497
1498 updateCursorImage(window);
1499
1500 const NSRect contentRect = [window->ns.view frame];
1501 // NOTE: The returned location uses base 0,1 not 0,0
1502 const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
1503
1504 window->ns.cursorWarpDeltaX += x - pos.x;
1505 window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y;
1506
1507 if (window->monitor)
1508 {
1509 CGDisplayMoveCursorToPoint(window->monitor->ns.displayID,
1510 CGPointMake(x, y));
1511 }
1512 else
1513 {
1514 const NSRect localRect = NSMakeRect(x, contentRect.size.height - y - 1, 0, 0);
1515 const NSRect globalRect = [window->ns.object convertRectToScreen:localRect];
1516 const NSPoint globalPoint = globalRect.origin;
1517
1518 CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
1519 _glfwTransformYNS(globalPoint.y)));
1520 }
1521
1522 } // autoreleasepool
1523}
1524
1525void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
1527 @autoreleasepool {
1528 if (_glfwPlatformWindowFocused(window))
1529 updateCursorMode(window);
1530 } // autoreleasepool
1531}
1532
1533const char* _glfwPlatformGetScancodeName(int scancode)
1535 @autoreleasepool {
1536
1537 if (scancode < 0 || scancode > 0xff ||
1538 _glfw.ns.keycodes[scancode] == GLFW_KEY_UNKNOWN)
1539 {
1540 _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
1541 return NULL;
1542 }
1543
1544 const int key = _glfw.ns.keycodes[scancode];
1545
1546 UInt32 deadKeyState = 0;
1547 UniChar characters[4];
1548 UniCharCount characterCount = 0;
1549
1550 if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes],
1551 scancode,
1552 kUCKeyActionDisplay,
1553 0,
1554 LMGetKbdType(),
1555 kUCKeyTranslateNoDeadKeysBit,
1556 &deadKeyState,
1557 sizeof(characters) / sizeof(characters[0]),
1558 &characterCount,
1559 characters) != noErr)
1560 {
1561 return NULL;
1562 }
1563
1564 if (!characterCount)
1565 return NULL;
1566
1567 CFStringRef string = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
1568 characters,
1569 characterCount,
1570 kCFAllocatorNull);
1571 CFStringGetCString(string,
1572 _glfw.ns.keynames[key],
1573 sizeof(_glfw.ns.keynames[key]),
1574 kCFStringEncodingUTF8);
1575 CFRelease(string);
1576
1577 return _glfw.ns.keynames[key];
1578
1579 } // autoreleasepool
1580}
1581
1582int _glfwPlatformGetKeyScancode(int key)
1584 return _glfw.ns.scancodes[key];
1585}
1586
1588 const GLFWimage* image,
1589 int xhot, int yhot)
1590{
1591 @autoreleasepool {
1592
1593 NSImage* native;
1594 NSBitmapImageRep* rep;
1595
1596 rep = [[NSBitmapImageRep alloc]
1597 initWithBitmapDataPlanes:NULL
1598 pixelsWide:image->width
1599 pixelsHigh:image->height
1600 bitsPerSample:8
1601 samplesPerPixel:4
1602 hasAlpha:YES
1603 isPlanar:NO
1604 colorSpaceName:NSCalibratedRGBColorSpace
1605 bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
1606 bytesPerRow:image->width * 4
1607 bitsPerPixel:32];
1608
1609 if (rep == nil)
1610 return GLFW_FALSE;
1611
1612 memcpy([rep bitmapData], image->pixels, image->width * image->height * 4);
1613
1614 native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
1615 [native addRepresentation:rep];
1616
1617 cursor->ns.object = [[NSCursor alloc] initWithImage:native
1618 hotSpot:NSMakePoint(xhot, yhot)];
1619
1620 [native release];
1621 [rep release];
1622
1623 if (cursor->ns.object == nil)
1624 return GLFW_FALSE;
1625
1626 return GLFW_TRUE;
1627
1628 } // autoreleasepool
1629}
1630
1631int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
1633 @autoreleasepool {
1634
1635 SEL cursorSelector = NULL;
1636
1637 // HACK: Try to use a private message
1638 switch (shape)
1639 {
1641 cursorSelector = NSSelectorFromString(@"_windowResizeEastWestCursor");
1642 break;
1644 cursorSelector = NSSelectorFromString(@"_windowResizeNorthSouthCursor");
1645 break;
1647 cursorSelector = NSSelectorFromString(@"_windowResizeNorthWestSouthEastCursor");
1648 break;
1650 cursorSelector = NSSelectorFromString(@"_windowResizeNorthEastSouthWestCursor");
1651 break;
1652 }
1653
1654 if (cursorSelector && [NSCursor respondsToSelector:cursorSelector])
1655 {
1656 id object = [NSCursor performSelector:cursorSelector];
1657 if ([object isKindOfClass:[NSCursor class]])
1658 cursor->ns.object = object;
1659 }
1660
1661 if (!cursor->ns.object)
1662 {
1663 switch (shape)
1664 {
1665 case GLFW_ARROW_CURSOR:
1666 cursor->ns.object = [NSCursor arrowCursor];
1667 break;
1668 case GLFW_IBEAM_CURSOR:
1669 cursor->ns.object = [NSCursor IBeamCursor];
1670 break;
1672 cursor->ns.object = [NSCursor crosshairCursor];
1673 break;
1675 cursor->ns.object = [NSCursor pointingHandCursor];
1676 break;
1678 cursor->ns.object = [NSCursor resizeLeftRightCursor];
1679 break;
1681 cursor->ns.object = [NSCursor resizeUpDownCursor];
1682 break;
1684 cursor->ns.object = [NSCursor closedHandCursor];
1685 break;
1687 cursor->ns.object = [NSCursor operationNotAllowedCursor];
1688 break;
1689 }
1690 }
1691
1692 if (!cursor->ns.object)
1693 {
1695 "Cocoa: Standard cursor shape unavailable");
1696 return GLFW_FALSE;
1697 }
1698
1699 [cursor->ns.object retain];
1700 return GLFW_TRUE;
1701
1702 } // autoreleasepool
1703}
1704
1707 @autoreleasepool {
1708 if (cursor->ns.object)
1709 [(NSCursor*) cursor->ns.object release];
1710 } // autoreleasepool
1711}
1712
1713void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
1715 @autoreleasepool {
1716 if (cursorInContentArea(window))
1717 updateCursorImage(window);
1718 } // autoreleasepool
1719}
1720
1721void _glfwPlatformSetClipboardString(const char* string)
1723 @autoreleasepool {
1724 NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
1725 [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
1726 [pasteboard setString:@(string) forType:NSPasteboardTypeString];
1727 } // autoreleasepool
1728}
1729
1730const char* _glfwPlatformGetClipboardString(void)
1732 @autoreleasepool {
1733
1734 NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
1735
1736 if (![[pasteboard types] containsObject:NSPasteboardTypeString])
1737 {
1739 "Cocoa: Failed to retrieve string from pasteboard");
1740 return NULL;
1741 }
1742
1743 NSString* object = [pasteboard stringForType:NSPasteboardTypeString];
1744 if (!object)
1745 {
1747 "Cocoa: Failed to retrieve object from pasteboard");
1748 return NULL;
1749 }
1750
1751 free(_glfw.ns.clipboardString);
1752 _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
1753
1754 return _glfw.ns.clipboardString;
1755
1756 } // autoreleasepool
1757}
1758
1762 {
1763 int type = 0;
1764
1766 {
1769 }
1770
1772 {
1775 }
1776
1777 if (type)
1778 {
1779 *attribs = calloc(3, sizeof(EGLint));
1780 (*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE;
1781 (*attribs)[1] = type;
1782 (*attribs)[2] = EGL_NONE;
1784 }
1785 }
1786
1787 return 0;
1788}
1789
1792 return EGL_DEFAULT_DISPLAY;
1793}
1794
1797 return window->ns.layer;
1798}
1799
1800void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
1802 if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface)
1803 {
1804 extensions[0] = "VK_KHR_surface";
1805 extensions[1] = "VK_EXT_metal_surface";
1806 }
1807 else if (_glfw.vk.KHR_surface && _glfw.vk.MVK_macos_surface)
1808 {
1809 extensions[0] = "VK_KHR_surface";
1810 extensions[1] = "VK_MVK_macos_surface";
1811 }
1812}
1813
1816 uint32_t queuefamily)
1817{
1818 return GLFW_TRUE;
1819}
1820
1823 const VkAllocationCallbacks* allocator,
1824 VkSurfaceKHR* surface)
1825{
1826 @autoreleasepool {
1827
1828#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
1829 // HACK: Dynamically load Core Animation to avoid adding an extra
1830 // dependency for the majority who don't use MoltenVK
1831 NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
1832 if (!bundle)
1833 {
1835 "Cocoa: Failed to find QuartzCore.framework");
1837 }
1838
1839 // NOTE: Create the layer here as makeBackingLayer should not return nil
1840 window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
1841 if (!window->ns.layer)
1842 {
1844 "Cocoa: Failed to create layer for view");
1846 }
1847
1848 if (window->ns.retina)
1849 [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
1850
1851 [window->ns.view setLayer:window->ns.layer];
1852 [window->ns.view setWantsLayer:YES];
1853
1854 VkResult err;
1855
1856 if (_glfw.vk.EXT_metal_surface)
1857 {
1859
1860 PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
1861 vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)
1862 vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT");
1863 if (!vkCreateMetalSurfaceEXT)
1864 {
1866 "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension");
1868 }
1869
1870 memset(&sci, 0, sizeof(sci));
1872 sci.pLayer = window->ns.layer;
1873
1874 err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface);
1875 }
1876 else
1877 {
1879
1880 PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
1881 vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
1882 vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
1883 if (!vkCreateMacOSSurfaceMVK)
1884 {
1886 "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
1888 }
1889
1890 memset(&sci, 0, sizeof(sci));
1892 sci.pView = window->ns.view;
1893
1894 err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
1895 }
1896
1897 if (err)
1898 {
1900 "Cocoa: Failed to create Vulkan surface: %s",
1902 }
1903
1904 return err;
1905#else
1907#endif
1908
1909 } // autoreleasepool
1910}
1911
1912
1916
1919 _GLFWwindow* window = (_GLFWwindow*) handle;
1921 return window->ns.object;
1922}
1923
void _glfwRestoreVideoModeNS(_GLFWmonitor *monitor)
void _glfwPlatformGetVideoMode(_GLFWmonitor *monitor, GLFWvidmode *mode)
void _glfwSetVideoModeNS(_GLFWmonitor *monitor, const GLFWvidmode *desired)
void _glfwPlatformGetMonitorPos(_GLFWmonitor *monitor, int *xpos, int *ypos)
#define NSWindowStyleMaskResizable
#define NSEventModifierFlagOption
#define NSEventModifierFlagCommand
#define NSEventModifierFlagCapsLock
#define LMGetKbdType
#define NSEventModifierFlagDeviceIndependentFlagsMask
#define NSWindowStyleMaskTitled
VkResult(APIENTRY * PFN_vkCreateMetalSurfaceEXT)(VkInstance, const VkMetalSurfaceCreateInfoEXT *, const VkAllocationCallbacks *, VkSurfaceKHR *)
#define NSWindowStyleMaskMiniaturizable
VkResult(APIENTRY * PFN_vkCreateMacOSSurfaceMVK)(VkInstance, const VkMacOSSurfaceCreateInfoMVK *, const VkAllocationCallbacks *, VkSurfaceKHR *)
#define NSWindowStyleMaskClosable
#define NSEventModifierFlagShift
#define NSEventModifierFlagControl
#define NSWindowStyleMaskBorderless
void _glfwPlatformSetWindowMonitor(_GLFWwindow *window, _GLFWmonitor *monitor, int xpos, int ypos, int width, int height, int refreshRate)
void _glfwPlatformGetWindowContentScale(_GLFWwindow *window, float *xscale, float *yscale)
void _glfwPlatformSetCursorPos(_GLFWwindow *window, double x, double y)
void _glfwPlatformSetWindowResizable(_GLFWwindow *window, GLFWbool enabled)
int _glfwPlatformWindowIconified(_GLFWwindow *window)
void _glfwPlatformMaximizeWindow(_GLFWwindow *window)
EGLenum _glfwPlatformGetEGLPlatform(EGLint **attribs)
void _glfwPlatformIconifyWindow(_GLFWwindow *window)
float _glfwTransformYNS(float y)
Definition: cocoa_window.m:889
void _glfwPlatformSetWindowSize(_GLFWwindow *window, int width, int height)
void _glfwPlatformWaitEvents(void)
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow *window, int minwidth, int minheight, int maxwidth, int maxheight)
void _glfwPlatformGetRequiredInstanceExtensions(char **extensions)
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow *window, const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface)
int _glfwPlatformFramebufferTransparent(_GLFWwindow *window)
int _glfwPlatformCreateCursor(_GLFWcursor *cursor, const GLFWimage *image, int xhot, int yhot)
void _glfwPlatformPollEvents(void)
void _glfwPlatformGetFramebufferSize(_GLFWwindow *window, int *width, int *height)
int _glfwPlatformWindowVisible(_GLFWwindow *window)
void _glfwPlatformSetCursor(_GLFWwindow *window, _GLFWcursor *cursor)
void _glfwPlatformGetWindowSize(_GLFWwindow *window, int *width, int *height)
void _glfwPlatformSetWindowPos(_GLFWwindow *window, int x, int y)
void _glfwPlatformGetWindowFrameSize(_GLFWwindow *window, int *left, int *top, int *right, int *bottom)
void _glfwPlatformSetWindowIcon(_GLFWwindow *window, int count, const GLFWimage *images)
Definition: cocoa_window.m:993
EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow *window)
const char * _glfwPlatformGetScancodeName(int scancode)
void _glfwPlatformSetWindowDecorated(_GLFWwindow *window, GLFWbool enabled)
void _glfwPlatformGetWindowPos(_GLFWwindow *window, int *xpos, int *ypos)
void _glfwPlatformSetWindowOpacity(_GLFWwindow *window, float opacity)
float _glfwPlatformGetWindowOpacity(_GLFWwindow *window)
void _glfwPlatformDestroyCursor(_GLFWcursor *cursor)
void _glfwPlatformRestoreWindow(_GLFWwindow *window)
GLFWbool _glfwPlatformRawMouseMotionSupported(void)
void _glfwPlatformSetCursorMode(_GLFWwindow *window, int mode)
int _glfwPlatformWindowHovered(_GLFWwindow *window)
void _glfwPlatformDestroyWindow(_GLFWwindow *window)
Definition: cocoa_window.m:951
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformHideWindow(_GLFWwindow *window)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily)
int _glfwPlatformWindowMaximized(_GLFWwindow *window)
void _glfwPlatformSetClipboardString(const char *string)
void _glfwPlatformShowWindow(_GLFWwindow *window)
GLFWAPI id glfwGetCocoaWindow(GLFWwindow *handle)
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
int _glfwPlatformWindowFocused(_GLFWwindow *window)
void _glfwPlatformPostEmptyEvent(void)
int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformCreateStandardCursor(_GLFWcursor *cursor, int shape)
int _glfwPlatformCreateWindow(_GLFWwindow *window, const _GLFWwndconfig *wndconfig, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
Definition: cocoa_window.m:899
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow *window, int numer, int denom)
const char * _glfwPlatformGetClipboardString(void)
void _glfwPlatformGetCursorPos(_GLFWwindow *window, double *xpos, double *ypos)
void _glfwPlatformRequestWindowAttention(_GLFWwindow *window)
EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void)
void _glfwPlatformSetWindowTitle(_GLFWwindow *window, const char *title)
Definition: cocoa_window.m:982
void _glfwPlatformFocusWindow(_GLFWwindow *window)
void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow *window, GLFWbool enabled)
void _glfwPlatformSetWindowFloating(_GLFWwindow *window, GLFWbool enabled)
GLFWbool _glfwInitEGL(void)
Definition: egl_context.c:303
GLFWbool _glfwCreateContextEGL(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
Definition: egl_context.c:505
#define EGL_DEFAULT_DISPLAY
Definition: egl_context.h:75
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE
Definition: egl_context.h:98
unsigned int EGLenum
Definition: egl_context.h:109
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE
Definition: egl_context.h:99
void * EGLNativeDisplayType
Definition: egl_context.h:115
#define EGL_NONE
Definition: egl_context.h:66
void * EGLNativeWindowType
Definition: egl_context.h:116
int EGLint
Definition: egl_context.h:107
#define EGL_PLATFORM_ANGLE_ANGLE
Definition: egl_context.h:97
#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
Definition: egl_context.h:104
#define GLFW_EGL_CONTEXT_API
Definition: glfw3.h:1113
#define GLFW_NATIVE_CONTEXT_API
Definition: glfw3.h:1112
#define GLFW_CURSOR_DISABLED
Definition: glfw3.h:1106
#define GLFWAPI
Definition: glfw3.h:269
#define GLFW_DONT_CARE
Definition: glfw3.h:1262
#define GLFW_NO_API
Definition: glfw3.h:1086
#define GLFW_ANGLE_PLATFORM_TYPE_METAL
Definition: glfw3.h:1122
#define GLFW_CURSOR_HIDDEN
Definition: glfw3.h:1105
#define GLFW_ANGLE_PLATFORM_TYPE_OPENGL
Definition: glfw3.h:1117
#define GLFW_CURSOR_NORMAL
Definition: glfw3.h:1104
#define GLFW_OSMESA_CONTEXT_API
Definition: glfw3.h:1114
#define GLFW_MOUSE_BUTTON_RIGHT
Definition: glfw3.h:579
#define GLFW_MOUSE_BUTTON_LEFT
Definition: glfw3.h:578
#define GLFW_CURSOR_UNAVAILABLE
The specified cursor shape is not available.
Definition: glfw3.h:796
#define GLFW_FORMAT_UNAVAILABLE
The requested format is not supported or available.
Definition: glfw3.h:777
#define GLFW_FEATURE_UNAVAILABLE
The requested feature is not provided by the platform.
Definition: glfw3.h:810
#define GLFW_API_UNAVAILABLE
GLFW could not find support for the requested API on the system.
Definition: glfw3.h:730
#define GLFW_FEATURE_UNIMPLEMENTED
The requested feature is not implemented for the platform.
Definition: glfw3.h:823
#define GLFW_INVALID_VALUE
One of the arguments to the function was an invalid value.
Definition: glfw3.h:706
#define GLFW_PLATFORM_ERROR
A platform-specific error occurred that does not match any of the more specific categories.
Definition: glfw3.h:758
#define GLFW_TRUE
One.
Definition: glfw3.h:310
#define GLFW_FALSE
Zero.
Definition: glfw3.h:319
#define GLFW_PRESS
The key or mouse button was pressed.
Definition: glfw3.h:336
#define GLFW_RELEASE
The key or mouse button was released.
Definition: glfw3.h:329
#define GLFW_KEY_RIGHT_ALT
Definition: glfw3.h:511
#define GLFW_KEY_LEFT_ALT
Definition: glfw3.h:507
#define GLFW_KEY_LEFT_SHIFT
Definition: glfw3.h:505
#define GLFW_KEY_CAPS_LOCK
Definition: glfw3.h:458
#define GLFW_KEY_UNKNOWN
Definition: glfw3.h:389
#define GLFW_KEY_LEFT_CONTROL
Definition: glfw3.h:506
#define GLFW_KEY_RIGHT_CONTROL
Definition: glfw3.h:510
#define GLFW_KEY_RIGHT_SUPER
Definition: glfw3.h:512
#define GLFW_KEY_LEFT_SUPER
Definition: glfw3.h:508
#define GLFW_KEY_RIGHT_SHIFT
Definition: glfw3.h:509
#define GLFW_MOD_SHIFT
If this bit is set one or more Shift keys were held down.
Definition: glfw3.h:531
#define GLFW_MOD_SUPER
If this bit is set one or more Super keys were held down.
Definition: glfw3.h:546
#define GLFW_MOD_CONTROL
If this bit is set one or more Control keys were held down.
Definition: glfw3.h:536
#define GLFW_MOD_ALT
If this bit is set one or more Alt keys were held down.
Definition: glfw3.h:541
#define GLFW_MOD_CAPS_LOCK
If this bit is set the Caps Lock key is enabled.
Definition: glfw3.h:552
#define GLFW_RESIZE_EW_CURSOR
The horizontal resize/move arrow shape.
Definition: glfw3.h:1158
#define GLFW_NOT_ALLOWED_CURSOR
The operation-not-allowed shape.
Definition: glfw3.h:1212
#define GLFW_IBEAM_CURSOR
The text input I-beam cursor shape.
Definition: glfw3.h:1142
#define GLFW_RESIZE_ALL_CURSOR
The omni-directional resize/move cursor shape.
Definition: glfw3.h:1200
#define GLFW_ARROW_CURSOR
The regular arrow cursor shape.
Definition: glfw3.h:1137
#define GLFW_CROSSHAIR_CURSOR
The crosshair cursor shape.
Definition: glfw3.h:1147
#define GLFW_RESIZE_NS_CURSOR
The vertical resize/move arrow shape.
Definition: glfw3.h:1164
#define GLFW_POINTING_HAND_CURSOR
The pointing hand cursor shape.
Definition: glfw3.h:1152
#define GLFW_RESIZE_NESW_CURSOR
The top-right to bottom-left diagonal resize/move arrow shape.
Definition: glfw3.h:1194
#define GLFW_RESIZE_NWSE_CURSOR
The top-left to bottom-right diagonal resize/move arrow shape.
Definition: glfw3.h:1179
struct GLFWwindow GLFWwindow
Opaque window object.
Definition: glfw3.h:1319
_GLFWlibrary _glfw
Definition: init.c:46
void _glfwInputError(int code, const char *format,...)
Definition: init.c:160
char * _glfw_strdup(const char *source)
Definition: init.c:121
void _glfwInputDrop(_GLFWwindow *window, int count, const char **paths)
Definition: input.c:378
void _glfwInputCursorEnter(_GLFWwindow *window, GLFWbool entered)
Definition: input.c:370
void _glfwInputScroll(_GLFWwindow *window, double xoffset, double yoffset)
Definition: input.c:328
void _glfwInputChar(_GLFWwindow *window, unsigned int codepoint, int mods, GLFWbool plain)
Definition: input.c:308
void _glfwInputCursorPos(_GLFWwindow *window, double xpos, double ypos)
Definition: input.c:356
void _glfwInputKey(_GLFWwindow *window, int key, int scancode, int action, int mods)
Definition: input.c:277
void _glfwCenterCursorInContentArea(_GLFWwindow *window)
Definition: input.c:475
void _glfwInputMouseClick(_GLFWwindow *window, int button, int action, int mods)
Definition: input.c:336
NSTrackingArea * trackingArea
Definition: cocoa_window.m:344
_GLFWwindow * window
Definition: cocoa_window.m:343
NSMutableAttributedString * markedText
Definition: cocoa_window.m:345
_GLFWwindow * window
Definition: cocoa_window.m:220
void _glfwInputMonitorWindow(_GLFWmonitor *monitor, _GLFWwindow *window)
Definition: monitor.c:155
uint64_t VkSurfaceKHR
Definition: internal.h:120
void _glfwInputFramebufferSize(_GLFWwindow *window, int width, int height)
Definition: window.c:108
void * VkInstance
Definition: internal.h:118
void _glfwInputWindowIconify(_GLFWwindow *window, GLFWbool iconified)
Definition: window.c:91
void _glfwInputWindowMaximize(_GLFWwindow *window, GLFWbool maximized)
Definition: window.c:99
void _glfwInputWindowSize(_GLFWwindow *window, int width, int height)
Definition: window.c:83
void _glfwInputWindowMonitor(_GLFWwindow *window, _GLFWmonitor *monitor)
Definition: window.c:143
#define _GLFW_REQUIRE_INIT_OR_RETURN(x)
Definition: internal.h:214
void _glfwInputWindowPos(_GLFWwindow *window, int xpos, int ypos)
Definition: window.c:74
void * VkPhysicalDevice
Definition: internal.h:119
const char * _glfwGetVulkanResultString(VkResult result)
Definition: vulkan.c:165
void _glfwInputWindowContentScale(_GLFWwindow *window, float xscale, float yscale)
Definition: window.c:117
int GLFWbool
Definition: internal.h:61
void _glfwInputWindowDamage(_GLFWwindow *window)
Definition: window.c:125
void _glfwInputWindowCloseRequest(_GLFWwindow *window)
Definition: window.c:133
void _glfwInputWindowFocus(_GLFWwindow *window, GLFWbool focused)
Definition: window.c:45
@ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK
Definition: internal.h:130
@ VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT
Definition: internal.h:131
#define NULL
Definition: miniaudio.h:3718
GLFWbool _glfwCreateContextNSGL(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
Definition: nsgl_context.m:158
GLFWbool _glfwInitNSGL(void)
Definition: nsgl_context.m:133
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
GLFWbool _glfwInitOSMesa(void)
unsigned int uint32_t
Definition: stdint.h:80
_GLFWdestroycontextfun destroy
Definition: internal.h:365
GLFWbool transparent
Definition: internal.h:340
GLFWbool ANGLE_platform_angle_metal
Definition: egl_context.h:191
GLFWbool ANGLE_platform_angle
Definition: egl_context.h:187
GLFWbool ANGLE_platform_angle_opengl
Definition: egl_context.h:188
_GLFWlibraryEGL egl
Definition: internal.h:595
struct _GLFWlibrary::@25 vk
GLFWbool KHR_surface
Definition: internal.h:569
_GLFWinitconfig init
Definition: internal.h:532
struct _GLFWlibrary::@23 hints
_GLFWwindow * window
Definition: internal.h:446
int minwidth
Definition: internal.h:395
int minheight
Definition: internal.h:395
GLFWvidmode videoMode
Definition: internal.h:391
int cursorMode
Definition: internal.h:402
double virtualCursorPosY
Definition: internal.h:406
_GLFWmonitor * monitor
Definition: internal.h:392
GLFWbool resizable
Definition: internal.h:382
double virtualCursorPosX
Definition: internal.h:406
int maxheight
Definition: internal.h:396
GLFWbool decorated
Definition: internal.h:383
int maxwidth
Definition: internal.h:396
GLFWwindowsizefun size
Definition: internal.h:413
GLFWbool autoIconify
Definition: internal.h:384
GLFWbool floating
Definition: internal.h:385
GLFWwindowclosefun close
Definition: internal.h:414
char keys[GLFW_KEY_LAST+1]
Definition: internal.h:404
_GLFWcursor * cursor
Definition: internal.h:393
_GLFWcontext context
Definition: internal.h:409
char frameName[256]
Definition: internal.h:280
struct _GLFWwndconfig::@18 ns
GLFWbool resizable
Definition: internal.h:267
GLFWbool retina
Definition: internal.h:279
GLFWbool floating
Definition: internal.h:272
GLFWbool maximized
Definition: internal.h:273
Image data.
Definition: glfw3.h:1855
int height
Definition: glfw3.h:1861
unsigned char * pixels
Definition: glfw3.h:1864
int width
Definition: glfw3.h:1858
Video mode type.
Definition: glfw3.h:1792
int width
Definition: glfw3.h:1795
int height
Definition: glfw3.h:1798
VkResult
Definition: vulkan.h:842
@ VK_ERROR_EXTENSION_NOT_PRESENT
Definition: vulkan.h:855
#define vkGetInstanceProcAddr
Definition: vulkan.h:3378