| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2017 Marko Pintera ([email protected]). All rights reserved. **********************//
- #define BS_COCOA_INTERNALS 1
- #include "MacOS/BsMacOSWindow.h"
- #include "MacOS/BsMacOSPlatform.h"
- #include "MacOS/BsMacOSDropTarget.h"
- #include "Math/BsRect2I.h"
- #include "Input/BsInputFwd.h"
- #include "String/BsUnicode.h"
- #include "RenderAPI/BsRenderWindow.h"
- static bool keyCodeToInputCommand(uint32_t keyCode, bool shift, bs::InputCommandType& inputCommand)
- {
- switch(keyCode)
- {
- case 36: // Return
- inputCommand = shift ? bs::InputCommandType::Return : bs::InputCommandType::Confirm;
- return true;
- case 51: // Backspace
- inputCommand = bs::InputCommandType::Backspace;
- return true;
- case 53: // Escape
- inputCommand = bs::InputCommandType::Escape;
- return true;
- case 117: // Delete
- inputCommand = bs::InputCommandType::Delete;
- return true;
- case 123: // Left
- inputCommand = shift ? bs::InputCommandType::SelectLeft : bs::InputCommandType::CursorMoveLeft;
- return true;
- case 124: // Right
- inputCommand = shift ? bs::InputCommandType::SelectRight : bs::InputCommandType::CursorMoveRight;
- return true;
- case 125: // Down
- inputCommand = shift ? bs::InputCommandType::SelectDown : bs::InputCommandType::CursorMoveDown;
- return true;
- case 126: // Up
- inputCommand = shift ? bs::InputCommandType::SelectUp : bs::InputCommandType::CursorMoveUp;
- return true;
- }
- return false;
- }
- /**
- * Overrides window so even borderless windows can become key windows (allowing resize events and cursor changes, among
- * others.
- */
- @interface BSWindow : NSWindow
- @end
- @implementation BSWindow
- - (BOOL)canBecomeKeyWindow
- {
- return YES;
- }
- @end
- /** Implementation of NSView that handles custom cursors, transparent background images and reports the right mouse click. */
- @interface BSView : NSView
- @property (atomic, strong) NSArray* resizeAreas;
- -(void)rightMouseDown:(NSEvent *) event;
- -(void)setBackgroundImage:(NSImage*)image;
- @end
- @implementation BSView
- {
- NSTrackingArea* mTrackingArea;
- NSImageView* mImageView;
- }
- -(id)init
- {
- self = [super init];
- mTrackingArea = nil;
- mImageView = nil;
- return self;
- }
- -(void)resetCursorRects
- {
- [super resetCursorRects];
- [self addCursorRect:[self bounds] cursor:bs::MacOSPlatform::_getCurrentCursor()];
- }
- -(void)updateTrackingAreas
- {
- [super updateTrackingAreas];
- if(mTrackingArea)
- [self removeTrackingArea:mTrackingArea];
- NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp;
- mTrackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:[self window] userInfo:nil];
- [self addTrackingArea:mTrackingArea];
- }
- -(void)rightMouseDown:(NSEvent*)event
- {
- // By default the view eats the right mouse event, but we instead forward the event to window's responder for normal
- // handling
- if([event.window nextResponder])
- [[event.window nextResponder] rightMouseDown:event];
- }
- -(void)setBackgroundImage:(NSImage*)image
- { @autoreleasepool {
- if(image)
- {
- NSRect frame = [self frame];
- frame.origin = NSMakePoint(0, 0);
- mImageView = [[NSImageView alloc] initWithFrame:frame];
- [mImageView setImageScaling:NSImageScaleAxesIndependently];
- [mImageView setImage:image];
- [mImageView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- self.subviews = @[mImageView];
- }
- else
- self.subviews = @[];
- }}
- @end
- /** Types of mouse events reported by BSWindowListener. */
- enum class MouseEventType
- {
- ButtonUp, ButtonDown
- };
- /** Listens to mouse and keyboard events for a specific window. Reports them to Platform accordingly. */
- @interface BSWindowListener : NSResponder
- // Properties
- @property (atomic, strong) NSArray* dragAreas;
- // Mouse
- -(void) handleMouseEvent:(NSEvent *) event type:(MouseEventType) type button:(bs::OSMouseButton) button;
- -(void) mouseDown:(NSEvent *) event;
- -(void) rightMouseDown:(NSEvent *) event;
- -(void) otherMouseDown:(NSEvent *) event;
- -(void) mouseUp:(NSEvent *) event;
- -(void) rightMouseUp:(NSEvent *) event;
- -(void) otherMouseUp:(NSEvent *) event;
- -(void) mouseMoved:(NSEvent *) event;
- -(void) mouseDragged:(NSEvent *) event;
- -(void) rightMouseDragged:(NSEvent *) event;
- -(void) otherMouseDragged:(NSEvent *) event;
- -(void) scrollWheel:(NSEvent *) event;
- // Keyboard
- -(void) keyDown:(NSEvent *)event;
- // Other
- -(BSWindowListener*)initWithOwner:(bs::CocoaWindow*) owner;
- @end
- @implementation BSWindowListener
- {
- bs::CocoaWindow* mOwner;
- }
- @synthesize dragAreas;
- - (BSWindowListener* )initWithOwner:(bs::CocoaWindow*)owner
- {
- self = [super init];
- mOwner = owner;
- dragAreas = nil;
- return self;
- }
- - (void)handleMouseEvent:(NSEvent *)event type:(MouseEventType) type button:(bs::OSMouseButton) button
- {
- NSPoint screenPos = NSEvent.mouseLocation;
- NSUInteger modifierFlags = NSEvent.modifierFlags;
- uint32_t pressedButtons = (uint32_t)NSEvent.pressedMouseButtons;
- bs::OSPointerButtonStates buttonStates;
- buttonStates.ctrl = (modifierFlags & NSEventModifierFlagControl) != 0;
- buttonStates.shift = (modifierFlags & NSEventModifierFlagShift) != 0;
- buttonStates.mouseButtons[0] = (pressedButtons & (1 << 0)) != 0;
- buttonStates.mouseButtons[1] = (pressedButtons & (1 << 1)) != 0;
- buttonStates.mouseButtons[2] = (pressedButtons & (1 << 2)) != 0;
- NSWindow* window = [event window];
- NSScreen* screen = window ? [window screen] : [NSScreen mainScreen];
- bs::flipY(screen, screenPos);
- bs::Vector2I pos((int32_t)screenPos.x, (int32_t)screenPos.y);
- if(type == MouseEventType::ButtonDown)
- bs::MacOSPlatform::sendPointerButtonPressedEvent(pos, button, buttonStates);
- else // ButtonUp
- {
- if([event clickCount] == 2 && button == bs::OSMouseButton::Left)
- bs::MacOSPlatform::sendPointerDoubleClickEvent(pos, buttonStates);
- else
- bs::MacOSPlatform::sendPointerButtonReleasedEvent(pos, button, buttonStates);
- }
- }
- - (void)mouseDown:(NSEvent *)event
- {
- // Check for manual drag
- bool isManualDrag = false;
- if(dragAreas)
- {
- NSPoint point = [event locationInWindow];
- NSWindow* window = [event window];
- NSScreen* screen = nil;
- if(window)
- {
- NSRect windowFrame = [window frame];
- point.x += windowFrame.origin.x;
- point.y += windowFrame.origin.y;
- screen = [window screen];
- }
- else
- screen = NSScreen.mainScreen;
- bs::flipY(screen, point);
- for (NSUInteger i = 0; i < [dragAreas count]; i++)
- {
- bs::Rect2I rect;
- [dragAreas[i] getValue:&rect];
- if(point.x >= rect.x && point.x < (rect.x + rect.width) &&
- (point.y >= rect.y && point.y < (rect.y + rect.height)))
- {
- [window performWindowDragWithEvent:event];
- isManualDrag = true;
- break;
- }
- }
- }
- if(!isManualDrag)
- [self handleMouseEvent:event type:MouseEventType::ButtonDown button:bs::OSMouseButton::Left];
- }
- - (void)rightMouseDown:(NSEvent *)event
- {
- [self handleMouseEvent:event type:MouseEventType::ButtonDown button:bs::OSMouseButton::Right];
- }
- - (void)otherMouseDown:(NSEvent *)event
- {
- [self handleMouseEvent:event type:MouseEventType::ButtonDown button:bs::OSMouseButton::Middle];
- }
- - (void)mouseUp:(NSEvent *)event
- {
- [self handleMouseEvent:event type:MouseEventType::ButtonUp button:bs::OSMouseButton::Left];
- }
- - (void)rightMouseUp:(NSEvent *)event
- {
- [self handleMouseEvent:event type:MouseEventType::ButtonUp button:bs::OSMouseButton::Right];
- }
- - (void)otherMouseUp:(NSEvent *)event
- {
- [self handleMouseEvent:event type:MouseEventType::ButtonUp button:bs::OSMouseButton::Middle];
- }
- - (void)mouseMoved:(NSEvent *)event
- {
- uint32_t pressedButtons = (uint32_t)NSEvent.pressedMouseButtons;
- NSPoint point = [event locationInWindow];
- NSWindow* window = [event window];
- NSScreen* screen = nil;
- if(window)
- {
- NSRect windowFrame = [window frame];
- point.x += windowFrame.origin.x;
- point.y += windowFrame.origin.y;
- screen = [window screen];
- }
- else
- screen = NSScreen.mainScreen;
- bs::flipY(screen, point);
- bs::Vector2I pos;
- pos.x = (int32_t)point.x;
- pos.y = (int32_t)point.y;
- if(bs::MacOSPlatform::_clipCursor(pos))
- bs::MacOSPlatform::_setCursorPosition(pos);
- NSUInteger modifierFlags = NSEvent.modifierFlags;
- bs::OSPointerButtonStates buttonStates;
- buttonStates.ctrl = (modifierFlags & NSEventModifierFlagControl) != 0;
- buttonStates.shift = (modifierFlags & NSEventModifierFlagShift) != 0;
- buttonStates.mouseButtons[0] = (pressedButtons & (1 << 0)) != 0;
- buttonStates.mouseButtons[1] = (pressedButtons & (1 << 1)) != 0;
- buttonStates.mouseButtons[2] = (pressedButtons & (1 << 2)) != 0;
- bs::MacOSPlatform::sendPointerMovedEvent(pos, buttonStates);
- }
- - (void)mouseDragged:(NSEvent *)event
- {
- [self mouseMoved:event];
- }
- - (void)rightMouseDragged:(NSEvent *)event
- {
- [self mouseMoved:event];
- }
- - (void)otherMouseDragged:(NSEvent *)event
- {
- [self mouseMoved:event];
- }
- - (void)scrollWheel:(NSEvent *)event
- {
- float y = (float)[event deltaY];
- bs::MacOSPlatform::sendMouseWheelScrollEvent((float)y);
- }
- - (void)keyDown:(NSEvent *)event
- {
- NSString* string = event.characters;
- uint32_t keyCode = event.keyCode;
- NSUInteger modifierFlags = NSEvent.modifierFlags;
- bool shift = (modifierFlags & NSEventModifierFlagShift) != 0;
- bs::InputCommandType ict;
- if(keyCodeToInputCommand(keyCode, shift, ict))
- bs::MacOSPlatform::sendInputCommandEvent(ict);
- else
- {
- bs::String utf8String = [string UTF8String];
- bs::U32String utf32String = bs::UTF8::toUTF32(utf8String);
- for(size_t i = 0; utf32String.length(); i++)
- bs::MacOSPlatform::sendCharInputEvent(utf32String[i]);
- }
- }
- - (void)mouseEntered:(NSEvent*)event
- {
- // Do nothing
- }
- - (void)mouseExited:(NSEvent*)event
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mOwner->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_notifyMouseLeft();
- }
- @end
- /** Converts a point from coordinates relative to window's frame, into coordinates relative to window's content rectangle. */
- NSPoint frameToContentRect(NSWindow* window, NSPoint framePoint)
- {
- bs::flipYWindow(window, framePoint);
- NSRect frameRect = [window frame];
- NSRect contentRect = [window contentRectForFrameRect:frameRect];
- NSPoint offset;
- offset.x = frameRect.origin.x - contentRect.origin.x;
- offset.y = (frameRect.origin.y + frameRect.size.height) - (contentRect.origin.y + contentRect.size.height);
- framePoint.x -= offset.x;
- framePoint.y -= offset.y;
- return framePoint;
- }
- /** Listens to window move, resize, focus change and close events, handles drag and drop operations. */
- @interface BSWindowDelegate : NSObject<NSWindowDelegate, NSDraggingDestination>
- -(id)initWithWindow:(bs::CocoaWindow*)window;
- @end
- @implementation BSWindowDelegate
- {
- bs::CocoaWindow* mWindow;
- NSRect mStandardZoomFrame;
- bool mIsZooming;
- }
- - (id)initWithWindow:(bs::CocoaWindow*)window
- {
- self = [super init];
- mWindow = window;
- mIsZooming = false;
- return self;
- }
- - (void)windowWillClose:(NSNotification *)notification
- {
- // If it's a render window we allow the client code to handle the message
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_notifyCloseRequested();
- else // If not, we just destroy the window
- mWindow->_destroy();
- }
- - (void)windowDidBecomeKey:(NSNotification*)notification
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_windowFocusReceived();
- }
- - (void)windowDidResignKey:(NSNotification*)notification
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_windowFocusLost();
- }
- - (void)windowDidResize:(NSNotification*)notification
- {
- if([[notification object] isKindOfClass:[NSWindow class]])
- bs::MacOSPlatform::_updateClipBounds([notification object]);
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_windowMovedOrResized();
- }
- - (void)windowDidMove:(NSNotification*)notification
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_windowMovedOrResized();
- }
- - (void)windowDidMiniaturize:(NSNotification*)notification
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_notifyMinimized();
- }
- - (void)windowDidDeminiaturize:(NSNotification*)notification
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- renderWindow->_notifyRestored();
- }
- - (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame
- {
- // Maximizing, or restoring
- if(mIsZooming)
- {
- bs::ct::RenderWindow* renderWindow = (bs::ct::RenderWindow*)mWindow->_getUserData();
- if(renderWindow != nullptr)
- {
- if (newFrame.size.width == mStandardZoomFrame.size.width &&
- newFrame.size.height == mStandardZoomFrame.size.height)
- renderWindow->_notifyMaximized();
- else
- renderWindow->_notifyRestored();
- }
- mIsZooming = true;
- }
- return YES;
- }
- - (NSRect)windowWillUseStandardFrame:(NSWindow*)window defaultFrame:(NSRect)newFrame
- {
- mIsZooming = true;
- mStandardZoomFrame = newFrame;
- return newFrame;
- }
- - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
- {
- bs::CocoaWindow::Pimpl* privateData = mWindow->_getPrivateData();
- NSPoint point = [sender draggingLocation];
- point = frameToContentRect(privateData->window, point);
- bs::Vector2I position((int32_t)point.x, (int32_t)point.y);
- if(bs::CocoaDragAndDrop::_notifyDragEntered(mWindow, position))
- return NSDragOperationLink;
- return NSDragOperationNone;
- }
- - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
- {
- bs::CocoaWindow::Pimpl* privateData = mWindow->_getPrivateData();
- NSPoint point = [sender draggingLocation];
- point = frameToContentRect(privateData->window, point);
- bs::Vector2I position((int32_t)point.x, (int32_t)point.y);
- if(bs::CocoaDragAndDrop::_notifyDragMoved(mWindow, position))
- return NSDragOperationLink;
- return NSDragOperationNone;
- }
- - (void)draggingExited:(nullable id <NSDraggingInfo>)sender
- {
- bs::CocoaDragAndDrop::_notifyDragLeft(mWindow);
- }
- - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
- {
- NSPasteboard* pasteboard = [sender draggingPasteboard];
- if([[pasteboard types] containsObject:NSFilenamesPboardType])
- {
- NSArray* entries = [pasteboard propertyListForType:NSFilenamesPboardType];
- bs::Vector<bs::Path> paths;
- for(NSString* path in entries)
- {
- const char* pathChars = [path UTF8String];
- paths.push_back(bs::Path(pathChars));
- }
- bs::CocoaWindow::Pimpl* privateData = mWindow->_getPrivateData();
- NSPoint point = [sender draggingLocation];
- point = frameToContentRect(privateData->window, point);
- bs::Vector2I position((int32_t)point.x, (int32_t)point.y);
- if(bs::CocoaDragAndDrop::_notifyDragDropped(mWindow, position, paths))
- return YES;
- }
- return NO;
- }
- @end
- namespace bs
- {
- CocoaWindow::CocoaWindow(const WINDOW_DESC& desc)
- { @autoreleasepool {
- m = bs_new<Pimpl>();
- NSArray* screens = [NSScreen screens];
- NSScreen* screen = nil;
- INT32 x = 0;
- INT32 y = 0;
- for(NSScreen* entry in screens)
- {
- NSRect screenRect = [entry frame];
- if(((desc.x >= screenRect.origin.x && desc.y < (screenRect.origin.x + screenRect.size.width)) || desc.x == -1) &&
- ((desc.y >= screenRect.origin.y && desc.y < (screenRect.origin.y + screenRect.size.height)) || desc.y == -1))
- {
- if(desc.x == -1)
- x = (INT32)screenRect.origin.x + std::max(0, (INT32)screenRect.size.width - (INT32)desc.width) / 2;
- else
- x = desc.x - (INT32)screenRect.origin.x;
- if(desc.y == -1)
- y = (INT32)screenRect.origin.y + std::max(0, (INT32)screenRect.size.height - (INT32)desc.height) / 2;
- else
- y = desc.y - (INT32)screenRect.origin.y;
- screen = entry;
- break;
- }
- }
- if(!desc.showDecorations)
- m->style |= NSWindowStyleMaskBorderless;
- else
- m->style |= NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
- if(desc.allowResize)
- m->style |= NSWindowStyleMaskResizable;
- m->window = [BSWindow alloc];
- m->window = [m->window
- initWithContentRect:NSMakeRect(x, y, desc.width, desc.height)
- styleMask:(NSWindowStyleMask)m->style
- backing:NSBackingStoreBuffered
- defer:NO
- screen:screen];
- if(desc.allowResize)
- {
- bool allowSpaces = NSAppKitVersionNumber > NSAppKitVersionNumber10_6;
- if(allowSpaces)
- [m->window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
- }
- NSString* titleString = [NSString stringWithUTF8String:desc.title.c_str()];
- [m->window setAcceptsMouseMovedEvents:YES];
- [m->window setReleasedWhenClosed:NO];
- [m->window setTitle:titleString];
- [m->window makeKeyAndOrderFront:nil];
- m->responder = [[BSWindowListener alloc] initWithOwner:this];
- [m->window setNextResponder:m->responder];
- m->delegate = [[BSWindowDelegate alloc] initWithWindow:this];
- [m->window setDelegate:m->delegate];
- m->view = [[BSView alloc] init];
- [m->window setContentView:m->view];
- if(desc.background)
- {
- [m->window setAlphaValue:1.0f];
- [m->window setOpaque:NO];
- [m->window setBackgroundColor:[NSColor clearColor]];
- NSImage* image = MacOSPlatform::createNSImage(*desc.background);
- [m->view setBackgroundImage:image];
- }
- m->isModal = desc.modal;
- m->windowNumber = [m->window windowNumber];
- MacOSPlatform::registerWindow(this);
- }}
- CocoaWindow::~CocoaWindow()
- {
- if(m->window != nil)
- _destroy();
- bs_delete(m);
- }
- void CocoaWindow::move(INT32 x, INT32 y)
- { @autoreleasepool {
- NSPoint point;
- point.x = x;
- point.y = y;
- [m->window setFrameTopLeftPoint:point];
- }}
- void CocoaWindow::resize(UINT32 width, UINT32 height)
- { @autoreleasepool {
- NSRect frameRect = m->window.frame;
- NSRect contentRect = [m->window contentRectForFrameRect:frameRect];
- contentRect.size.width = width;
- contentRect.size.height = height;
- [m->window setFrame:[m->window frameRectForContentRect:contentRect] display:YES];
- }}
- void CocoaWindow::_destroy()
- {
- MacOSPlatform::unregisterWindow(this);
- m->window = nil;
- }
- Rect2I CocoaWindow::getArea() const
- { @autoreleasepool {
- NSRect frameRect = [m->window frame];
- NSRect contentRect = [m->window contentRectForFrameRect:frameRect];
- flipY([m->window screen], contentRect);
- return Rect2I(
- (INT32)contentRect.origin.x,
- (INT32)contentRect.origin.y,
- (UINT32)contentRect.size.width,
- (UINT32)contentRect.size.height
- );
- }}
- void CocoaWindow::hide()
- { @autoreleasepool {
- [m->window orderOut:nil];
- }}
- void CocoaWindow::show()
- { @autoreleasepool {
- [m->window makeKeyAndOrderFront:nil];
- }}
- void CocoaWindow::maximize()
- { @autoreleasepool {
- if(![m->window isZoomed])
- [m->window zoom:nil];
- }}
- void CocoaWindow::minimize()
- { @autoreleasepool {
- [m->window miniaturize:nil];
- }}
- void CocoaWindow::restore()
- { @autoreleasepool {
- if([m->window isMiniaturized])
- [m->window deminiaturize:nil];
- else if([m->window isZoomed])
- [m->window zoom:nil];
- }}
- Vector2I CocoaWindow::windowToScreenPos(const Vector2I& windowPos) const
- { @autoreleasepool {
- NSRect frameRect = [m->window frame];
- NSRect contentRect = [m->window contentRectForFrameRect:frameRect];
- flipY([m->window screen], contentRect);
- Vector2I screenPos;
- screenPos.x = windowPos.x + (INT32)contentRect.origin.x;
- screenPos.y = windowPos.y + (INT32)contentRect.origin.y;
- return screenPos;
- }}
- Vector2I CocoaWindow::screenToWindowPos(const Vector2I& screenPos) const
- { @autoreleasepool {
- NSRect frameRect = [m->window frame];
- NSRect contentRect = [m->window contentRectForFrameRect:frameRect];
- flipY([m->window screen], contentRect);
- Vector2I windowPos;
- windowPos.x = screenPos.x - (INT32) contentRect.origin.x;
- windowPos.y = screenPos.y - (INT32) contentRect.origin.y;
- return windowPos;
- }}
- void CocoaWindow::setWindowed()
- {
- if(m->isFullscreen)
- {
- [m->window setStyleMask:(NSWindowStyleMask)m->style];
- [m->window setFrame:m->windowedRect display:NO];
- [m->window setLevel:NSNormalWindowLevel];
- m->isFullscreen = false;
- }
- }
- void CocoaWindow::setFullscreen()
- {
- if(!m->isFullscreen)
- m->windowedRect = [m->window frame];
- NSRect frame = [[m->window screen] frame];
- [m->window setStyleMask:NSWindowStyleMaskBorderless];
- [m->window setFrame:frame display:NO];
- [m->window setLevel:NSMainMenuWindowLevel+1];
- [m->window makeKeyAndOrderFront:nil];
- m->isFullscreen = true;
- }
- void CocoaWindow::_setDragZones(const Vector<Rect2I>& rects)
- { @autoreleasepool {
- NSMutableArray* array = [[NSMutableArray alloc] init];
- for(auto& entry : rects)
- [array addObject:[NSValue valueWithBytes:&entry objCType:@encode(Rect2I)]];
- [m->responder setDragAreas:array];
- }}
- void CocoaWindow::_setUserData(void* data)
- {
- m->userData = data;
- }
- void* CocoaWindow::_getUserData() const
- {
- return m->userData;
- }
- void CocoaWindow::_registerForDragAndDrop()
- {
- if(m->numDropTargets == 0)
- [m->window registerForDraggedTypes:@[NSFilenamesPboardType]];
- }
- void CocoaWindow::_unregisterForDragAndDrop()
- {
- if(m->numDropTargets == 0)
- return;
- m->numDropTargets--;
- if(m->numDropTargets == 0)
- [m->window unregisterDraggedTypes];
- }
- }
|