Blender V5.0
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_ContextMTL.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 = system_cocoa_;
55@synthesize windowCocoa = window_cocoa_;
56
57- (instancetype)initWithSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
58 windowCocoa:(GHOST_WindowCocoa *)winCocoa
59{
60 self = [super init];
61
62 if (self) {
63 system_cocoa_ = sysCocoa;
64 window_cocoa_ = winCocoa;
65 }
66
67 return self;
68}
69
70- (void)windowDidBecomeKey:(NSNotification *)notification
71{
72 system_cocoa_->handleWindowEvent(GHOST_kEventWindowActivate, window_cocoa_);
73 /* Workaround for broken app-switching when combining Command-Tab and mission-control. */
74 [(NSWindow *)window_cocoa_->getOSWindow() orderFrontRegardless];
75}
76
77- (void)windowDidResignKey:(NSNotification *)notification
78{
79 system_cocoa_->handleWindowEvent(GHOST_kEventWindowDeactivate, window_cocoa_);
80}
81
82- (void)windowDidExpose:(NSNotification *)notification
83{
84 system_cocoa_->handleWindowEvent(GHOST_kEventWindowUpdate, window_cocoa_);
85}
86
87- (void)windowDidMove:(NSNotification *)notification
88{
89 system_cocoa_->handleWindowEvent(GHOST_kEventWindowMove, window_cocoa_);
90}
91
92- (void)windowWillMove:(NSNotification *)notification
93{
94 system_cocoa_->handleWindowEvent(GHOST_kEventWindowMove, window_cocoa_);
95}
96
97- (void)windowWillEnterFullScreen:(NSNotification *)notification
98{
99 window_cocoa_->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 system_cocoa_->handleWindowEvent(GHOST_kEventWindowSize, window_cocoa_);
108
109 window_cocoa_->setImmediateDraw(false);
110}
111
112- (void)windowWillExitFullScreen:(NSNotification *)notification
113{
114 window_cocoa_->setImmediateDraw(true);
115}
116
117- (void)windowDidExitFullScreen:(NSNotification *)notification
118{
119 /* See comment for windowWillEnterFullScreen. */
120 system_cocoa_->handleWindowEvent(GHOST_kEventWindowSize, window_cocoa_);
121 window_cocoa_->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 system_cocoa_->handleWindowEvent(GHOST_kEventWindowSize, window_cocoa_);
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 system_cocoa_->dispatchEvents();
137 }
138}
139
140- (void)windowDidChangeBackingProperties:(NSNotification *)notification
141{
142 system_cocoa_->handleWindowEvent(GHOST_kEventNativeResolutionChange, window_cocoa_);
143 system_cocoa_->handleWindowEvent(GHOST_kEventWindowSize, window_cocoa_);
144}
145
146- (BOOL)windowShouldClose:(id)sender;
147{
148 /* Let Blender close the window rather than closing immediately. */
149 system_cocoa_->handleWindowEvent(GHOST_kEventWindowClose, window_cocoa_);
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 = system_cocoa_;
173@synthesize windowCocoa = window_cocoa_;
174@synthesize draggedObjectType = dragged_object_type_;
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 system_cocoa_ = sysCocoa;
190 window_cocoa_ = 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 (window_cocoa_->isDialog() || !system_cocoa_->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 dragged_object_type_ = GHOST_kDragnDropTypeBitmap;
209 }
210 else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) {
211 dragged_object_type_ = GHOST_kDragnDropTypeFilenames;
212 }
213 else if ([[draggingPBoard types] containsObject:NSPasteboardTypeString]) {
214 dragged_object_type_ = GHOST_kDragnDropTypeString;
215 }
216 else {
217 return NSDragOperationNone;
218 }
219
220 const NSPoint mouseLocation = sender.draggingLocation;
221 window_cocoa_->setAcceptDragOperation(TRUE); /* Drag operation is accepted by default. */
222 system_cocoa_->handleDraggingEvent(GHOST_kEventDraggingEntered,
223 dragged_object_type_,
224 window_cocoa_,
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 system_cocoa_->handleDraggingEvent(GHOST_kEventDraggingUpdated,
242 dragged_object_type_,
243 window_cocoa_,
244 mouseLocation.x,
245 mouseLocation.y,
246 nil);
247 return window_cocoa_->canAcceptDragOperation() ? NSDragOperationCopy : NSDragOperationNone;
248}
249
250- (void)draggingExited:(id<NSDraggingInfo>)sender
251{
252 system_cocoa_->handleDraggingEvent(
253 GHOST_kEventDraggingExited, dragged_object_type_, window_cocoa_, 0, 0, nil);
254 dragged_object_type_ = GHOST_kDragnDropTypeUnknown;
255}
256
257- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender
258{
259 if (window_cocoa_->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 (dragged_object_type_) {
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 system_cocoa_->handleDraggingEvent(GHOST_kEventDraggingDropDone,
294 dragged_object_type_,
295 window_cocoa_,
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 GHOST_ContextParams &context_params,
331 bool is_dialog,
332 GHOST_WindowCocoa *parent_window,
333 const GHOST_GPUDevice &preferred_device)
334 : GHOST_Window(width, height, state, context_params, false),
335 opengl_view_(nil),
336 metal_view_(nil),
337 metal_layer_(nil),
341 is_dialog_(is_dialog),
342 preferred_device_(preferred_device)
343{
344 full_screen_ = false;
345
346 @autoreleasepool {
347 /* Create the window. */
348 NSRect rect;
349 rect.origin.x = left;
350 rect.origin.y = bottom;
351 rect.size.width = width;
352 rect.size.height = height;
353
354 NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
355 NSWindowStyleMaskResizable;
356 if (!is_dialog) {
357 styleMask |= NSWindowStyleMaskMiniaturizable;
358 }
359
360 window_ = [[BlenderWindow alloc] initWithSystemCocoa:systemCocoa
361 windowCocoa:this
362 contentRect:rect
363 styleMask:styleMask
364 backing:NSBackingStoreBuffered
365 defer:NO];
366 /* By default, AppKit repositions the window in the context of the current "mainMonitor"
367 * (the monitor which has focus), bypass this by forcing the window back into its correct
368 * position. Since we use global screen coordinate indexed on the first, primary screen.
369 */
370 [window_ setFrameOrigin:NSMakePoint(left, bottom)];
371
372 /* Forbid to resize the window below the blender defined minimum one. */
373 const NSSize minSize = {320, 240};
374 window_.contentMinSize = minSize;
375
376 /* Create NSView inside the window. */
377 id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
378 NSView *view;
379
380 if (metalDevice) {
381 /* Create metal layer and view if supported. */
382 metal_layer_ = [[CAMetalLayer alloc] init];
383 metal_layer_.edgeAntialiasingMask = 0;
384 metal_layer_.masksToBounds = NO;
385 metal_layer_.opaque = YES;
386 metal_layer_.framebufferOnly = YES;
387 metal_layer_.presentsWithTransaction = NO;
388 [metal_layer_ removeAllAnimations];
389 metal_layer_.device = metalDevice;
390
391 if (type == GHOST_kDrawingContextTypeMetal) {
392 /* Enable EDR support. This is done by:
393 * 1. Using a floating point render target, so that values outside 0..1 can be used
394 * 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1
395 * 3. Setting the extended sRGB color space so that the OS knows how to interpret the
396 * values.
397 */
398 metal_layer_.wantsExtendedDynamicRangeContent = YES;
399 metal_layer_.pixelFormat = MTLPixelFormatRGBA16Float;
400 const CFStringRef name = kCGColorSpaceExtendedSRGB;
401 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name);
402 metal_layer_.colorspace = colorspace;
403 CGColorSpaceRelease(colorspace);
404
405 /* For Blender to know if this window supports HDR. */
406 hdr_info_.hdr_enabled = true;
407 hdr_info_.wide_gamut_enabled = true;
408 hdr_info_.sdr_white_level = 1.0f;
409 }
410
411 metal_view_ = [[CocoaMetalView alloc] initWithSystemCocoa:systemCocoa
412 windowCocoa:this
413 frame:rect];
414 metal_view_.wantsLayer = YES;
417 }
418 else {
419 /* Fall back to OpenGL view if there is no Metal support. */
420 opengl_view_ = [[CocoaOpenGLView alloc] initWithSystemCocoa:systemCocoa
421 windowCocoa:this
422 frame:rect];
424 }
425
426 if (system_cocoa_->native_pixel_) {
427 /* Needs to happen early when building with the 10.14 SDK, otherwise
428 * has no effect until resizing the window. */
429 if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
430 view.wantsBestResolutionOpenGLSurface = YES;
431 }
432 }
433
434 window_.contentView = view;
435 window_.initialFirstResponder = view;
436
437 [window_ makeKeyAndOrderFront:nil];
438
442
443 setTitle(title);
444
446
447 BlenderWindowDelegate *windowDelegate = [[BlenderWindowDelegate alloc]
448 initWithSystemCocoa:systemCocoa
449 windowCocoa:this];
450 window_.delegate = windowDelegate;
451
452 window_.acceptsMouseMovedEvents = YES;
453
454 NSView *contentview = window_.contentView;
455 contentview.allowedTouchTypes = (NSTouchTypeMaskDirect | NSTouchTypeMaskIndirect);
456
457 [window_ registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
458 NSPasteboardTypeString,
459 NSPasteboardTypeTIFF,
460 nil]];
461
462 if (is_dialog && parent_window) {
463 [parent_window->getViewWindow() addChildWindow:window_ ordered:NSWindowAbove];
464 window_.collectionBehavior = NSWindowCollectionBehaviorFullScreenAuxiliary;
465 }
466 else {
467 window_.collectionBehavior = NSWindowCollectionBehaviorFullScreenPrimary;
468 }
469
472 }
473
475 }
476}
477
479{
480 @autoreleasepool {
481 if (custom_cursor_) {
482 [custom_cursor_ release];
483 custom_cursor_ = nil;
484 }
485
487
488 if (opengl_view_) {
489 [opengl_view_ release];
490 opengl_view_ = nil;
491 }
492 if (metal_view_) {
493 [metal_view_ release];
494 metal_view_ = nil;
495 }
496 if (metal_layer_) {
497 [metal_layer_ release];
498 metal_layer_ = nil;
499 }
500
501 if (window_) {
502 [window_ close];
503 }
504
505 /* Check for other blender opened windows and make the front-most key
506 * NOTE: for some reason the closed window is still in the list. */
507 NSArray *windowsList = [NSApp orderedWindows];
508 for (int a = 0; a < [windowsList count]; a++) {
509 if (window_ != (BlenderWindow *)[windowsList objectAtIndex:a]) {
510 [[windowsList objectAtIndex:a] makeKeyWindow];
511 break;
512 }
513 }
514 window_ = nil;
515 }
516}
517
518/* --------------------------------------------------------------------
519 * Accessors.
520 */
521
523{
525 return GHOST_Window::getValid() && window_ != nullptr && view != nullptr;
526}
527
529{
530 return (void *)window_;
531}
532
533void GHOST_WindowCocoa::setTitle(const char *title)
534{
535 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid");
536
537 @autoreleasepool {
538 NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding];
539 window_.title = windowTitle;
540
541 [windowTitle release];
542 }
543}
544
546{
547 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid");
548
549 std::string title;
550 @autoreleasepool {
551 NSString *windowTitle = window_.title;
552 if (windowTitle != nil) {
553 title = windowTitle.UTF8String;
554 }
555 }
556 return title;
557}
558
560{
561 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setAssociatedFile(): window invalid");
562
563 @autoreleasepool {
564 NSString *associatedFileName = [[[NSString alloc] initWithCString:filepath
565 encoding:NSUTF8StringEncoding]
566 autorelease];
567
568 window_.representedFilename = associatedFileName;
569 }
570
571 return GHOST_kSuccess;
572}
573
575{
576 @autoreleasepool {
578 const float *background_color = window_decoration_style_settings_.colored_titlebar_bg_color;
579
580 /* Title-bar background color. */
581 window_.backgroundColor = [NSColor colorWithRed:background_color[0]
582 green:background_color[1]
583 blue:background_color[2]
584 alpha:1.0];
585
586 /* Title-bar foreground color.
587 * Use the value component of the title-bar background's HSV representation to determine
588 * whether we should use the macOS dark or light title-bar text appearance. With values below
589 * 0.5 considered as dark themes, and values above 0.5 considered as light themes.
590 */
591 const float hsv_v = MAX(background_color[0], MAX(background_color[1], background_color[2]));
592
593 const NSAppearanceName win_appearance = hsv_v > 0.5 ? NSAppearanceNameVibrantLight :
594 NSAppearanceNameVibrantDark;
595
596 window_.appearance = [NSAppearance appearanceNamed:win_appearance];
597 window_.titlebarAppearsTransparent = YES;
598 }
599 else {
600 window_.titlebarAppearsTransparent = NO;
601 }
602 }
603 return GHOST_kSuccess;
604}
605
607{
608 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid");
609
610 @autoreleasepool {
611 /* All coordinates are based off the primary screen. */
612 const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
613 const NSRect windowFrame = window_.frame;
614
615 /* Flip the Y axis, from bottom left coordinate to top left, which is the expected coordinate
616 * return format for GHOST, even though the Window Manager later reflips it to bottom-left
617 * this is the expected coordinate system for all GHOST backends
618 */
619
620 const int32_t screenMaxY = screenFrame.origin.y + screenFrame.size.height;
621
622 /* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
623 * as expected by GHOST. */
624 bounds.b_ = screenMaxY - windowFrame.origin.y;
625 bounds.t_ = screenMaxY - windowFrame.origin.y - windowFrame.size.height;
626
627 bounds.l_ = windowFrame.origin.x;
628 bounds.r_ = windowFrame.origin.x + windowFrame.size.width;
629 }
630}
631
633{
634 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid");
635
636 @autoreleasepool {
637 /* All coordinates are based off the primary screen. */
638 const NSRect screenFrame = [getPrimaryScreen() visibleFrame];
639 /* Screen Content Rectangle (excluding Menu Bar and Dock). */
640 const NSRect screenContentRect = [NSWindow contentRectForFrameRect:screenFrame
641 styleMask:[window_ styleMask]];
642
643 const NSRect windowFrame = window_.frame;
644 /* Window Content Rectangle (excluding Titlebar and borders) */
645 const NSRect windowContentRect = [window_ contentRectForFrameRect:windowFrame];
646
647 const int32_t screenMaxY = screenContentRect.origin.y + screenContentRect.size.height;
648
649 /* Flip the coordinates vertically from a bottom-left origin to a top-left origin,
650 * as expected by GHOST. */
651 bounds.b_ = screenMaxY - windowContentRect.origin.y;
652 bounds.t_ = screenMaxY - windowContentRect.origin.y - windowContentRect.size.height;
653
654 bounds.l_ = windowContentRect.origin.x;
655 bounds.r_ = windowContentRect.origin.x + windowContentRect.size.width;
656 }
657}
658
660{
661 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid");
662
663 @autoreleasepool {
664 GHOST_Rect cBnds;
665 getClientBounds(cBnds);
666
667 if ((uint32_t(cBnds.getWidth())) != width) {
668 const NSSize size = {(CGFloat)width, (CGFloat)cBnds.getHeight()};
669 [window_ setContentSize:size];
670 }
671 }
672 return GHOST_kSuccess;
673}
674
676{
677 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid");
678
679 @autoreleasepool {
680 GHOST_Rect cBnds;
681 getClientBounds(cBnds);
682
683 if ((uint32_t(cBnds.getHeight())) != height) {
684 const NSSize size = {(CGFloat)cBnds.getWidth(), (CGFloat)height};
685 [window_ setContentSize:size];
686 }
687 }
688 return GHOST_kSuccess;
689}
690
691GHOST_TSuccess GHOST_WindowCocoa::setClientSize(uint32_t width, uint32_t height)
692{
693 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid");
694
695 @autoreleasepool {
696 GHOST_Rect cBnds;
697 getClientBounds(cBnds);
698 if (((uint32_t(cBnds.getWidth())) != width) || ((uint32_t(cBnds.getHeight())) != height)) {
699 const NSSize size = {(CGFloat)width, (CGFloat)height};
700 [window_ setContentSize:size];
701 }
702 }
703 return GHOST_kSuccess;
704}
705
707{
708 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid");
709
710 @autoreleasepool {
711 NSUInteger masks = window_.styleMask;
712
713 if (masks & NSWindowStyleMaskFullScreen) {
714 /* Lion style full-screen. */
715 if (!immediate_draw_) {
717 }
719 }
720 if (window_.isMiniaturized) {
722 }
723 if (window_.isZoomed) {
725 }
726 if (immediate_draw_) {
728 }
730 }
731}
732
734 int32_t inY,
735 int32_t &outX,
736 int32_t &outY) const
737{
738 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid");
739
740 screenToClientIntern(inX, inY, outX, outY);
741
742 /* switch y to match ghost convention */
743 GHOST_Rect cBnds;
744 getClientBounds(cBnds);
745 outY = (cBnds.getHeight() - 1) - outY;
746}
747
749 int32_t inY,
750 int32_t &outX,
751 int32_t &outY) const
752{
753 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid");
754
755 /* switch y to match ghost convention */
756 GHOST_Rect cBnds;
757 getClientBounds(cBnds);
758 inY = (cBnds.getHeight() - 1) - inY;
759
760 clientToScreenIntern(inX, inY, outX, outY);
761}
762
764 int32_t inY,
765 int32_t &outX,
766 int32_t &outY) const
767{
768 NSRect screenCoord;
769 screenCoord.origin = {(CGFloat)inX, (CGFloat)inY};
770
771 const NSRect baseCoord = [window_ convertRectFromScreen:screenCoord];
772
773 outX = baseCoord.origin.x;
774 outY = baseCoord.origin.y;
775}
776
778 int32_t inY,
779 int32_t &outX,
780 int32_t &outY) const
781{
782 NSRect baseCoord;
783 baseCoord.origin = {(CGFloat)inX, (CGFloat)inY};
784
785 const NSRect screenCoord = [window_ convertRectToScreen:baseCoord];
786
787 outX = screenCoord.origin.x;
788 outY = screenCoord.origin.y;
789}
790
792{
793 return window_.screen;
794}
795
797{
798 /* The first element of the screens array is guaranted to be the primary screen by AppKit. */
799 return [[NSScreen screens] firstObject];
800}
801
802/* called for event, when window leaves monitor to another */
804{
806 const NSRect backingBounds = [view convertRectToBacking:[view bounds]];
807
808 GHOST_Rect rect;
809 getClientBounds(rect);
810
811 native_pixel_size_ = float(backingBounds.size.width) / float(rect.getWidth());
812}
813
822{
823 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid");
824
825 @autoreleasepool {
826 switch (state) {
828 [window_ miniaturize:nil];
829 break;
831 [window_ zoom:nil];
832 break;
833
835 const NSUInteger masks = window_.styleMask;
836
837 if (!(masks & NSWindowStyleMaskFullScreen)) {
838 [window_ toggleFullScreen:nil];
839 }
840 break;
841 }
843 default:
844 @autoreleasepool {
845 const NSUInteger masks = window_.styleMask;
846
847 if (masks & NSWindowStyleMaskFullScreen) {
848 /* Lion style full-screen. */
849 [window_ toggleFullScreen:nil];
850 }
851 else if (window_.isMiniaturized) {
852 [window_ deminiaturize:nil];
853 }
854 else if (window_.isZoomed) {
855 [window_ zoom:nil];
856 }
857 }
858 break;
859 }
860 }
861 return GHOST_kSuccess;
862}
863
865{
866 @autoreleasepool {
867 window_.documentEdited = is_unsaved_changes;
868 }
869 return GHOST_Window::setModifiedState(is_unsaved_changes);
870}
871
873{
874 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid");
875
876 @autoreleasepool {
877 if (order == GHOST_kWindowOrderTop) {
878 [NSApp activateIgnoringOtherApps:YES];
879 [window_ makeKeyAndOrderFront:nil];
880 }
881 else {
882 NSArray *windowsList;
883
884 [window_ orderBack:nil];
885
886 /* Check for other blender opened windows and make the front-most key. */
887 windowsList = [NSApp orderedWindows];
888 if (windowsList.count) {
889 [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
890 }
891 }
892 }
893 return GHOST_kSuccess;
894}
895
896/* --------------------------------------------------------------------
897 * Drawing context.
898 */
899
901{
902 switch (type) {
903#ifdef WITH_VULKAN_BACKEND
904 case GHOST_kDrawingContextTypeVulkan: {
905 GHOST_Context *context = new GHOST_ContextVK(
907 if (context->initializeDrawingContext()) {
908 return context;
909 }
910 delete context;
911 return nullptr;
912 }
913#endif
914
915#ifdef WITH_METAL_BACKEND
916 case GHOST_kDrawingContextTypeMetal: {
917 GHOST_Context *context = new GHOST_ContextMTL(
919 if (context->initializeDrawingContext()) {
920 return context;
921 }
922 delete context;
923 return nullptr;
924 }
925#endif
926
927 default:
928 /* Unsupported backend. */
929 return nullptr;
930 }
931}
932
933/* --------------------------------------------------------------------
934 * Invalidate.
935 */
936
938{
939 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid");
940
941 @autoreleasepool {
943 view.needsDisplay = YES;
944 }
945 return GHOST_kSuccess;
946}
947
948/* --------------------------------------------------------------------
949 * Progress bar.
950 */
951
953{
954 @autoreleasepool {
955 if ((progress >= 0.0) && (progress <= 1.0)) {
956 NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)];
957
958 [dockIcon lockFocus];
959
960 [[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint
961 fromRect:NSZeroRect
962 operation:NSCompositingOperationSourceOver
963 fraction:1.0];
964
965 NSRect progressRect = {{8, 8}, {112, 14}};
966 NSBezierPath *progressPath;
967
968 /* Draw white track. */
969 [[[NSColor whiteColor] colorWithAlphaComponent:0.6] setFill];
970 progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:7 yRadius:7];
971 [progressPath fill];
972
973 /* Black progress fill. */
974 [[[NSColor blackColor] colorWithAlphaComponent:0.7] setFill];
975 progressRect = NSInsetRect(progressRect, 2, 2);
976 progressRect.size.width *= progress;
977 progressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:5 yRadius:5];
978 [progressPath fill];
979
980 [dockIcon unlockFocus];
981 [NSApp setApplicationIconImage:dockIcon];
982 [dockIcon release];
983
985 }
986 }
987 return GHOST_kSuccess;
988}
989
991{
993 return GHOST_kFailure;
994 }
995 progress_bar_visible_ = false;
996
997 /* Reset application icon to remove the progress bar. */
998 @autoreleasepool {
999 NSImage *dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128, 128)];
1000 [dockIcon lockFocus];
1001 [[NSImage imageNamed:@"NSApplicationIcon"] drawAtPoint:NSZeroPoint
1002 fromRect:NSZeroRect
1003 operation:NSCompositingOperationSourceOver
1004 fraction:1.0];
1005 [dockIcon unlockFocus];
1006 [NSApp setApplicationIconImage:dockIcon];
1007 [dockIcon release];
1008 }
1009 return GHOST_kSuccess;
1010}
1011
1012/* --------------------------------------------------------------------
1013 * Cursor handling.
1014 */
1015
1016static NSCursor *getImageCursor(GHOST_TStandardCursor shape, NSString *name, NSPoint hotspot)
1017{
1018 static NSCursor *cursors[GHOST_kStandardCursorNumCursors] = {nullptr};
1019 static bool loaded[GHOST_kStandardCursorNumCursors] = {false};
1020
1021 const int index = int(shape);
1022 if (!loaded[index]) {
1023 /* Load image from file in application Resources folder. */
1024 @autoreleasepool {
1025 NSImage *image = [NSImage imageNamed:name];
1026 if (image != nullptr) {
1027 cursors[index] = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
1028 }
1029 }
1030
1031 loaded[index] = true;
1032 }
1033
1034 return cursors[index];
1035}
1036
1037/* busyButClickableCursor is an undocumented NSCursor API, but
1038 * has been in use since at least OS X 10.4 and through 10.9. */
1039@interface NSCursor (Undocumented)
1041@end
1042
1044{
1045 @autoreleasepool {
1046 switch (shape) {
1048 if (custom_cursor_) {
1049 return custom_cursor_;
1050 }
1051 else {
1052 return nullptr;
1053 }
1055 return [NSCursor disappearingItemCursor];
1057 return [NSCursor IBeamCursor];
1059 return [NSCursor crosshairCursor];
1061 return [NSCursor resizeUpDownCursor];
1063 return [NSCursor resizeLeftRightCursor];
1065 return [NSCursor resizeUpCursor];
1067 return [NSCursor resizeDownCursor];
1069 return [NSCursor resizeLeftCursor];
1071 return [NSCursor resizeRightCursor];
1073 return [NSCursor dragCopyCursor];
1075 return [NSCursor operationNotAllowedCursor];
1077 return [NSCursor openHandCursor];
1079 return [NSCursor openHandCursor];
1081 return [NSCursor closedHandCursor];
1083 return [NSCursor pointingHandCursor];
1085 return [NSCursor arrowCursor];
1087 if ([NSCursor respondsToSelector:@selector(busyButClickableCursor)]) {
1088 return [NSCursor busyButClickableCursor];
1089 }
1090 return nullptr;
1092 return getImageCursor(shape, @"knife.pdf", NSMakePoint(6, 24));
1094 return getImageCursor(shape, @"eraser.pdf", NSMakePoint(6, 24));
1096 return getImageCursor(shape, @"pen.pdf", NSMakePoint(6, 24));
1098 return getImageCursor(shape, @"eyedropper.pdf", NSMakePoint(6, 24));
1100 return getImageCursor(shape, @"zoomin.pdf", NSMakePoint(8, 7));
1102 return getImageCursor(shape, @"zoomout.pdf", NSMakePoint(8, 7));
1104 return getImageCursor(shape, @"scrollnsew.pdf", NSMakePoint(16, 16));
1106 return getImageCursor(shape, @"scrollns.pdf", NSMakePoint(16, 16));
1108 return getImageCursor(shape, @"scrollew.pdf", NSMakePoint(16, 16));
1110 return getImageCursor(shape, @"arrowup.pdf", NSMakePoint(16, 16));
1112 return getImageCursor(shape, @"arrowdown.pdf", NSMakePoint(16, 16));
1114 return getImageCursor(shape, @"arrowleft.pdf", NSMakePoint(16, 16));
1116 return getImageCursor(shape, @"arrowright.pdf", NSMakePoint(16, 16));
1118 return getImageCursor(shape, @"splitv.pdf", NSMakePoint(16, 16));
1120 return getImageCursor(shape, @"splith.pdf", NSMakePoint(16, 16));
1122 return getImageCursor(shape, @"paint_cursor_cross.pdf", NSMakePoint(16, 15));
1124 return getImageCursor(shape, @"paint_cursor_dot.pdf", NSMakePoint(16, 15));
1126 return getImageCursor(shape, @"crossc.pdf", NSMakePoint(16, 16));
1128 return getImageCursor(shape, @"handle_left.pdf", NSMakePoint(12, 14));
1130 return getImageCursor(shape, @"handle_right.pdf", NSMakePoint(10, 14));
1132 return getImageCursor(shape, @"handle_both.pdf", NSMakePoint(11, 14));
1133 default:
1134 return nullptr;
1135 }
1136 }
1137}
1138
1140{
1141 static bool systemCursorVisible = true;
1142
1143 @autoreleasepool {
1144 if (visible != systemCursorVisible) {
1145 if (visible) {
1146 [NSCursor unhide];
1147 systemCursorVisible = true;
1148 }
1149 else {
1150 [NSCursor hide];
1151 systemCursorVisible = false;
1152 }
1153 }
1154
1155 NSCursor *cursor = getStandardCursor(shape);
1156 if (cursor == nullptr) {
1158 }
1159
1160 [cursor set];
1161 }
1162}
1163
1165{
1166 return is_dialog_;
1167}
1168
1170{
1171 @autoreleasepool {
1172 if (window_.isVisible) {
1173 loadCursor(visible, getCursorShape());
1174 }
1175 }
1176 return GHOST_kSuccess;
1177}
1178
1180{
1181 @autoreleasepool {
1182 if (mode != GHOST_kGrabDisable) {
1183 /* No need to perform grab without warp as it is always enabled in OS X. */
1184 if (mode != GHOST_kGrabNormal) {
1185 @autoreleasepool {
1187 setCursorGrabAccum(0, 0);
1188
1189 if (mode == GHOST_kGrabHide) {
1191 }
1192
1193 /* Make window key if it wasn't to get the mouse move events. */
1194 [window_ makeKeyWindow];
1195 }
1196 }
1197 }
1198 else {
1202 }
1203
1204 /* Almost works without but important otherwise the mouse GHOST location
1205 * can be incorrect on exit. */
1206 setCursorGrabAccum(0, 0);
1207 cursor_grab_bounds_.l_ = cursor_grab_bounds_.r_ = -1; /* disable */
1208 }
1209 }
1210 return GHOST_kSuccess;
1211}
1212
1214{
1215 @autoreleasepool {
1216 if (window_.isVisible) {
1218 }
1219 }
1220 return GHOST_kSuccess;
1221}
1222
1224{
1225 @autoreleasepool {
1227 return success;
1228 }
1229}
1230
1231/* Reverse the bits in a uint8_t */
1232#if 0
1233static uint8_t uns8ReverseBits(uint8_t ch)
1234{
1235 ch= ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
1236 ch= ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
1237 ch= ((ch >> 4) & 0x0F) | ((ch << 4) & 0xF0);
1238 return ch;
1239}
1240#endif
1241
1243static uint16_t uns16ReverseBits(uint16_t shrt)
1244{
1245 shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
1246 shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
1247 shrt = ((shrt >> 4) & 0x0F0F) | ((shrt << 4) & 0xF0F0);
1248 shrt = ((shrt >> 8) & 0x00FF) | ((shrt << 8) & 0xFF00);
1249 return shrt;
1250}
1251
1253 const uint8_t *mask,
1254 const int size[2],
1255 const int hot_spot[2],
1256 const bool can_invert_color)
1257{
1258 @autoreleasepool {
1259 if (custom_cursor_) {
1260 [custom_cursor_ release];
1261 custom_cursor_ = nil;
1262 }
1263
1264 NSBitmapImageRep *cursorImageRep = [[NSBitmapImageRep alloc]
1265 initWithBitmapDataPlanes:nil
1266 pixelsWide:size[0]
1267 pixelsHigh:size[1]
1268 bitsPerSample:1
1269 samplesPerPixel:2
1270 hasAlpha:YES
1271 isPlanar:YES
1272 colorSpaceName:NSDeviceWhiteColorSpace
1273 bytesPerRow:(size[0] / 8 + (size[0] % 8 > 0 ? 1 : 0))
1274 bitsPerPixel:1];
1275
1276 uint16_t *cursorBitmap = (uint16_t *)cursorImageRep.bitmapData;
1277 int nbUns16 = cursorImageRep.bytesPerPlane / 2;
1278
1279 for (int y = 0; y < nbUns16; y++) {
1280#if !defined(__LITTLE_ENDIAN__)
1281 cursorBitmap[y] = uns16ReverseBits((bitmap[2 * y] << 0) | (bitmap[2 * y + 1] << 8));
1282 cursorBitmap[nbUns16 + y] = uns16ReverseBits((mask[2 * y] << 0) | (mask[2 * y + 1] << 8));
1283#else
1284 cursorBitmap[y] = uns16ReverseBits((bitmap[2 * y + 1] << 0) | (bitmap[2 * y] << 8));
1285 cursorBitmap[nbUns16 + y] = uns16ReverseBits((mask[2 * y + 1] << 0) | (mask[2 * y] << 8));
1286#endif
1287
1288 /* Flip white cursor with black outline to black cursor with white outline
1289 * to match macOS platform conventions. */
1290 if (can_invert_color) {
1291 cursorBitmap[y] = ~cursorBitmap[y];
1292 }
1293 }
1294
1295 const NSSize imSize = {(CGFloat)size[0], (CGFloat)size[1]};
1296 NSImage *cursorImage = [[NSImage alloc] initWithSize:imSize];
1297 [cursorImage addRepresentation:cursorImageRep];
1298
1299 const NSPoint hotSpotPoint = {(CGFloat)(hot_spot[0]), (CGFloat)(hot_spot[1])};
1300
1301 /* Foreground and background color parameter is not handled for now (10.6). */
1302 custom_cursor_ = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint];
1303
1304 [cursorImageRep release];
1305 [cursorImage release];
1306
1307 if (window_.isVisible) {
1309 }
1310 }
1311 return GHOST_kSuccess;
1312}
1313
1314#ifdef WITH_INPUT_IME
1315void GHOST_WindowCocoa::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
1316{
1317 if (opengl_view_) {
1318 [opengl_view_ beginIME:x y:y w:w h:h completed:completed];
1319 }
1320 else {
1321 [metal_view_ beginIME:x y:y w:w h:h completed:completed];
1322 }
1323}
1324
1325void GHOST_WindowCocoa::endIME()
1326{
1327 if (opengl_view_) {
1328 [opengl_view_ endIME];
1329 }
1330 else {
1331 [metal_view_ endIME];
1332 }
1333}
1334#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:57
@ GHOST_kFailure
Definition GHOST_Types.h:57
@ GHOST_kSuccess
Definition GHOST_Types.h:57
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)
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
BlenderWindow * window_
bool isDialog() const override
GHOST_TSuccess setProgressBar(float progress) override
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override
GHOST_TSuccess setState(GHOST_TWindowState state) override
std::string getTitle() const override
GHOST_SystemCocoa * system_cocoa_
GHOST_TSuccess setClientHeight(uint32_t height) override
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
CAMetalLayer * metal_layer_
NSScreen * getScreen() const
void setTitle(const char *title) override
GHOST_TSuccess invalidate() override
GHOST_TSuccess endProgressBar() override
NSCursor * getStandardCursor(GHOST_TStandardCursor cursor) const
GHOST_TWindowState getState() const override
GHOST_TSuccess setClientWidth(uint32_t width) override
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
CocoaOpenGLView * opengl_view_
void getClientBounds(GHOST_Rect &bounds) const override
GHOST_TSuccess setModifiedState(bool is_unsaved_changes) 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(const uint8_t *bitmap, const uint8_t *mask, const int size[2], const int hot_spot[2], bool can_invert_color) override
static NSScreen * getPrimaryScreen()
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 GHOST_ContextParams &context_params, bool dialog, GHOST_WindowCocoa *parent_window, const GHOST_GPUDevice &preferred_device)
GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override
CocoaMetalView * metal_view_
void screenToClientIntern(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
GHOST_GPUDevice preferred_device_
GHOST_TSuccess setPath(const char *filepath) override
bool getValid() const override
GHOST_TSuccess setWindowCursorVisibility(bool visible) override
GHOST_TabletData tablet_
void loadCursor(bool visible, GHOST_TStandardCursor cursor) const
GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override
GHOST_ContextParams want_context_params_
float native_pixel_size_
GHOST_TSuccess setModifiedState(bool is_unsaved_changes) override
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_WindowDecorationStyleSettings window_decoration_style_settings_
GHOST_TStandardCursor getCursorShape() const override
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override
int32_t cursor_grab_init_pos_[2]
GHOST_TSuccess releaseNativeHandles()
GHOST_TWindowDecorationStyleFlags window_decoration_style_flags_
bool getValid() const override
bool getCursorVisibility() const override
GHOST_TSuccess activateDrawingContext() override
GHOST_TSuccess updateDrawingContext()
GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, const GHOST_ContextParams &context_params, const bool exclusive=false)
GHOST_Rect cursor_grab_bounds_
bool progress_bar_visible_
GHOST_WindowHDRInfo hdr_info_
GHOST_TGrabCursorMode cursor_grab_
nullptr float
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
const char * name