Blender V4.5
GHOST_WindowCocoa.mm
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7#include "GHOST_Debug.hh"
9
10/* Don't generate OpenGL deprecation warning. This is a known thing, and is not something easily
11 * solvable in a short term. */
12#ifdef __clang__
13# pragma clang diagnostic ignored "-Wdeprecated-declarations"
14#endif
15
16#ifdef WITH_METAL_BACKEND
17# include "GHOST_ContextCGL.hh"
18#endif
19
20#ifdef WITH_VULKAN_BACKEND
21# include "GHOST_ContextVK.hh"
22#endif
23
24#import <Cocoa/Cocoa.h>
25#import <Metal/Metal.h>
26#import <QuartzCore/QuartzCore.h>
27
28#include <sys/sysctl.h>
29
30/* --------------------------------------------------------------------
31 * Blender window delegate object.
32 */
33
34@interface BlenderWindowDelegate : NSObject <NSWindowDelegate>
35
36@property(nonatomic, readonly, assign) GHOST_SystemCocoa *systemCocoa;
37@property(nonatomic, readonly, assign) GHOST_WindowCocoa *windowCocoa;
38
39- (instancetype)initWithSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
40 windowCocoa:(GHOST_WindowCocoa *)winCocoa;
41- (void)windowDidBecomeKey:(NSNotification *)notification;
42- (void)windowDidResignKey:(NSNotification *)notification;
43- (void)windowDidExpose:(NSNotification *)notification;
44- (void)windowDidResize:(NSNotification *)notification;
45- (void)windowDidMove:(NSNotification *)notification;
46- (void)windowWillMove:(NSNotification *)notification;
47- (BOOL)windowShouldClose:(id)sender;
48- (void)windowDidChangeBackingProperties:(NSNotification *)notification;
49
50@end
51
52@implementation BlenderWindowDelegate : NSObject
53
54@synthesize systemCocoa = m_systemCocoa;
55@synthesize windowCocoa = m_windowCocoa;
56
57- (instancetype)initWithSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
58 windowCocoa:(GHOST_WindowCocoa *)winCocoa
59{
60 self = [super init];
61
62 if (self) {
63 m_systemCocoa = sysCocoa;
64 m_windowCocoa = winCocoa;
65 }
66
67 return self;
68}
69
70- (void)windowDidBecomeKey:(NSNotification *)notification
71{
72 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, m_windowCocoa);
73 /* Workaround for broken app-switching when combining Command-Tab and mission-control. */
74 [(NSWindow *)m_windowCocoa->getOSWindow() orderFrontRegardless];
75}
76
77- (void)windowDidResignKey:(NSNotification *)notification
78{
79 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, m_windowCocoa);
80}
81
82- (void)windowDidExpose:(NSNotification *)notification
83{
84 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, m_windowCocoa);
85}
86
87- (void)windowDidMove:(NSNotification *)notification
88{
89 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, m_windowCocoa);
90}
91
92- (void)windowWillMove:(NSNotification *)notification
93{
94 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, m_windowCocoa);
95}
96
97- (void)windowWillEnterFullScreen:(NSNotification *)notification
98{
99 m_windowCocoa->setImmediateDraw(true);
100}
101
102- (void)windowDidEnterFullScreen:(NSNotification *)notification
103{
104 /* macOS does not send a window resize event when switching between zoomed
105 * and full-screen, when automatic show/hide of dock and menu bar are enabled.
106 * Send our own to prevent artifacts. */
107 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, m_windowCocoa);
108
109 m_windowCocoa->setImmediateDraw(false);
110}
111
112- (void)windowWillExitFullScreen:(NSNotification *)notification
113{
114 m_windowCocoa->setImmediateDraw(true);
115}
116
117- (void)windowDidExitFullScreen:(NSNotification *)notification
118{
119 /* See comment for windowWillEnterFullScreen. */
120 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, m_windowCocoa);
121 m_windowCocoa->setImmediateDraw(false);
122}
123
124- (void)windowDidResize:(NSNotification *)notification
125{
126#if 0
127 if (![[notification object] inLiveResize])
128#endif
129 {
130 /* Send event only once, at end of resize operation (when user has released mouse button). */
131 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, m_windowCocoa);
132 }
133 /* Live resize, send event, gets handled in wm_window.c.
134 * Needed because live resize runs in a modal loop, not letting main loop run */
135 if ([[notification object] inLiveResize]) {
136 m_systemCocoa->dispatchEvents();
137 }
138}
139
140- (void)windowDidChangeBackingProperties:(NSNotification *)notification
141{
142 m_systemCocoa->handleWindowEvent(GHOST_kEventNativeResolutionChange, m_windowCocoa);
143 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, m_windowCocoa);
144}
145
146- (BOOL)windowShouldClose:(id)sender;
147{
148 /* Let Blender close the window rather than closing immediately. */
149 m_systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, m_windowCocoa);
150 return false;
151}
152
153@end
154
155@interface BlenderWindow : NSWindow
156
157@property(nonatomic, readonly, assign) GHOST_SystemCocoa *systemCocoa;
158@property(nonatomic, readonly, assign) GHOST_WindowCocoa *windowCocoa;
159@property(nonatomic, readonly, assign) GHOST_TDragnDropTypes draggedObjectType;
160
161- (instancetype)initWithSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
162 windowCocoa:(GHOST_WindowCocoa *)winCocoa
163 contentRect:(NSRect)contentRect
164 styleMask:(NSWindowStyleMask)style
165 backing:(NSBackingStoreType)backingStoreType
166 defer:(BOOL)flag;
167
168@end
169
170@implementation BlenderWindow
171
172@synthesize systemCocoa = m_systemCocoa;
173@synthesize windowCocoa = m_windowCocoa;
174@synthesize draggedObjectType = m_draggedObjectType;
175
176- (instancetype)initWithSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
177 windowCocoa:(GHOST_WindowCocoa *)winCocoa
178 contentRect:(NSRect)contentRect
179 styleMask:(NSWindowStyleMask)style
180 backing:(NSBackingStoreType)backingStoreType
181 defer:(BOOL)flag
182{
183 self = [super initWithContentRect:contentRect
184 styleMask:style
185 backing:backingStoreType
186 defer:flag];
187
188 if (self) {
189 m_systemCocoa = sysCocoa;
190 m_windowCocoa = winCocoa;
191 }
192
193 return self;
194}
195
196- (BOOL)canBecomeKeyWindow
197{
198 /* Don't make other windows active when a dialog window is open. */
199 return (m_windowCocoa->isDialog() || !m_systemCocoa->hasDialogWindow());
200}
201
202/* The drag & drop dragging destination methods. */
203- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
204{
205 @autoreleasepool {
206 NSPasteboard *draggingPBoard = sender.draggingPasteboard;
207 if ([[draggingPBoard types] containsObject:NSPasteboardTypeTIFF]) {
208 m_draggedObjectType = GHOST_kDragnDropTypeBitmap;
209 }
210 else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) {
211 m_draggedObjectType = GHOST_kDragnDropTypeFilenames;
212 }
213 else if ([[draggingPBoard types] containsObject:NSPasteboardTypeString]) {
214 m_draggedObjectType = GHOST_kDragnDropTypeString;
215 }
216 else {
217 return NSDragOperationNone;
218 }
219
220 const NSPoint mouseLocation = sender.draggingLocation;
221 m_windowCocoa->setAcceptDragOperation(TRUE); /* Drag operation is accepted by default. */
222 m_systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered,
223 m_draggedObjectType,
224 m_windowCocoa,
225 mouseLocation.x,
226 mouseLocation.y,
227 nil);
228 }
229 return NSDragOperationCopy;
230}
231
232- (BOOL)wantsPeriodicDraggingUpdates
233{
234 return NO; /* No need to overflow blender event queue. Events shall be sent only on changes. */
235}
236
237- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
238{
239 const NSPoint mouseLocation = [sender draggingLocation];
240
241 m_systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated,
242 m_draggedObjectType,
243 m_windowCocoa,
244 mouseLocation.x,
245 mouseLocation.y,
246 nil);
247 return m_windowCocoa->canAcceptDragOperation() ? NSDragOperationCopy : NSDragOperationNone;
248}
249
250- (void)draggingExited:(id<NSDraggingInfo>)sender
251{
252 m_systemCocoa->handleDraggingEvent(
253 GHOST_kEventDraggingExited, m_draggedObjectType, m_windowCocoa, 0, 0, nil);
254 m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
255}
256
257- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender
258{
259 if (m_windowCocoa->canAcceptDragOperation()) {
260 return YES;
261 }
262 return NO;
263}
264
265- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
266{
267 @autoreleasepool {
268 NSPasteboard *draggingPBoard = sender.draggingPasteboard;
269 id data;
270
271 switch (m_draggedObjectType) {
273 if (![NSImage canInitWithPasteboard:draggingPBoard]) {
274 return NO;
275 }
276 /* Caller must [release] the returned data in this case. */
277 NSImage *droppedImg = [[NSImage alloc] initWithPasteboard:draggingPBoard];
278 data = droppedImg;
279 break;
280 }
282 data = [draggingPBoard propertyListForType:NSFilenamesPboardType];
283 break;
285 data = [draggingPBoard stringForType:NSPasteboardTypeString];
286 break;
287 default:
288 return NO;
289 break;
290 }
291
292 const NSPoint mouseLocation = sender.draggingLocation;
293 m_systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone,
294 m_draggedObjectType,
295 m_windowCocoa,
296 mouseLocation.x,
297 mouseLocation.y,
298 (void *)data);
299 }
300 return YES;
301}
302
303@end
304
305/* NSView for handling input and drawing. */
306#define COCOA_VIEW_CLASS CocoaOpenGLView
307#define COCOA_VIEW_BASE_CLASS NSOpenGLView
309#undef COCOA_VIEW_CLASS
310#undef COCOA_VIEW_BASE_CLASS
311
312#define COCOA_VIEW_CLASS CocoaMetalView
313#define COCOA_VIEW_BASE_CLASS NSView
315#undef COCOA_VIEW_CLASS
316#undef COCOA_VIEW_BASE_CLASS
317
318/* --------------------------------------------------------------------
319 * Initialization / Finalization.
320 */
321
323 const char *title,
325 int32_t bottom,
326 uint32_t width,
327 uint32_t height,
330 const bool stereoVisual,
331 bool is_debug,
332 bool is_dialog,
333 GHOST_WindowCocoa *parentWindow,
334 const GHOST_GPUDevice &preferred_device)
335 : GHOST_Window(width, height, state, stereoVisual, false),
336 m_openGLView(nil),
337 m_metalView(nil),
338 m_metalLayer(nil),
342 m_debug_context(is_debug),
343 m_is_dialog(is_dialog),
344 m_preferred_device(preferred_device)
345{
346 m_fullScreen = false;
347
348 @autoreleasepool {
349 /* Create the window. */
350 NSRect rect;
351 rect.origin.x = left;
352 rect.origin.y = bottom;
353 rect.size.width = width;
354 rect.size.height = height;
355
356 NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
357 NSWindowStyleMaskResizable;
358 if (!is_dialog) {
359 styleMask |= NSWindowStyleMaskMiniaturizable;
360 }
361
362 m_window = [[BlenderWindow alloc] initWithSystemCocoa:systemCocoa
363 windowCocoa:this
364 contentRect:rect
365 styleMask:styleMask
366 backing:NSBackingStoreBuffered
367 defer:NO];
368 /* By default, AppKit repositions the window in the context of the current "mainMonitor"
369 * (the monitor which has focus), bypass this by forcing the window back into its correct
370 * position. Since we use global screen coordinate indexed on the first, primary screen.
371 */
372 [m_window setFrameOrigin:NSMakePoint(left, bottom)];
373
374 /* Forbid to resize the window below the blender defined minimum one. */
375 const NSSize minSize = {320, 240};
376 m_window.contentMinSize = minSize;
377
378 /* Create NSView inside the window. */
379 id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
380 NSView *view;
381
382 if (metalDevice) {
383 /* Create metal layer and view if supported. */
384 m_metalLayer = [[CAMetalLayer alloc] init];
385 m_metalLayer.edgeAntialiasingMask = 0;
386 m_metalLayer.masksToBounds = NO;
387 m_metalLayer.opaque = YES;
388 m_metalLayer.framebufferOnly = YES;
389 m_metalLayer.presentsWithTransaction = NO;
390 [m_metalLayer removeAllAnimations];
391 m_metalLayer.device = metalDevice;
392
393 if (type == GHOST_kDrawingContextTypeMetal) {
394 /* Enable EDR support. This is done by:
395 * 1. Using a floating point render target, so that values outside 0..1 can be used
396 * 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1
397 * 3. Setting the extended sRGB color space so that the OS knows how to interpret the
398 * values.
399 */
400 m_metalLayer.wantsExtendedDynamicRangeContent = YES;
401 m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float;
402 const CFStringRef name = kCGColorSpaceExtendedSRGB;
403 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name);
404 m_metalLayer.colorspace = colorspace;
405 CGColorSpaceRelease(colorspace);
406 }
407
408 m_metalView = [[CocoaMetalView alloc] initWithSystemCocoa:systemCocoa
409 windowCocoa:this
410 frame:rect];
411 m_metalView.wantsLayer = YES;
414 }
415 else {
416 /* Fall back to OpenGL view if there is no Metal support. */
417 m_openGLView = [[CocoaOpenGLView alloc] initWithSystemCocoa:systemCocoa
418 windowCocoa:this
419 frame:rect];
421 }
422
423 if (m_systemCocoa->m_nativePixel) {
424 /* Needs to happen early when building with the 10.14 SDK, otherwise
425 * has no effect until resizing the window. */
426 if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
427 view.wantsBestResolutionOpenGLSurface = YES;
428 }
429 }
430
431 m_window.contentView = view;
432 m_window.initialFirstResponder = view;
433
434 [m_window makeKeyAndOrderFront:nil];
435
439
440 setTitle(title);
441
443
444 BlenderWindowDelegate *windowDelegate = [[BlenderWindowDelegate alloc]
445 initWithSystemCocoa:systemCocoa
446 windowCocoa:this];
447 m_window.delegate = windowDelegate;
448
449 m_window.acceptsMouseMovedEvents = YES;
450
451 NSView *contentview = m_window.contentView;
452 contentview.allowedTouchTypes = (NSTouchTypeMaskDirect | NSTouchTypeMaskIndirect);
453
454 [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
455 NSPasteboardTypeString,
456 NSPasteboardTypeTIFF,
457 nil]];
458
459 if (is_dialog && parentWindow) {
460 [parentWindow->getViewWindow() addChildWindow:m_window ordered:NSWindowAbove];
461 m_window.collectionBehavior = NSWindowCollectionBehaviorFullScreenAuxiliary;
462 }
463 else {
464 m_window.collectionBehavior = NSWindowCollectionBehaviorFullScreenPrimary;
465 }
466
469 }
470
472 }
473}
474
476{
477 @autoreleasepool {
478 if (m_customCursor) {
479 [m_customCursor release];
480 m_customCursor = nil;
481 }
482
484
485 if (m_openGLView) {
486 [m_openGLView release];
487 m_openGLView = nil;
488 }
489 if (m_metalView) {
490 [m_metalView release];
491 m_metalView = nil;
492 }
493 if (m_metalLayer) {
494 [m_metalLayer release];
495 m_metalLayer = nil;
496 }
497
498 if (m_window) {
499 [m_window close];
500 }
501
502 /* Check for other blender opened windows and make the front-most key
503 * NOTE: for some reason the closed window is still in the list. */
504 NSArray *windowsList = [NSApp orderedWindows];
505 for (int a = 0; a < [windowsList count]; a++) {
506 if (m_window != (BlenderWindow *)[windowsList objectAtIndex:a]) {
507 [[windowsList objectAtIndex:a] makeKeyWindow];
508 break;
509 }
510 }
511 m_window = nil;
512 }
513}
514
515/* --------------------------------------------------------------------
516 * Accessors.
517 */
518
520{
522 return GHOST_Window::getValid() && m_window != nullptr && view != nullptr;
523}
524
526{
527 return (void *)m_window;
528}
529
530void GHOST_WindowCocoa::setTitle(const char *title)
531{
532 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid");
533
534 @autoreleasepool {
535 NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding];
536 m_window.title = windowTitle;
537
538 [windowTitle release];
539 }
540}
541
543{
544 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid");
545
546 std::string title;
547 @autoreleasepool {
548 NSString *windowTitle = m_window.title;
549 if (windowTitle != nil) {
550 title = windowTitle.UTF8String;
551 }
552 }
553 return title;
554}
555
557{
558 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setAssociatedFile(): window invalid");
559
560 @autoreleasepool {
561 NSString *associatedFileName = [[[NSString alloc] initWithCString:filepath
562 encoding:NSUTF8StringEncoding]
563 autorelease];
564
565 m_window.representedFilename = associatedFileName;
566 }
567
568 return GHOST_kSuccess;
569}
570
572{
573 @autoreleasepool {
575 const float *background_color = m_windowDecorationStyleSettings.colored_titlebar_bg_color;
576
577 /* Title-bar background color. */
578 m_window.backgroundColor = [NSColor colorWithRed:background_color[0]
579 green:background_color[1]
580 blue:background_color[2]
581 alpha:1.0];
582
583 /* Title-bar foreground color.
584 * Use the value component of the title-bar background's HSV representation to determine
585 * whether we should use the macOS dark or light title-bar text appearance. With values below
586 * 0.5 considered as dark themes, and values above 0.5 considered as light themes.
587 */
588 const float hsv_v = MAX(background_color[0], MAX(background_color[1], background_color[2]));
589
590 const NSAppearanceName win_appearance = hsv_v > 0.5 ? NSAppearanceNameVibrantLight :
591 NSAppearanceNameVibrantDark;
592
593 m_window.appearance = [NSAppearance appearanceNamed:win_appearance];
594 m_window.titlebarAppearsTransparent = YES;
595 }
596 else {
597 m_window.titlebarAppearsTransparent = NO;
598 }
599 }
600 return GHOST_kSuccess;
601}
602
604{
605 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid");
606
607 @autoreleasepool {
608 /* All coordinates are based off the primary screen. */
609 const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
610 const NSRect windowFrame = m_window.frame;
611
612 /* Flip the Y axis, from bottom left coordinate to top left, which is the expected coordinate
613 * return format for GHOST, even though the Window Manager later reflips it to bottom-left
614 * this is the expected coordinate system for all GHOST backends
615 */
616
617 const int32_t screenMaxY = screenFrame.origin.y + screenFrame.size.height;
618
619 /* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
620 * as expected by GHOST. */
621 bounds.m_b = screenMaxY - windowFrame.origin.y;
622 bounds.m_t = screenMaxY - windowFrame.origin.y - windowFrame.size.height;
623
624 bounds.m_l = windowFrame.origin.x;
625 bounds.m_r = windowFrame.origin.x + windowFrame.size.width;
626 }
627}
628
630{
631 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid");
632
633 @autoreleasepool {
634 /* All coordinates are based off the primary screen. */
635 const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
636 /* Screen Content Rectangle (excluding Menu Bar and Dock). */
637 const NSRect screenContentRect = [NSWindow contentRectForFrameRect:screenFrame
638 styleMask:[m_window styleMask]];
639
640 const NSRect windowFrame = m_window.frame;
641 /* Window Content Rectangle (excluding Titlebar and borders) */
642 const NSRect windowContentRect = [m_window contentRectForFrameRect:windowFrame];
643
644 const int32_t screenMaxY = screenContentRect.origin.y + screenContentRect.size.height;
645
646 /* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
647 * as expected by GHOST. */
648 bounds.m_b = screenMaxY - windowContentRect.origin.y;
649 bounds.m_t = screenMaxY - windowContentRect.origin.y - windowContentRect.size.height;
650
651 bounds.m_l = windowContentRect.origin.x;
652 bounds.m_r = windowContentRect.origin.x + windowContentRect.size.width;
653 }
654}
655
657{
658 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid");
659
660 @autoreleasepool {
661 GHOST_Rect cBnds;
662 getClientBounds(cBnds);
663
664 if ((uint32_t(cBnds.getWidth())) != width) {
665 const NSSize size = {(CGFloat)width, (CGFloat)cBnds.getHeight()};
666 [m_window setContentSize:size];
667 }
668 }
669 return GHOST_kSuccess;
670}
671
673{
674 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid");
675
676 @autoreleasepool {
677 GHOST_Rect cBnds;
678 getClientBounds(cBnds);
679
680 if ((uint32_t(cBnds.getHeight())) != height) {
681 const NSSize size = {(CGFloat)cBnds.getWidth(), (CGFloat)height};
682 [m_window setContentSize:size];
683 }
684 }
685 return GHOST_kSuccess;
686}
687
688GHOST_TSuccess GHOST_WindowCocoa::setClientSize(uint32_t width, uint32_t height)
689{
690 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid");
691
692 @autoreleasepool {
693 GHOST_Rect cBnds;
694 getClientBounds(cBnds);
695 if (((uint32_t(cBnds.getWidth())) != width) || ((uint32_t(cBnds.getHeight())) != height)) {
696 const NSSize size = {(CGFloat)width, (CGFloat)height};
697 [m_window setContentSize:size];
698 }
699 }
700 return GHOST_kSuccess;
701}
702
704{
705 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid");
706
707 @autoreleasepool {
708 NSUInteger masks = m_window.styleMask;
709
710 if (masks & NSWindowStyleMaskFullScreen) {
711 /* Lion style full-screen. */
712 if (!m_immediateDraw) {
714 }
716 }
717 if (m_window.isMiniaturized) {
719 }
720 if (m_window.isZoomed) {
722 }
723 if (m_immediateDraw) {
725 }
727 }
728}
729
731 int32_t inY,
732 int32_t &outX,
733 int32_t &outY) const
734{
735 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid");
736
737 screenToClientIntern(inX, inY, outX, outY);
738
739 /* switch y to match ghost convention */
740 GHOST_Rect cBnds;
741 getClientBounds(cBnds);
742 outY = (cBnds.getHeight() - 1) - outY;
743}
744
746 int32_t inY,
747 int32_t &outX,
748 int32_t &outY) const
749{
750 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid");
751
752 /* switch y to match ghost convention */
753 GHOST_Rect cBnds;
754 getClientBounds(cBnds);
755 inY = (cBnds.getHeight() - 1) - inY;
756
757 clientToScreenIntern(inX, inY, outX, outY);
758}
759
761 int32_t inY,
762 int32_t &outX,
763 int32_t &outY) const
764{
765 NSRect screenCoord;
766 screenCoord.origin = {(CGFloat)inX, (CGFloat)inY};
767
768 const NSRect baseCoord = [m_window convertRectFromScreen:screenCoord];
769
770 outX = baseCoord.origin.x;
771 outY = baseCoord.origin.y;
772}
773
775 int32_t inY,
776 int32_t &outX,
777 int32_t &outY) const
778{
779 NSRect baseCoord;
780 baseCoord.origin = {(CGFloat)inX, (CGFloat)inY};
781
782 const NSRect screenCoord = [m_window convertRectToScreen:baseCoord];
783
784 outX = screenCoord.origin.x;
785 outY = screenCoord.origin.y;
786}
787
789{
790 return m_window.screen;
791}
792
794{
795 /* The first element of the screens array is guaranted to be the primary screen by AppKit. */
796 return [[NSScreen screens] firstObject];
797}
798
799/* called for event, when window leaves monitor to another */
801{
803 const NSRect backingBounds = [view convertRectToBacking:[view bounds]];
804
805 GHOST_Rect rect;
806 getClientBounds(rect);
807
808 m_nativePixelSize = float(backingBounds.size.width) / float(rect.getWidth());
809}
810
819{
820 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid");
821
822 @autoreleasepool {
823 switch (state) {
825 [m_window miniaturize:nil];
826 break;
828 [m_window zoom:nil];
829 break;
830
832 const NSUInteger masks = m_window.styleMask;
833
834 if (!(masks & NSWindowStyleMaskFullScreen)) {
835 [m_window toggleFullScreen:nil];
836 }
837 break;
838 }
840 default:
841 @autoreleasepool {
842 const NSUInteger masks = m_window.styleMask;
843
844 if (masks & NSWindowStyleMaskFullScreen) {
845 /* Lion style full-screen. */
846 [m_window toggleFullScreen:nil];
847 }
848 else if (m_window.isMiniaturized) {
849 [m_window deminiaturize:nil];
850 }
851 else if (m_window.isZoomed) {
852 [m_window zoom:nil];
853 }
854 }
855 break;
856 }
857 }
858 return GHOST_kSuccess;
859}
860
862{
863 @autoreleasepool {
864 m_window.documentEdited = isUnsavedChanges;
865 }
866 return GHOST_Window::setModifiedState(isUnsavedChanges);
867}
868
870{
871 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid");
872
873 @autoreleasepool {
874 if (order == GHOST_kWindowOrderTop) {
875 [NSApp activateIgnoringOtherApps:YES];
876 [m_window makeKeyAndOrderFront:nil];
877 }
878 else {
879 NSArray *windowsList;
880
881 [m_window orderBack:nil];
882
883 /* Check for other blender opened windows and make the front-most key. */
884 windowsList = [NSApp orderedWindows];
885 if (windowsList.count) {
886 [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
887 }
888 }
889 }
890 return GHOST_kSuccess;
891}
892
893/* --------------------------------------------------------------------
894 * Drawing context.
895 */
896
898{
899 switch (type) {
900#ifdef WITH_VULKAN_BACKEND
901 case GHOST_kDrawingContextTypeVulkan: {
902 GHOST_Context *context = new GHOST_ContextVK(
904 if (context->initializeDrawingContext()) {
905 return context;
906 }
907 delete context;
908 return nullptr;
909 }
910#endif
911
912#ifdef WITH_METAL_BACKEND
913 case GHOST_kDrawingContextTypeMetal: {
914 GHOST_Context *context = new GHOST_ContextCGL(
916 if (context->initializeDrawingContext()) {
917 return context;
918 }
919 delete context;
920 return nullptr;
921 }
922#endif
923
924 default:
925 /* Unsupported backend. */
926 return nullptr;
927 }
928}
929
930/* --------------------------------------------------------------------
931 * Invalidate.
932 */
933
935{
936 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid");
937
938 @autoreleasepool {
940 view.needsDisplay = YES;
941 }
942 return GHOST_kSuccess;
943}
944
945/* --------------------------------------------------------------------
946 * Progress bar.
947 */
948
950{
951 @autoreleasepool {
952 if ((progress >= 0.0) && (progress <= 1.0)) {
953 NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)];
954
955 [dockIcon lockFocus];
956
957 [[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint
958 fromRect:NSZeroRect
959 operation:NSCompositingOperationSourceOver
960 fraction:1.0];
961
962 NSRect progressRect = {{8, 8}, {112, 14}};
963 NSBezierPath *progressPath;
964
965 /* Draw white track. */
966 [[[NSColor whiteColor] colorWithAlphaComponent:0.6] setFill];
967 progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:7 yRadius:7];
968 [progressPath fill];
969
970 /* Black progress fill. */
971 [[[NSColor blackColor] colorWithAlphaComponent:0.7] setFill];
972 progressRect = NSInsetRect(progressRect, 2, 2);
973 progressRect.size.width *= progress;
974 progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:5 yRadius:5];
975 [progressPath fill];
976
977 [dockIcon unlockFocus];
978 [NSApp setApplicationIconImage:dockIcon];
979 [dockIcon release];
980
982 }
983 }
984 return GHOST_kSuccess;
985}
986
988{
990 return GHOST_kFailure;
991 }
992 m_progressBarVisible = false;
993
994 /* Reset application icon to remove the progress bar. */
995 @autoreleasepool {
996 NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)];
997 [dockIcon lockFocus];
998 [[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint
999 fromRect:NSZeroRect
1000 operation:NSCompositingOperationSourceOver
1001 fraction:1.0];
1002 [dockIcon unlockFocus];
1003 [NSApp setApplicationIconImage:dockIcon];
1004 [dockIcon release];
1005 }
1006 return GHOST_kSuccess;
1007}
1008
1009/* --------------------------------------------------------------------
1010 * Cursor handling.
1011 */
1012
1013static NSCursor *getImageCursor(GHOST_TStandardCursor shape, NSString *name, NSPoint hotspot)
1014{
1015 static NSCursor *cursors[GHOST_kStandardCursorNumCursors] = {nullptr};
1016 static bool loaded[GHOST_kStandardCursorNumCursors] = {false};
1017
1018 const int index = int(shape);
1019 if (!loaded[index]) {
1020 /* Load image from file in application Resources folder. */
1021 @autoreleasepool {
1022 NSImage *image = [NSImage imageNamed:name];
1023 if (image != nullptr) {
1024 cursors[index] = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
1025 }
1026 }
1027
1028 loaded[index] = true;
1029 }
1030
1031 return cursors[index];
1032}
1033
1034/* busyButClickableCursor is an undocumented NSCursor API, but
1035 * has been in use since at least OS X 10.4 and through 10.9. */
1036@interface NSCursor (Undocumented)
1038@end
1039
1041{
1042 @autoreleasepool {
1043 switch (shape) {
1045 if (m_customCursor) {
1046 return m_customCursor;
1047 }
1048 else {
1049 return nullptr;
1050 }
1052 return [NSCursor disappearingItemCursor];
1054 return [NSCursor IBeamCursor];
1056 return [NSCursor crosshairCursor];
1058 return [NSCursor resizeUpDownCursor];
1060 return [NSCursor resizeLeftRightCursor];
1062 return [NSCursor resizeUpCursor];
1064 return [NSCursor resizeDownCursor];
1066 return [NSCursor resizeLeftCursor];
1068 return [NSCursor resizeRightCursor];
1070 return [NSCursor dragCopyCursor];
1072 return [NSCursor operationNotAllowedCursor];
1074 return [NSCursor openHandCursor];
1076 return [NSCursor openHandCursor];
1078 return [NSCursor closedHandCursor];
1080 return [NSCursor pointingHandCursor];
1082 return [NSCursor arrowCursor];
1084 if ([NSCursor respondsToSelector:@selector(busyButClickableCursor)]) {
1085 return [NSCursor busyButClickableCursor];
1086 }
1087 return nullptr;
1089 return getImageCursor(shape, @"knife.pdf", NSMakePoint(6, 24));
1091 return getImageCursor(shape, @"eraser.pdf", NSMakePoint(6, 24));
1093 return getImageCursor(shape, @"pen.pdf", NSMakePoint(6, 24));
1095 return getImageCursor(shape, @"eyedropper.pdf", NSMakePoint(6, 24));
1097 return getImageCursor(shape, @"zoomin.pdf", NSMakePoint(8, 7));
1099 return getImageCursor(shape, @"zoomout.pdf", NSMakePoint(8, 7));
1101 return getImageCursor(shape, @"scrollnsew.pdf", NSMakePoint(16, 16));
1103 return getImageCursor(shape, @"scrollns.pdf", NSMakePoint(16, 16));
1105 return getImageCursor(shape, @"scrollew.pdf", NSMakePoint(16, 16));
1107 return getImageCursor(shape, @"arrowup.pdf", NSMakePoint(16, 16));
1109 return getImageCursor(shape, @"arrowdown.pdf", NSMakePoint(16, 16));
1111 return getImageCursor(shape, @"arrowleft.pdf", NSMakePoint(16, 16));
1113 return getImageCursor(shape, @"arrowright.pdf", NSMakePoint(16, 16));
1115 return getImageCursor(shape, @"splitv.pdf", NSMakePoint(16, 16));
1117 return getImageCursor(shape, @"splith.pdf", NSMakePoint(16, 16));
1119 return getImageCursor(shape, @"paint_cursor_cross.pdf", NSMakePoint(16, 15));
1121 return getImageCursor(shape, @"paint_cursor_dot.pdf", NSMakePoint(16, 15));
1123 return getImageCursor(shape, @"crossc.pdf", NSMakePoint(16, 16));
1125 return getImageCursor(shape, @"handle_left.pdf", NSMakePoint(12, 14));
1127 return getImageCursor(shape, @"handle_right.pdf", NSMakePoint(10, 14));
1129 return getImageCursor(shape, @"handle_both.pdf", NSMakePoint(11, 14));
1130 default:
1131 return nullptr;
1132 }
1133 }
1134}
1135
1137{
1138 static bool systemCursorVisible = true;
1139
1140 @autoreleasepool {
1141 if (visible != systemCursorVisible) {
1142 if (visible) {
1143 [NSCursor unhide];
1144 systemCursorVisible = true;
1145 }
1146 else {
1147 [NSCursor hide];
1148 systemCursorVisible = false;
1149 }
1150 }
1151
1152 NSCursor *cursor = getStandardCursor(shape);
1153 if (cursor == nullptr) {
1155 }
1156
1157 [cursor set];
1158 }
1159}
1160
1162{
1163 return m_is_dialog;
1164}
1165
1167{
1168 @autoreleasepool {
1169 if (m_window.isVisible) {
1170 loadCursor(visible, getCursorShape());
1171 }
1172 }
1173 return GHOST_kSuccess;
1174}
1175
1177{
1178 @autoreleasepool {
1179 if (mode != GHOST_kGrabDisable) {
1180 /* No need to perform grab without warp as it is always on in OS X. */
1181 if (mode != GHOST_kGrabNormal) {
1182 @autoreleasepool {
1183 m_systemCocoa->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1184 setCursorGrabAccum(0, 0);
1185
1186 if (mode == GHOST_kGrabHide) {
1188 }
1189
1190 /* Make window key if it wasn't to get the mouse move events. */
1191 [m_window makeKeyWindow];
1192 }
1193 }
1194 }
1195 else {
1197 m_systemCocoa->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1199 }
1200
1201 /* Almost works without but important otherwise the mouse GHOST location
1202 * can be incorrect on exit. */
1203 setCursorGrabAccum(0, 0);
1204 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1205 }
1206 }
1207 return GHOST_kSuccess;
1208}
1209
1211{
1212 @autoreleasepool {
1213 if (m_window.isVisible) {
1215 }
1216 }
1217 return GHOST_kSuccess;
1218}
1219
1221{
1222 @autoreleasepool {
1224 return success;
1225 }
1226}
1227
1228/* Reverse the bits in a uint8_t */
1229#if 0
1230static uint8_t uns8ReverseBits(uint8_t ch)
1231{
1232 ch= ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
1233 ch= ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
1234 ch= ((ch >> 4) & 0x0F) | ((ch << 4) & 0xF0);
1235 return ch;
1236}
1237#endif
1238
1240static uint16_t uns16ReverseBits(uint16_t shrt)
1241{
1242 shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
1243 shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
1244 shrt = ((shrt >> 4) & 0x0F0F) | ((shrt << 4) & 0xF0F0);
1245 shrt = ((shrt >> 8) & 0x00FF) | ((shrt << 8) & 0xFF00);
1246 return shrt;
1247}
1248
1250 uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
1251{
1252 @autoreleasepool {
1253 if (m_customCursor) {
1254 [m_customCursor release];
1255 m_customCursor = nil;
1256 }
1257
1258 NSBitmapImageRep *cursorImageRep = [[NSBitmapImageRep alloc]
1259 initWithBitmapDataPlanes:nil
1260 pixelsWide:sizex
1261 pixelsHigh:sizey
1262 bitsPerSample:1
1263 samplesPerPixel:2
1264 hasAlpha:YES
1265 isPlanar:YES
1266 colorSpaceName:NSDeviceWhiteColorSpace
1267 bytesPerRow:(sizex / 8 + (sizex % 8 > 0 ? 1 : 0))
1268 bitsPerPixel:1];
1269
1270 uint16_t *cursorBitmap = (uint16_t *)cursorImageRep.bitmapData;
1271 int nbUns16 = cursorImageRep.bytesPerPlane / 2;
1272
1273 for (int y = 0; y < nbUns16; y++) {
1274#if !defined(__LITTLE_ENDIAN__)
1275 cursorBitmap[y] = uns16ReverseBits((bitmap[2 * y] << 0) | (bitmap[2 * y + 1] << 8));
1276 cursorBitmap[nbUns16 + y] = uns16ReverseBits((mask[2 * y] << 0) | (mask[2 * y + 1] << 8));
1277#else
1278 cursorBitmap[y] = uns16ReverseBits((bitmap[2 * y + 1] << 0) | (bitmap[2 * y] << 8));
1279 cursorBitmap[nbUns16 + y] = uns16ReverseBits((mask[2 * y + 1] << 0) | (mask[2 * y] << 8));
1280#endif
1281
1282 /* Flip white cursor with black outline to black cursor with white outline
1283 * to match macOS platform conventions. */
1284 if (canInvertColor) {
1285 cursorBitmap[y] = ~cursorBitmap[y];
1286 }
1287 }
1288
1289 const NSSize imSize = {(CGFloat)sizex, (CGFloat)sizey};
1290 NSImage *cursorImage = [[NSImage alloc] initWithSize:imSize];
1291 [cursorImage addRepresentation:cursorImageRep];
1292
1293 const NSPoint hotSpotPoint = {(CGFloat)(hotX), (CGFloat)(hotY)};
1294
1295 /* Foreground and background color parameter is not handled for now (10.6). */
1296 m_customCursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint];
1297
1298 [cursorImageRep release];
1299 [cursorImage release];
1300
1301 if (m_window.isVisible) {
1303 }
1304 }
1305 return GHOST_kSuccess;
1306}
1307
1308#ifdef WITH_INPUT_IME
1309void GHOST_WindowCocoa::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
1310{
1311 if (m_openGLView) {
1312 [m_openGLView beginIME:x y:y w:w h:h completed:completed];
1313 }
1314 else {
1315 [m_metalView beginIME:x y:y w:w h:h completed:completed];
1316 }
1317}
1318
1319void GHOST_WindowCocoa::endIME()
1320{
1321 if (m_openGLView) {
1322 [m_openGLView endIME];
1323 }
1324 else {
1325 [m_metalView endIME];
1326 }
1327}
1328#endif /* WITH_INPUT_IME */
static AppView * view
#define GHOST_ASSERT(x, info)
GHOST_TWindowState
@ GHOST_kWindowStateMinimized
@ GHOST_kWindowStateMaximized
@ GHOST_kWindowStateNormal
@ GHOST_kWindowStateFullScreen
GHOST_TStandardCursor
@ GHOST_kStandardCursorLeftHandle
@ GHOST_kStandardCursorHandClosed
@ GHOST_kStandardCursorHandOpen
@ GHOST_kStandardCursorZoomIn
@ GHOST_kStandardCursorVerticalSplit
@ GHOST_kStandardCursorCopy
@ GHOST_kStandardCursorWait
@ GHOST_kStandardCursorRightHandle
@ GHOST_kStandardCursorHorizontalSplit
@ GHOST_kStandardCursorTopSide
@ GHOST_kStandardCursorStop
@ GHOST_kStandardCursorCrosshair
@ GHOST_kStandardCursorCustom
@ GHOST_kStandardCursorNSEWScroll
@ GHOST_kStandardCursorLeftRight
@ GHOST_kStandardCursorPencil
@ GHOST_kStandardCursorNSScroll
@ GHOST_kStandardCursorCrosshairA
@ GHOST_kStandardCursorUpDown
@ GHOST_kStandardCursorUpArrow
@ GHOST_kStandardCursorHandPoint
@ GHOST_kStandardCursorBottomSide
@ GHOST_kStandardCursorBothHandles
@ GHOST_kStandardCursorEyedropper
@ GHOST_kStandardCursorKnife
@ GHOST_kStandardCursorMove
@ GHOST_kStandardCursorCrosshairB
@ GHOST_kStandardCursorDownArrow
@ GHOST_kStandardCursorEraser
@ GHOST_kStandardCursorDefault
@ GHOST_kStandardCursorEWScroll
@ GHOST_kStandardCursorRightSide
@ GHOST_kStandardCursorRightArrow
@ GHOST_kStandardCursorDestroy
@ GHOST_kStandardCursorCrosshairC
@ GHOST_kStandardCursorZoomOut
@ GHOST_kStandardCursorLeftSide
@ GHOST_kStandardCursorText
@ GHOST_kStandardCursorLeftArrow
@ GHOST_kEventWindowClose
@ GHOST_kEventWindowMove
@ GHOST_kEventWindowSize
@ GHOST_kEventDraggingDropDone
@ GHOST_kEventDraggingExited
@ GHOST_kEventNativeResolutionChange
@ GHOST_kEventDraggingUpdated
@ GHOST_kEventDraggingEntered
@ GHOST_kEventWindowActivate
@ GHOST_kEventWindowUpdate
@ GHOST_kEventWindowDeactivate
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
GHOST_TDrawingContextType
GHOST_TWindowOrder
@ GHOST_kWindowOrderTop
GHOST_TSuccess
Definition GHOST_Types.h:80
@ GHOST_kFailure
Definition GHOST_Types.h:80
@ GHOST_kSuccess
Definition GHOST_Types.h:80
GHOST_TGrabCursorMode
@ GHOST_kGrabDisable
@ GHOST_kGrabHide
@ GHOST_kGrabNormal
GHOST_TDragnDropTypes
@ GHOST_kDragnDropTypeUnknown
@ GHOST_kDragnDropTypeFilenames
@ GHOST_kDragnDropTypeBitmap
@ GHOST_kDragnDropTypeString
@ GHOST_kDecorationColoredTitleBar
static NSCursor * getImageCursor(GHOST_TStandardCursor shape, NSString *name, NSPoint hotspot)
static uint16_t uns16ReverseBits(uint16_t shrt)
static uint8_t uns8ReverseBits(uint8_t ch)
float progress
Definition WM_types.hh:1019
BMesh const char void * data
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
NSCursor * busyButClickableCursor()
virtual int32_t getHeight() const
virtual int32_t getWidth() const
bool isDialog() const override
GHOST_TSuccess setProgressBar(float progress) override
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override
GHOST_SystemCocoa * m_systemCocoa
GHOST_TSuccess setState(GHOST_TWindowState state) override
std::string getTitle() const override
BlenderWindow * m_window
GHOST_TSuccess setClientHeight(uint32_t height) override
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
NSScreen * getScreen() const
void setTitle(const char *title) override
GHOST_TSuccess setModifiedState(bool isUnsavedChanges) override
GHOST_TSuccess invalidate() override
CocoaOpenGLView * m_openGLView
CAMetalLayer * m_metalLayer
GHOST_TSuccess endProgressBar() override
NSCursor * getStandardCursor(GHOST_TStandardCursor cursor) const
GHOST_TWindowState getState() const override
GHOST_TSuccess setClientWidth(uint32_t width) override
GHOST_GPUDevice m_preferred_device
GHOST_TabletData m_tablet
GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, const char *title, int32_t left, int32_t bottom, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, bool is_debug, bool dialog, GHOST_WindowCocoa *parentWindow, const GHOST_GPUDevice &preferred_device)
GHOST_TSuccess applyWindowDecorationStyle() override
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor shape) override
void clientToScreenIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
void * getOSWindow() const override
void getClientBounds(GHOST_Rect &bounds) const override
void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
void getWindowBounds(GHOST_Rect &bounds) const override
GHOST_Context * newDrawingContext(GHOST_TDrawingContextType type) override
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override
GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) override
static NSScreen * getPrimaryScreen()
GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override
void screenToClientIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
CocoaMetalView * m_metalView
GHOST_TSuccess setPath(const char *filepath) override
bool getValid() const override
GHOST_TSuccess setWindowCursorVisibility(bool visible) override
void loadCursor(bool visible, GHOST_TStandardCursor cursor) const
GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override
GHOST_TWindowDecorationStyleFlags m_windowDecorationStyleFlags
GHOST_Rect m_cursorGrabBounds
GHOST_WindowDecorationStyleSettings m_windowDecorationStyleSettings
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_TGrabCursorMode m_cursorGrab
bool m_wantStereoVisual
int32_t m_cursorGrabInitPos[2]
GHOST_TStandardCursor getCursorShape() const override
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override
GHOST_TSuccess releaseNativeHandles()
bool getValid() const override
bool getCursorVisibility() const override
GHOST_TSuccess activateDrawingContext() override
GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, const bool wantStereoVisual=false, const bool exclusive=false)
float m_nativePixelSize
GHOST_TSuccess updateDrawingContext()
GHOST_TSuccess setModifiedState(bool isUnsavedChanges) override
bool m_progressBarVisible
GHOST_SystemCocoa * systemCocoa
GHOST_WindowCocoa * windowCocoa
GHOST_TDragnDropTypes draggedObjectType
GHOST_SystemCocoa * systemCocoa
GHOST_WindowCocoa * windowCocoa
static char ** types
Definition makesdna.cc:71
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong state[N]
static int left