mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 14:44:36 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
50
Engine/source/windowManager/mac/macCursorController.h
Normal file
50
Engine/source/windowManager/mac/macCursorController.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MACCURSORCONTROLLER_H_
|
||||
#define _MACCURSORCONTROLLER_H_
|
||||
|
||||
#include "windowManager/platformCursorController.h"
|
||||
|
||||
class MacCursorController : public PlatformCursorController
|
||||
{
|
||||
public:
|
||||
MacCursorController(MacWindow* owner)
|
||||
: PlatformCursorController( ( PlatformWindow* ) owner )
|
||||
{
|
||||
pushCursor(PlatformCursorController::curArrow);
|
||||
}
|
||||
|
||||
virtual void setCursorPosition(S32 x, S32 y);
|
||||
virtual void getCursorPosition(Point2I &point);
|
||||
virtual void setCursorVisible(bool visible);
|
||||
virtual bool isCursorVisible();
|
||||
|
||||
virtual void setCursorShape(U32 cursorID);
|
||||
virtual void setCursorShape( const UTF8 *fileName, bool reload );
|
||||
|
||||
virtual U32 getDoubleClickTime();
|
||||
virtual S32 getDoubleClickWidth();
|
||||
virtual S32 getDoubleClickHeight();
|
||||
};
|
||||
|
||||
#endif
|
||||
166
Engine/source/windowManager/mac/macCursorController.mm
Normal file
166
Engine/source/windowManager/mac/macCursorController.mm
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
#include "windowManager/mac/macCursorController.h"
|
||||
|
||||
void MacCursorController::setCursorPosition(S32 x, S32 y)
|
||||
{
|
||||
MacWindow* macWindow = dynamic_cast<MacWindow*>(mOwner);
|
||||
if(!macWindow || !macWindow->isVisible())
|
||||
return;
|
||||
|
||||
CGPoint pt = { x, y };
|
||||
CGWarpMouseCursorPosition(pt);
|
||||
|
||||
macWindow->_skipAnotherMouseEvent();
|
||||
}
|
||||
|
||||
void MacCursorController::getCursorPosition( Point2I &point )
|
||||
{
|
||||
NSPoint pos = [NSEvent mouseLocation];
|
||||
point.x = pos.x;
|
||||
point.y = pos.y;
|
||||
|
||||
//what does this do?? comment??
|
||||
|
||||
MacWindow* macWindow = static_cast<MacWindow*>(mOwner);
|
||||
|
||||
CGRect bounds = macWindow->getDisplayBounds();
|
||||
CGRect mainbounds = macWindow->getMainDisplayBounds();
|
||||
F32 offsetY = mainbounds.size.height - (bounds.size.height + bounds.origin.y);
|
||||
point.y = bounds.size.height + offsetY - point.y;
|
||||
}
|
||||
|
||||
void MacCursorController::setCursorVisible(bool visible)
|
||||
{
|
||||
visible ? [NSCursor unhide] : [NSCursor hide];
|
||||
}
|
||||
|
||||
bool MacCursorController::isCursorVisible()
|
||||
{
|
||||
return CGCursorIsVisible();
|
||||
}
|
||||
|
||||
// a repository of custom cursors.
|
||||
@interface TorqueCursors : NSObject { }
|
||||
+(NSCursor*)resizeAll;
|
||||
+(NSCursor*)resizeNWSE;
|
||||
+(NSCursor*)resizeNESW;
|
||||
@end
|
||||
@implementation TorqueCursors
|
||||
+(NSCursor*)resizeAll
|
||||
{
|
||||
static NSCursor* cur = nil;
|
||||
if(!cur)
|
||||
cur = [[NSCursor alloc] initWithImage:[NSImage imageNamed:@"resizeAll"] hotSpot:NSMakePoint(8, 8)];
|
||||
return cur;
|
||||
}
|
||||
+(NSCursor*)resizeNWSE
|
||||
{
|
||||
static NSCursor* cur = nil;
|
||||
if(!cur)
|
||||
cur = [[NSCursor alloc] initWithImage:[NSImage imageNamed:@"resizeNWSE"] hotSpot:NSMakePoint(8, 8)];
|
||||
return cur;
|
||||
}
|
||||
+(NSCursor*)resizeNESW
|
||||
{
|
||||
static NSCursor* cur = nil;
|
||||
if(!cur)
|
||||
cur = [[NSCursor alloc] initWithImage:[NSImage imageNamed:@"resizeNESW"] hotSpot:NSMakePoint(8, 8)];
|
||||
return cur;
|
||||
}
|
||||
@end
|
||||
|
||||
void MacCursorController::setCursorShape(U32 cursorID)
|
||||
{
|
||||
NSCursor *cur;
|
||||
switch(cursorID)
|
||||
{
|
||||
case PlatformCursorController::curArrow:
|
||||
[[NSCursor arrowCursor] set];
|
||||
break;
|
||||
case PlatformCursorController::curWait:
|
||||
// hack: black-sheep carbon call
|
||||
SetThemeCursor(kThemeWatchCursor);
|
||||
break;
|
||||
case PlatformCursorController::curPlus:
|
||||
[[NSCursor crosshairCursor] set];
|
||||
break;
|
||||
case PlatformCursorController::curResizeVert:
|
||||
[[NSCursor resizeLeftRightCursor] set];
|
||||
break;
|
||||
case PlatformCursorController::curIBeam:
|
||||
[[NSCursor IBeamCursor] set];
|
||||
break;
|
||||
case PlatformCursorController::curResizeAll:
|
||||
cur = [TorqueCursors resizeAll];
|
||||
[cur set];
|
||||
break;
|
||||
case PlatformCursorController::curResizeNESW:
|
||||
[[TorqueCursors resizeNESW] set];
|
||||
break;
|
||||
case PlatformCursorController::curResizeNWSE:
|
||||
[[TorqueCursors resizeNWSE] set];
|
||||
break;
|
||||
case PlatformCursorController::curResizeHorz:
|
||||
[[NSCursor resizeUpDownCursor] set];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacCursorController::setCursorShape( const UTF8 *fileName, bool reload )
|
||||
{
|
||||
//TODO: this is untested code
|
||||
|
||||
NSString* strFileName = [ NSString stringWithUTF8String: fileName ];
|
||||
|
||||
// Load image file.
|
||||
|
||||
NSImage* image = [ NSImage alloc ];
|
||||
if( [ image initWithContentsOfFile: strFileName ] == nil )
|
||||
return;
|
||||
|
||||
// Allocate cursor.
|
||||
|
||||
NSCursor* cursor = [ NSCursor alloc ];
|
||||
[ cursor initWithImage: image hotSpot: NSMakePoint( 0.5, 0.5 ) ];
|
||||
}
|
||||
|
||||
U32 MacCursorController::getDoubleClickTime()
|
||||
{
|
||||
return GetDblTime() / 60.0f * 1000.0f;
|
||||
}
|
||||
|
||||
S32 MacCursorController::getDoubleClickWidth()
|
||||
{
|
||||
// This is an arbitrary value.
|
||||
return 10;
|
||||
}
|
||||
|
||||
S32 MacCursorController::getDoubleClickHeight()
|
||||
{
|
||||
return getDoubleClickWidth();
|
||||
}
|
||||
|
||||
75
Engine/source/windowManager/mac/macView.h
Normal file
75
Engine/source/windowManager/mac/macView.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MACVIEW_H_
|
||||
#define _MACVIEW_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
|
||||
/// GGMacView handles displaying content and responding to user input.
|
||||
@interface GGMacView : NSOpenGLView
|
||||
{
|
||||
MacWindow* mTorqueWindow;
|
||||
U32 mLastMods;
|
||||
bool mHandledAsCharEvent;
|
||||
}
|
||||
- (void)setTorqueWindow:(MacWindow*)theWindow;
|
||||
- (MacWindow*)torqueWindow;
|
||||
|
||||
/// @name Inherited Mouse Input methods
|
||||
/// @{
|
||||
- (void)mouseDown:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
- (void)mouseDragged:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)mouseUp:(NSEvent *)theEvent;
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent;
|
||||
- (void)mouseMoved:(NSEvent *)theEvent;
|
||||
- (void)scrollWheel:(NSEvent *)theEvent;
|
||||
/// @}
|
||||
|
||||
/// @name Inherited Keyboard Input methods
|
||||
/// @{
|
||||
- (void)keyDown:(NSEvent *)theEvent;
|
||||
- (void)keyUp:(NSEvent *)theEvent;
|
||||
/// @}
|
||||
|
||||
/// @name Keyboard Input Common Code
|
||||
/// @{
|
||||
- (void)rawKeyUpDown:(NSEvent *)theEvent keyDown:(BOOL)isKeyDown;
|
||||
/// @}
|
||||
|
||||
/// @name Mouse Input Common Code
|
||||
/// @{
|
||||
- (void)mouseUpDown:(NSEvent *)theEvent mouseDown:(BOOL)isMouseDown;
|
||||
- (void)mouseMotion:(NSEvent *)theEvent;
|
||||
/// @}
|
||||
|
||||
- (BOOL)acceptsFirstResponder;
|
||||
- (BOOL)becomeFirstResponder;
|
||||
- (BOOL)resignFirstResponder;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
401
Engine/source/windowManager/mac/macView.mm
Normal file
401
Engine/source/windowManager/mac/macView.mm
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "windowManager/mac/macView.h"
|
||||
#include "platform/event.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "console/console.h"
|
||||
#include "sim/actionMap.h"
|
||||
#include "app/mainLoop.h"
|
||||
|
||||
// For left/right side definitions.
|
||||
#include <IOKit/hidsystem/IOLLEvent.h>
|
||||
|
||||
|
||||
#define WHEEL_DELTA ( 120 * 0.1 )
|
||||
|
||||
static bool smApplicationInactive = false;
|
||||
|
||||
|
||||
extern InputModifiers convertModifierBits( const U32 in );
|
||||
|
||||
|
||||
inline U32 NSModifiersToTorqueModifiers( NSUInteger mods )
|
||||
{
|
||||
U32 torqueMods = 0;
|
||||
|
||||
if( mods & NX_DEVICELSHIFTKEYMASK )
|
||||
torqueMods |= IM_LSHIFT;
|
||||
if( mods & NX_DEVICERSHIFTKEYMASK )
|
||||
torqueMods |= IM_RSHIFT;
|
||||
if( mods & NX_DEVICELALTKEYMASK )
|
||||
torqueMods |= IM_LOPT;
|
||||
if( mods & NX_DEVICERALTKEYMASK )
|
||||
torqueMods |= IM_ROPT;
|
||||
if( mods & NX_DEVICELCTLKEYMASK )
|
||||
torqueMods |= IM_LCTRL;
|
||||
if( mods & NX_DEVICERCTLKEYMASK )
|
||||
torqueMods |= IM_RCTRL;
|
||||
if( mods & NX_DEVICELCMDKEYMASK )
|
||||
torqueMods |= IM_LALT;
|
||||
if( mods & NX_DEVICERCMDKEYMASK )
|
||||
torqueMods |= IM_RALT;
|
||||
|
||||
Input::setModifierKeys( convertModifierBits( torqueMods ) );
|
||||
|
||||
return torqueMods;
|
||||
}
|
||||
|
||||
|
||||
@implementation GGMacView
|
||||
- (void)setTorqueWindow:(MacWindow*)theWindow
|
||||
{
|
||||
mTorqueWindow = theWindow;
|
||||
mLastMods = 0;
|
||||
}
|
||||
|
||||
- (MacWindow*)torqueWindow
|
||||
{
|
||||
return mTorqueWindow;
|
||||
}
|
||||
|
||||
-(void)trackModState:(U32)torqueKey withMacMods:(U32)macMods event:(NSEvent*)theEvent
|
||||
{
|
||||
// track state:
|
||||
// translate the torque key code to the torque flag that changed
|
||||
// xor with existing mods for new mod state
|
||||
// clear anything that the mac says both siblings are not down ( to help stay in sync, a little bit )
|
||||
|
||||
// ?set left sibling of anything that the mac says some sibling is down, but that we don't see as down?
|
||||
|
||||
U32 torqueMod = 0;
|
||||
switch(torqueKey)
|
||||
{
|
||||
case KEY_LSHIFT: torqueMod = IM_LSHIFT; break;
|
||||
case KEY_RSHIFT: torqueMod = IM_RSHIFT; break;
|
||||
case KEY_LCONTROL: torqueMod = IM_LCTRL; break;
|
||||
case KEY_RCONTROL: torqueMod = IM_RCTRL; break;
|
||||
case KEY_MAC_LOPT: torqueMod = IM_LOPT; break;
|
||||
case KEY_MAC_ROPT: torqueMod = IM_ROPT; break;
|
||||
case KEY_LALT: torqueMod = IM_LALT; break;
|
||||
case KEY_RALT: torqueMod = IM_RALT; break;
|
||||
};
|
||||
|
||||
// flip the mod that we got an event for
|
||||
U32 newMods = mLastMods ^ torqueMod;
|
||||
|
||||
// clear left and right if mac thinks both are up.
|
||||
if( !(macMods & NSShiftKeyMask)) newMods &= ~IM_LSHIFT, newMods &= ~IM_RSHIFT;
|
||||
if( !(macMods & NSControlKeyMask)) newMods &= ~IM_LCTRL, newMods &= ~IM_RCTRL;
|
||||
if( !(macMods & NSAlternateKeyMask)) newMods &= ~IM_LOPT, newMods &= ~IM_ROPT;
|
||||
if( !(macMods & NSCommandKeyMask)) newMods &= ~IM_LALT, newMods &= ~IM_RALT;
|
||||
|
||||
// Generate keyUp/Down event (allows us to use modifier keys for actions)
|
||||
mLastMods = 0;
|
||||
[self rawKeyUpDown:theEvent keyDown:(newMods & torqueMod)];
|
||||
|
||||
mLastMods = newMods;
|
||||
|
||||
Input::setModifierKeys( convertModifierBits( mLastMods ) );
|
||||
}
|
||||
|
||||
- (Point2I)viewCoordsToTorqueCoords:(NSPoint)mousePoint
|
||||
{
|
||||
if(mTorqueWindow->isFullscreen())
|
||||
{
|
||||
CGRect bounds = mTorqueWindow->getDisplayBounds();
|
||||
CGRect mainbounds = mTorqueWindow->getMainDisplayBounds();
|
||||
F32 offsetY = mainbounds.size.height - (bounds.size.height + bounds.origin.y);
|
||||
Point2I pt(mousePoint.x - bounds.origin.x, bounds.size.height + offsetY - mousePoint.y);
|
||||
return pt;
|
||||
}
|
||||
return Point2I(mousePoint.x, mTorqueWindow->getClientExtent().y - mousePoint.y);
|
||||
}
|
||||
|
||||
- (void)signalGainFocus
|
||||
{
|
||||
if(smApplicationInactive)
|
||||
smApplicationInactive = false;
|
||||
|
||||
bool gainFocus = static_cast<MacWindowManager*>(WindowManager)->canWindowGainFocus(mTorqueWindow);
|
||||
if(gainFocus)
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), GainFocus);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Mouse Input
|
||||
// We're funnelling all the standard cocoa event handlers to -mouseUpDown and -mouseMotion.
|
||||
- (void)mouseDown:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:YES]; }
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:YES]; }
|
||||
- (void)otherMouseDown:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:YES]; }
|
||||
- (void)mouseUp:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:NO]; }
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:NO]; }
|
||||
- (void)otherMouseUp:(NSEvent *)theEvent { [self mouseUpDown:theEvent mouseDown:NO]; }
|
||||
- (void)mouseDragged:(NSEvent *)theEvent { [self mouseMotion:theEvent]; }
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent { [self mouseMotion:theEvent]; }
|
||||
- (void)otherMouseDragged:(NSEvent *)theEvent { [self mouseMotion:theEvent]; }
|
||||
- (void)mouseMoved:(NSEvent *)theEvent { [self mouseMotion:theEvent]; }
|
||||
|
||||
- (void)mouseUpDown:(NSEvent *)theEvent mouseDown:(BOOL)isMouseDown
|
||||
{
|
||||
Point2I eventLocation = [self viewCoordsToTorqueCoords: [theEvent locationInWindow]];
|
||||
U16 buttonNumber = [theEvent buttonNumber];
|
||||
U32 action = isMouseDown ? SI_MAKE : SI_BREAK;
|
||||
|
||||
// If the event location is negative then it occurred in the structure region (e.g. title bar, resize corner), and we don't want
|
||||
// to lock the mouse/drop into fullscreen for that.
|
||||
if(WindowManager->getFocusedWindow() != mTorqueWindow && eventLocation.x > 0 && eventLocation.y > 0)
|
||||
[self signalGainFocus];
|
||||
|
||||
mLastMods = NSModifiersToTorqueModifiers( [ theEvent modifierFlags ] );
|
||||
|
||||
mTorqueWindow->buttonEvent.trigger(mTorqueWindow->getWindowId(), mLastMods, action, buttonNumber);
|
||||
}
|
||||
|
||||
- (void)mouseMotion:(NSEvent *)theEvent
|
||||
{
|
||||
mTorqueWindow->_doMouseLockNow();
|
||||
|
||||
// when moving the mouse to the center of the window for mouse locking, we need
|
||||
// to skip the next mouse delta event
|
||||
if(mTorqueWindow->isMouseLocked() && mTorqueWindow->_skipNextMouseEvent())
|
||||
{
|
||||
mTorqueWindow->_skippedMouseEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
Point2I eventLocation;
|
||||
if(mTorqueWindow->isMouseLocked())
|
||||
{
|
||||
eventLocation.x = [theEvent deltaX];
|
||||
eventLocation.y = [theEvent deltaY];
|
||||
}
|
||||
else
|
||||
{
|
||||
eventLocation = [self viewCoordsToTorqueCoords:[theEvent locationInWindow]];
|
||||
}
|
||||
|
||||
mLastMods = NSModifiersToTorqueModifiers( [ theEvent modifierFlags ] );
|
||||
|
||||
mTorqueWindow->mouseEvent.trigger(mTorqueWindow->getWindowId(), mLastMods, eventLocation.x, eventLocation.y, mTorqueWindow->isMouseLocked());
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)theEvent
|
||||
{
|
||||
float deltaX = [ theEvent deltaX ];
|
||||
float deltaY = [ theEvent deltaY ];
|
||||
|
||||
if( mIsZero( deltaX ) && mIsZero( deltaY ) )
|
||||
return;
|
||||
|
||||
mLastMods = NSModifiersToTorqueModifiers( [ theEvent modifierFlags ] );
|
||||
|
||||
mTorqueWindow->wheelEvent.trigger( mTorqueWindow->getWindowId(), mLastMods, S32( deltaX * WHEEL_DELTA ), S32( deltaY * WHEEL_DELTA ) );
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Keyboard Input
|
||||
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
|
||||
{
|
||||
// Pass it off to the main menu. If the main menu handled it, we're done.
|
||||
if([[NSApp mainMenu] performKeyEquivalent:theEvent])
|
||||
return YES;
|
||||
|
||||
// cmd-q will quit. End of story.
|
||||
if(([theEvent modifierFlags] & NSCommandKeyMask && !([theEvent modifierFlags] & NSAlternateKeyMask) && !([theEvent modifierFlags] & NSControlKeyMask)) && [theEvent keyCode] == 0x0C)
|
||||
{
|
||||
StandardMainLoop::shutdown();
|
||||
[NSApp terminate:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// In fullscreen we grab ALL keyboard events, including ones which would normally be handled by the system,
|
||||
// like cmd-tab. Thus, we need to specifically check for cmd-tab and bail out of fullscreen and hide the app
|
||||
// to switch to the next application.
|
||||
// 0x30 is tab, so this grabs command-tab and command-shift-tab
|
||||
if([theEvent keyCode] == 0x30 && mTorqueWindow->isFullscreen())
|
||||
{
|
||||
// Bail!
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), LoseFocus);
|
||||
[NSApp hide:nil];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// All other events are uninteresting to us and can be handled by Torque.
|
||||
if([theEvent type] == NSKeyDown)
|
||||
[self keyDown:theEvent];
|
||||
else if([theEvent type] == NSKeyUp)
|
||||
[self keyUp:theEvent];
|
||||
|
||||
// Don't let the default handler continue processing these events, it does things we don't like.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)theEvent
|
||||
{
|
||||
U32 torqueKeyCode = TranslateOSKeyCode([theEvent keyCode]);
|
||||
U32 macMods = [theEvent modifierFlags];
|
||||
[self trackModState:torqueKeyCode withMacMods:macMods event:theEvent];
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
// If keyboard translation is on and the key isn't bound in the
|
||||
// global action map, first try turning this into one or more
|
||||
// character events.
|
||||
|
||||
if( mTorqueWindow->getKeyboardTranslation()
|
||||
&& !mTorqueWindow->shouldNotTranslate(
|
||||
convertModifierBits( NSModifiersToTorqueModifiers( [ theEvent modifierFlags ] ) ),
|
||||
( InputObjectInstances ) TranslateOSKeyCode( [ theEvent keyCode ] ) ) )
|
||||
{
|
||||
mHandledAsCharEvent = false;
|
||||
[ self interpretKeyEvents: [ NSArray arrayWithObject: theEvent ] ];
|
||||
|
||||
if( mHandledAsCharEvent )
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire as raw keyboard event.
|
||||
|
||||
[ self rawKeyUpDown: theEvent keyDown: YES ];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self rawKeyUpDown:theEvent keyDown:NO];
|
||||
}
|
||||
|
||||
- (void)rawKeyUpDown:(NSEvent *)theEvent keyDown:(BOOL)isKeyDown
|
||||
{
|
||||
U32 action;
|
||||
if([theEvent type] != NSFlagsChanged)
|
||||
action = isKeyDown ? ([theEvent isARepeat] ? SI_REPEAT : SI_MAKE) : SI_BREAK;
|
||||
else
|
||||
action = isKeyDown ? SI_MAKE : SI_BREAK;
|
||||
|
||||
U32 torqueKeyCode = TranslateOSKeyCode([theEvent keyCode]);
|
||||
mLastMods = NSModifiersToTorqueModifiers( [ theEvent modifierFlags ] );
|
||||
|
||||
mTorqueWindow->keyEvent.trigger(mTorqueWindow->getWindowId(), mLastMods, action, torqueKeyCode);
|
||||
}
|
||||
|
||||
- (void)insertText:(id)_inString
|
||||
{
|
||||
// input string may be an NSString or an NSAttributedString
|
||||
NSString *text = [_inString isKindOfClass:[NSAttributedString class]] ? [_inString string] : _inString;
|
||||
for(int i = 0; i < [text length]; i++)
|
||||
{
|
||||
mTorqueWindow->charEvent.trigger(mTorqueWindow->getWindowId(), mLastMods, [text characterAtIndex:i]);
|
||||
mHandledAsCharEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Application Delegate
|
||||
- (void)applicationDidResignActive:(NSNotification *)aNotification
|
||||
{
|
||||
smApplicationInactive = true;
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), LoseFocus);
|
||||
[NSApp setDelegate:nil];
|
||||
}
|
||||
|
||||
- (void)applicationDidHide:(NSNotification *)aNotification
|
||||
{
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), LoseFocus);
|
||||
}
|
||||
|
||||
- (void)applicationDidUnhide:(NSNotification *)aNotification
|
||||
{
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), GainFocus);
|
||||
}
|
||||
|
||||
#ifndef TORQUE_SHARED
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender
|
||||
{
|
||||
Platform::postQuitMessage(0);
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Window Delegate
|
||||
- (BOOL)windowShouldClose:(NSWindow *)sender
|
||||
{
|
||||
// We close the window ourselves
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), WindowDestroy);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *) notification
|
||||
{
|
||||
mTorqueWindow->_disassociateCocoaWindow();
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||
{
|
||||
// when our window is the key window, we become the app delegate.
|
||||
PlatformWindow* focusWindow = WindowManager->getFocusedWindow();
|
||||
if(focusWindow && focusWindow != mTorqueWindow)
|
||||
focusWindow->appEvent.trigger(mTorqueWindow->getWindowId(), LoseFocus);
|
||||
[NSApp setDelegate:self];
|
||||
[self signalGainFocus];
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification*)notification
|
||||
{
|
||||
mTorqueWindow->appEvent.trigger(mTorqueWindow->getWindowId(), LoseScreen);
|
||||
mTorqueWindow->_associateMouse();
|
||||
mTorqueWindow->setCursorVisible(true);
|
||||
[NSApp setDelegate:nil];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeScreen:(NSNotification*)notification
|
||||
{
|
||||
NSWindow* wnd = [notification object];
|
||||
// TODO: Add a category to NSScreen to deal with this
|
||||
CGDirectDisplayID disp = (CGDirectDisplayID)[[[[wnd screen] deviceDescription] valueForKey:@"NSScreenNumber"] unsignedIntValue];
|
||||
mTorqueWindow->setDisplay(disp);
|
||||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification*)notification
|
||||
{
|
||||
Point2I clientExtent = mTorqueWindow->getClientExtent();
|
||||
mTorqueWindow->resizeEvent.trigger(mTorqueWindow->getWindowId(), clientExtent.x, clientExtent.y);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark responder status
|
||||
- (BOOL)acceptsFirstResponder { return YES; }
|
||||
- (BOOL)becomeFirstResponder { return YES; }
|
||||
- (BOOL)resignFirstResponder { return YES; }
|
||||
|
||||
// Basic implementation because NSResponder's default implementation can cause infinite loops when our keyDown: method calls interpretKeyEvents:
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
if([self respondsToSelector:aSelector])
|
||||
[self performSelector:aSelector withObject:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
191
Engine/source/windowManager/mac/macWindow.h
Normal file
191
Engine/source/windowManager/mac/macWindow.h
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TORQUE_MACWINDOW_H_
|
||||
#define _TORQUE_MACWINDOW_H_
|
||||
|
||||
#include "windowManager/platformWindow.h"
|
||||
#include "windowManager/mac/macWindowManager.h"
|
||||
#include "windowManager/mac/macCursorController.h"
|
||||
|
||||
#ifndef _GFXTARGET_H_
|
||||
#include "gfx/gfxTarget.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXSTRUCTS_H_
|
||||
#include "gfx/gfxStructs.h"
|
||||
#endif
|
||||
|
||||
class MacWindow : public PlatformWindow
|
||||
{
|
||||
public:
|
||||
virtual ~MacWindow();
|
||||
|
||||
virtual GFXDevice *getGFXDevice() { return mDevice; }
|
||||
virtual GFXWindowTarget *getGFXTarget() { return mTarget; }
|
||||
virtual void setVideoMode(const GFXVideoMode &mode);
|
||||
virtual const GFXVideoMode &getVideoMode() { return mCurrentMode; }
|
||||
|
||||
virtual WindowId getWindowId() { return mWindowId; }
|
||||
|
||||
void setDisplay(CGDirectDisplayID display);
|
||||
CGDirectDisplayID getDisplay() { return mDisplay; }
|
||||
CGRect getMainDisplayBounds() { return mMainDisplayBounds; }
|
||||
CGRect getDisplayBounds() { return mDisplayBounds; }
|
||||
|
||||
virtual bool clearFullscreen()
|
||||
{
|
||||
// TODO: properly drop out of full screen
|
||||
return true;
|
||||
}
|
||||
virtual bool isFullscreen() { return mFullscreen; }
|
||||
|
||||
virtual PlatformWindow * getNextWindow() const;
|
||||
|
||||
virtual void setMouseLocked( bool enable )
|
||||
{
|
||||
mShouldMouseLock = enable;
|
||||
if(isFocused())
|
||||
_doMouseLockNow();
|
||||
}
|
||||
virtual bool isMouseLocked() const { return mMouseLocked; }
|
||||
virtual bool shouldLockMouse() const { return mShouldMouseLock; }
|
||||
|
||||
virtual bool setSize(const Point2I &newSize);
|
||||
|
||||
virtual void setClientExtent( const Point2I newExtent );
|
||||
virtual const Point2I getClientExtent();
|
||||
|
||||
virtual void setBounds( const RectI &newBounds );
|
||||
virtual const RectI getBounds() const;
|
||||
|
||||
virtual void setPosition( const Point2I newPosition );
|
||||
virtual const Point2I getPosition();
|
||||
|
||||
virtual void centerWindow();
|
||||
|
||||
virtual Point2I clientToScreen( const Point2I& pos );
|
||||
virtual Point2I screenToClient( const Point2I& pos );
|
||||
|
||||
virtual bool setCaption(const char *windowText);
|
||||
virtual const char *getCaption() { return mTitle; }
|
||||
|
||||
virtual bool setType( S32 windowType ) { return true; }
|
||||
|
||||
virtual void minimize();
|
||||
virtual void maximize();
|
||||
virtual void restore();
|
||||
virtual bool isMinimized();
|
||||
virtual bool isMaximized();
|
||||
virtual void show();
|
||||
virtual void close();
|
||||
virtual void hide();
|
||||
virtual bool isOpen();
|
||||
virtual bool isVisible();
|
||||
|
||||
virtual bool isFocused();
|
||||
virtual void setFocus();
|
||||
virtual void clearFocus();
|
||||
|
||||
virtual void* getPlatformDrawable() const;
|
||||
|
||||
// TODO: These should be private, but GGMacView (an Obj-C class) needs access to these and we can't friend Obj-C classes
|
||||
bool _skipNextMouseEvent() { return mSkipMouseEvents != 0; }
|
||||
void _skipAnotherMouseEvent() { mSkipMouseEvents++; }
|
||||
void _skippedMouseEvent() { mSkipMouseEvents--; }
|
||||
|
||||
/// Does the work of actually locking or unlocking the mouse, based on the
|
||||
/// value of shouldLockMouse().
|
||||
///
|
||||
/// Disassociates the cursor movement from the mouse input and hides the mouse
|
||||
/// when locking. Re-associates cursor movement with mouse input and shows the
|
||||
/// mouse when unlocking.
|
||||
///
|
||||
/// Returns true if we locked or unlocked the mouse. Returns false if the mouse
|
||||
/// was already in the correct state.
|
||||
void _doMouseLockNow();
|
||||
|
||||
// Helper methods for doMouseLockNow
|
||||
void _associateMouse();
|
||||
void _dissociateMouse();
|
||||
void _centerMouse();
|
||||
|
||||
// For GGMacView
|
||||
void _disassociateCocoaWindow();
|
||||
|
||||
// Safari support methods
|
||||
static void setSafariWindow(NSWindow *window, S32 x = 0, S32 y = 0, S32 width = 0, S32 height = 0);
|
||||
static void hideBrowserWindow(bool hide);
|
||||
|
||||
protected:
|
||||
virtual void _setFullscreen(bool fullScreen);
|
||||
|
||||
private:
|
||||
friend class MacWindowManager;
|
||||
friend class MacCursorController;
|
||||
|
||||
struct SafariWindowInfo
|
||||
{
|
||||
NSWindow* safariWindow; /* The Safari Browser Window */
|
||||
S32 x; /* Position of top left corner relative */
|
||||
S32 y; /* to a safari page. */
|
||||
U32 width; /* Maximum window size */
|
||||
U32 height;
|
||||
};
|
||||
|
||||
MacWindow(U32 windowId, const char* windowText, Point2I clientExtent);
|
||||
|
||||
void _initCocoaWindow(const char* windowText, Point2I clientExtent);
|
||||
void setWindowId(U32 newid) { mWindowId = newid;}
|
||||
void signalGainFocus();
|
||||
|
||||
static SafariWindowInfo* sSafariWindowInfo;
|
||||
static MacWindow* sInstance;
|
||||
|
||||
NSWindow* mCocoaWindow;
|
||||
GFXDevice *mDevice;
|
||||
GFXWindowTargetRef mTarget;
|
||||
GFXVideoMode mCurrentMode;
|
||||
|
||||
MacWindow *mNextWindow;
|
||||
|
||||
bool mMouseLocked;
|
||||
bool mShouldMouseLock;
|
||||
|
||||
const char* mTitle;
|
||||
bool mMouseCaptured;
|
||||
|
||||
MacWindowManager* mOwningWindowManager;
|
||||
U32 mSkipMouseEvents;
|
||||
|
||||
bool mFullscreen;
|
||||
bool mShouldFullscreen;
|
||||
NSDictionary* mDefaultDisplayMode;
|
||||
|
||||
void _onAppEvent(WindowId,S32);
|
||||
|
||||
CGDirectDisplayID mDisplay;
|
||||
CGRect mDisplayBounds;
|
||||
CGRect mMainDisplayBounds;
|
||||
};
|
||||
|
||||
#endif
|
||||
594
Engine/source/windowManager/mac/macWindow.mm
Normal file
594
Engine/source/windowManager/mac/macWindow.mm
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
#include "windowManager/mac/macView.h"
|
||||
|
||||
#include "console/console.h"
|
||||
|
||||
MacWindow::SafariWindowInfo* MacWindow::sSafariWindowInfo = NULL;
|
||||
MacWindow* MacWindow::sInstance = NULL;
|
||||
|
||||
@interface SafariBrowserWindow : NSWindow
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SafariBrowserWindow
|
||||
|
||||
// Windows created with NSBorderlessWindowMask normally can't be key, but we want ours to be
|
||||
- (BOOL) canBecomeKeyWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
MacWindow::MacWindow(U32 windowId, const char* windowText, Point2I clientExtent)
|
||||
{
|
||||
mMouseLocked = false;
|
||||
mShouldMouseLock = false;
|
||||
mTitle = NULL;
|
||||
mMouseCaptured = false;
|
||||
|
||||
mCocoaWindow = NULL;
|
||||
mCursorController = new MacCursorController( this );
|
||||
mOwningWindowManager = NULL;
|
||||
|
||||
mFullscreen = false;
|
||||
mShouldFullscreen = false;
|
||||
mDefaultDisplayMode = NULL;
|
||||
|
||||
mSkipMouseEvents = 0;
|
||||
|
||||
mDisplay = kCGDirectMainDisplay;
|
||||
mMainDisplayBounds = mDisplayBounds = CGDisplayBounds(mDisplay);
|
||||
|
||||
mWindowId = windowId;
|
||||
_initCocoaWindow(windowText, clientExtent);
|
||||
|
||||
appEvent.notify(this, &MacWindow::_onAppEvent);
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
MacWindow::~MacWindow()
|
||||
{
|
||||
if(mFullscreen)
|
||||
_setFullscreen(false);
|
||||
|
||||
appEvent.remove(this, &MacWindow::_onAppEvent);
|
||||
|
||||
//ensure our view isn't the delegate
|
||||
[NSApp setDelegate:nil];
|
||||
|
||||
if( mCocoaWindow )
|
||||
{
|
||||
NSWindow* window = mCocoaWindow;
|
||||
_disassociateCocoaWindow();
|
||||
|
||||
[ window close ];
|
||||
}
|
||||
|
||||
appEvent.trigger(mWindowId, LoseFocus);
|
||||
appEvent.trigger(mWindowId, WindowDestroy);
|
||||
|
||||
mOwningWindowManager->_removeWindow(this);
|
||||
|
||||
setSafariWindow(NULL);
|
||||
|
||||
sInstance = NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void torque_setsafariwindow( NSWindow *window, S32 x, S32 y, S32 width, S32 height)
|
||||
{
|
||||
MacWindow::setSafariWindow(window, x, y, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MacWindow::hideBrowserWindow(bool hide)
|
||||
{
|
||||
if (sSafariWindowInfo && sInstance && sInstance->mCocoaWindow)
|
||||
{
|
||||
if (hide)
|
||||
{
|
||||
if (sSafariWindowInfo && sSafariWindowInfo->safariWindow)
|
||||
[sSafariWindowInfo->safariWindow removeChildWindow: sInstance->mCocoaWindow];
|
||||
|
||||
sInstance->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (sSafariWindowInfo && sSafariWindowInfo->safariWindow)
|
||||
[sSafariWindowInfo->safariWindow addChildWindow: sInstance->mCocoaWindow ordered:NSWindowAbove];
|
||||
|
||||
sInstance->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::setSafariWindow(NSWindow *window, S32 x, S32 y, S32 width, S32 height )
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
hideBrowserWindow(true);
|
||||
|
||||
if (sSafariWindowInfo)
|
||||
delete sSafariWindowInfo;
|
||||
|
||||
sSafariWindowInfo = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sSafariWindowInfo)
|
||||
{
|
||||
sSafariWindowInfo = new SafariWindowInfo;
|
||||
sSafariWindowInfo->safariWindow = window;
|
||||
sSafariWindowInfo->width = width;
|
||||
sSafariWindowInfo->height = height;
|
||||
sSafariWindowInfo->x = x;
|
||||
sSafariWindowInfo->y = y;
|
||||
if (sInstance && sInstance->mCocoaWindow)
|
||||
{
|
||||
[window addChildWindow: sInstance->mCocoaWindow ordered:NSWindowAbove];
|
||||
hideBrowserWindow(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sSafariWindowInfo->width = width;
|
||||
sSafariWindowInfo->height = height;
|
||||
sSafariWindowInfo->x = x;
|
||||
sSafariWindowInfo->y = y;
|
||||
}
|
||||
|
||||
if (sInstance && sInstance->mCocoaWindow)
|
||||
{
|
||||
//update position
|
||||
|
||||
NSRect frame = [sSafariWindowInfo->safariWindow frame];
|
||||
|
||||
NSPoint o = { (float)sSafariWindowInfo->x, frame.size.height - sSafariWindowInfo->y };
|
||||
NSPoint p = [sSafariWindowInfo->safariWindow convertBaseToScreen: o];
|
||||
|
||||
NSRect contentRect = NSMakeRect(p.x, p.y - sSafariWindowInfo->height, sSafariWindowInfo->width,sSafariWindowInfo->height);
|
||||
|
||||
// we have to set display to NO when resizing otherwise get hangs, perhaps add delegate to SafariBrowserWindow class?
|
||||
[sInstance->mCocoaWindow setFrame:contentRect display:NO];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MacWindow::_initCocoaWindow(const char* windowText, Point2I clientExtent)
|
||||
{
|
||||
// TODO: cascade windows on screen?
|
||||
|
||||
// create the window
|
||||
NSRect contentRect;
|
||||
U32 style;
|
||||
|
||||
if (sSafariWindowInfo)
|
||||
{
|
||||
|
||||
NSRect frame = [sSafariWindowInfo->safariWindow frame];
|
||||
|
||||
NSPoint o = { (float)sSafariWindowInfo->x, frame.size.height - sSafariWindowInfo->y };
|
||||
|
||||
NSPoint p = [sSafariWindowInfo->safariWindow convertBaseToScreen: o];
|
||||
|
||||
contentRect = NSMakeRect(0, 0, sSafariWindowInfo->width,sSafariWindowInfo->height);
|
||||
|
||||
style = NSBorderlessWindowMask;
|
||||
|
||||
mCocoaWindow = [[SafariBrowserWindow alloc] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:YES screen:nil];
|
||||
|
||||
[mCocoaWindow setFrameTopLeftPoint: p];
|
||||
|
||||
[sSafariWindowInfo->safariWindow addChildWindow: mCocoaWindow ordered:NSWindowAbove];
|
||||
|
||||
// necessary to accept mouseMoved events
|
||||
[mCocoaWindow setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
contentRect = NSMakeRect(0,0,clientExtent.x, clientExtent.y);
|
||||
|
||||
style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask;
|
||||
|
||||
mCocoaWindow = [[NSWindow alloc] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:YES screen:nil];
|
||||
if(windowText)
|
||||
[mCocoaWindow setTitle: [NSString stringWithUTF8String: windowText]];
|
||||
|
||||
// necessary to accept mouseMoved events
|
||||
[mCocoaWindow setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
// correctly position the window on screen
|
||||
[mCocoaWindow center];
|
||||
|
||||
}
|
||||
|
||||
// create the opengl view. we don't care about its pixel format, because we
|
||||
// will be replacing its context with another one.
|
||||
GGMacView* view = [[GGMacView alloc] initWithFrame:contentRect pixelFormat:[NSOpenGLView defaultPixelFormat]];
|
||||
[view setTorqueWindow:this];
|
||||
[mCocoaWindow setContentView:view];
|
||||
[mCocoaWindow setDelegate:view];
|
||||
|
||||
}
|
||||
|
||||
void MacWindow::_disassociateCocoaWindow()
|
||||
{
|
||||
if( !mCocoaWindow )
|
||||
return;
|
||||
|
||||
[mCocoaWindow setContentView:nil];
|
||||
[mCocoaWindow setDelegate:nil];
|
||||
|
||||
if (sSafariWindowInfo)
|
||||
[sSafariWindowInfo->safariWindow removeChildWindow: mCocoaWindow];
|
||||
|
||||
mCocoaWindow = NULL;
|
||||
}
|
||||
|
||||
void MacWindow::setVideoMode(const GFXVideoMode &mode)
|
||||
{
|
||||
mCurrentMode = mode;
|
||||
setSize(mCurrentMode.resolution);
|
||||
|
||||
if(mTarget.isValid())
|
||||
mTarget->resetMode();
|
||||
|
||||
_setFullscreen(mCurrentMode.fullScreen);
|
||||
}
|
||||
|
||||
void MacWindow::_onAppEvent(WindowId, S32 evt)
|
||||
{
|
||||
if(evt == LoseFocus && isFullscreen())
|
||||
{
|
||||
mShouldFullscreen = true;
|
||||
GFXVideoMode mode = mCurrentMode;
|
||||
mode.fullScreen = false;
|
||||
setVideoMode(mode);
|
||||
}
|
||||
|
||||
if(evt == GainFocus && !isFullscreen() && mShouldFullscreen)
|
||||
{
|
||||
mShouldFullscreen = false;
|
||||
GFXVideoMode mode = mCurrentMode;
|
||||
mode.fullScreen = true;
|
||||
setVideoMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::_setFullscreen(bool fullScreen)
|
||||
{
|
||||
if(mFullscreen == fullScreen)
|
||||
return;
|
||||
|
||||
mFullscreen = fullScreen;
|
||||
|
||||
if(mFullscreen)
|
||||
{
|
||||
Con::printf("Capturing display %x", mDisplay);
|
||||
CGDisplayCapture(mDisplay);
|
||||
[mCocoaWindow setAlphaValue:0.0f];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mDefaultDisplayMode)
|
||||
{
|
||||
Con::printf("Restoring default display mode... width: %i height: %i bpp: %i", [[mDefaultDisplayMode valueForKey:@"Width"] intValue],
|
||||
[[mDefaultDisplayMode valueForKey:@"Height"] intValue], [[mDefaultDisplayMode valueForKey:@"BitsPerPixel"] intValue]);
|
||||
CGDisplaySwitchToMode(mDisplay, (CFDictionaryRef)mDefaultDisplayMode);
|
||||
mDisplayBounds = CGDisplayBounds(mDisplay);
|
||||
if(mDisplay == kCGDirectMainDisplay)
|
||||
mMainDisplayBounds = mDisplayBounds;
|
||||
}
|
||||
|
||||
Con::printf("Releasing display %x", mDisplay);
|
||||
CGDisplayRelease(mDisplay);
|
||||
[mCocoaWindow setAlphaValue:1.0f];
|
||||
mDefaultDisplayMode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void* MacWindow::getPlatformDrawable() const
|
||||
{
|
||||
return [mCocoaWindow contentView];
|
||||
}
|
||||
|
||||
void MacWindow::show()
|
||||
{
|
||||
[mCocoaWindow makeKeyAndOrderFront:nil];
|
||||
[mCocoaWindow makeFirstResponder:[mCocoaWindow contentView]];
|
||||
appEvent.trigger(getWindowId(), WindowShown);
|
||||
appEvent.trigger(getWindowId(), GainFocus);
|
||||
}
|
||||
|
||||
void MacWindow::close()
|
||||
{
|
||||
[mCocoaWindow close];
|
||||
appEvent.trigger(mWindowId, LoseFocus);
|
||||
appEvent.trigger(mWindowId, WindowDestroy);
|
||||
|
||||
mOwningWindowManager->_removeWindow(this);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void MacWindow::hide()
|
||||
{
|
||||
[mCocoaWindow orderOut:nil];
|
||||
appEvent.trigger(getWindowId(), WindowHidden);
|
||||
}
|
||||
|
||||
void MacWindow::setDisplay(CGDirectDisplayID display)
|
||||
{
|
||||
mDisplay = display;
|
||||
mDisplayBounds = CGDisplayBounds(mDisplay);
|
||||
}
|
||||
|
||||
PlatformWindow* MacWindow::getNextWindow() const
|
||||
{
|
||||
return mNextWindow;
|
||||
}
|
||||
|
||||
bool MacWindow::setSize(const Point2I &newSize)
|
||||
{
|
||||
if (sSafariWindowInfo)
|
||||
return true;
|
||||
|
||||
NSSize newExtent = {newSize.x, newSize.y};
|
||||
[mCocoaWindow setContentSize:newExtent];
|
||||
[mCocoaWindow center];
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacWindow::setClientExtent( const Point2I newExtent )
|
||||
{
|
||||
if(!mFullscreen)
|
||||
{
|
||||
// Set the Client Area Extent (Resolution) of this window
|
||||
NSSize newSize = {newExtent.x, newExtent.y};
|
||||
[mCocoaWindow setContentSize:newSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
// In fullscreen we have to resize the monitor (it'll be good to change it back too...)
|
||||
if(!mDefaultDisplayMode)
|
||||
mDefaultDisplayMode = (NSDictionary*)CGDisplayCurrentMode(mDisplay);
|
||||
|
||||
NSDictionary* newMode = (NSDictionary*)CGDisplayBestModeForParameters(mDisplay, 32, newExtent.x, newExtent.y, NULL);
|
||||
Con::printf("Switching to new display mode... width: %i height: %i bpp: %i",
|
||||
[[newMode valueForKey:@"Width"] intValue], [[newMode valueForKey:@"Height"] intValue], [[newMode valueForKey:@"BitsPerPixel"] intValue]);
|
||||
CGDisplaySwitchToMode(mDisplay, (CFDictionaryRef)newMode);
|
||||
mDisplayBounds = CGDisplayBounds(mDisplay);
|
||||
if(mDisplay == kCGDirectMainDisplay)
|
||||
mMainDisplayBounds = mDisplayBounds;
|
||||
}
|
||||
}
|
||||
|
||||
const Point2I MacWindow::getClientExtent()
|
||||
{
|
||||
if(!mFullscreen)
|
||||
{
|
||||
// Get the Client Area Extent (Resolution) of this window
|
||||
NSSize size = [[mCocoaWindow contentView] frame].size;
|
||||
return Point2I(size.width, size.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Point2I(mDisplayBounds.size.width, mDisplayBounds.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::setBounds( const RectI &newBounds )
|
||||
{
|
||||
NSRect newFrame = NSMakeRect(newBounds.point.x, newBounds.point.y, newBounds.extent.x, newBounds.extent.y);
|
||||
[mCocoaWindow setFrame:newFrame display:YES];
|
||||
}
|
||||
|
||||
const RectI MacWindow::getBounds() const
|
||||
{
|
||||
if(!mFullscreen)
|
||||
{
|
||||
// Get the position and size (fullscreen windows are always at (0,0)).
|
||||
NSRect frame = [mCocoaWindow frame];
|
||||
return RectI(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RectI(0, 0, mDisplayBounds.size.width, mDisplayBounds.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
void MacWindow::setPosition( const Point2I newPosition )
|
||||
{
|
||||
NSScreen *screen = [mCocoaWindow screen];
|
||||
NSRect screenFrame = [screen frame];
|
||||
|
||||
NSPoint pos = {newPosition.x, newPosition.y + screenFrame.size.height};
|
||||
[mCocoaWindow setFrameTopLeftPoint: pos];
|
||||
}
|
||||
|
||||
const Point2I MacWindow::getPosition()
|
||||
{
|
||||
NSScreen *screen = [mCocoaWindow screen];
|
||||
NSRect screenFrame = [screen frame];
|
||||
NSRect frame = [mCocoaWindow frame];
|
||||
|
||||
return Point2I(frame.origin.x, screenFrame.size.height - (frame.origin.y + frame.size.height));
|
||||
}
|
||||
|
||||
void MacWindow::centerWindow()
|
||||
{
|
||||
[mCocoaWindow center];
|
||||
}
|
||||
|
||||
Point2I MacWindow::clientToScreen( const Point2I& pos )
|
||||
{
|
||||
NSPoint p = { pos.x, pos.y };
|
||||
|
||||
p = [ mCocoaWindow convertBaseToScreen: p ];
|
||||
return Point2I( p.x, p.y );
|
||||
}
|
||||
|
||||
Point2I MacWindow::screenToClient( const Point2I& pos )
|
||||
{
|
||||
NSPoint p = { pos.x, pos.y };
|
||||
|
||||
p = [ mCocoaWindow convertScreenToBase: p ];
|
||||
return Point2I( p.x, p.y );
|
||||
}
|
||||
|
||||
bool MacWindow::isFocused()
|
||||
{
|
||||
return [mCocoaWindow isKeyWindow];
|
||||
}
|
||||
|
||||
bool MacWindow::isOpen()
|
||||
{
|
||||
// Maybe check if _window != NULL ?
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacWindow::isVisible()
|
||||
{
|
||||
return !isMinimized() && ([mCocoaWindow isVisible] == YES);
|
||||
}
|
||||
|
||||
void MacWindow::setFocus()
|
||||
{
|
||||
[mCocoaWindow makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
void MacWindow::signalGainFocus()
|
||||
{
|
||||
if(isFocused())
|
||||
[[mCocoaWindow delegate] performSelector:@selector(signalGainFocus)];
|
||||
}
|
||||
|
||||
void MacWindow::minimize()
|
||||
{
|
||||
if(!isVisible())
|
||||
return;
|
||||
|
||||
[mCocoaWindow miniaturize:nil];
|
||||
appEvent.trigger(getWindowId(), WindowHidden);
|
||||
}
|
||||
|
||||
void MacWindow::maximize()
|
||||
{
|
||||
if(!isVisible())
|
||||
return;
|
||||
|
||||
// GFX2_RENDER_MERGE
|
||||
//[mCocoaWindow miniaturize:nil];
|
||||
//appEvent.trigger(getWindowId(), WindowHidden);
|
||||
}
|
||||
|
||||
void MacWindow::restore()
|
||||
{
|
||||
if(!isMinimized())
|
||||
return;
|
||||
|
||||
[mCocoaWindow deminiaturize:nil];
|
||||
appEvent.trigger(getWindowId(), WindowShown);
|
||||
}
|
||||
|
||||
bool MacWindow::isMinimized()
|
||||
{
|
||||
return [mCocoaWindow isMiniaturized] == YES;
|
||||
}
|
||||
|
||||
bool MacWindow::isMaximized()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacWindow::clearFocus()
|
||||
{
|
||||
// Clear the focus state for this Window.
|
||||
// If the Window does not have focus, nothing happens.
|
||||
// If the Window has focus, it relinquishes it's focus to the Operating System
|
||||
|
||||
// TODO: find out if we can do anything correct here. We are instructed *not* to call [NSWindow resignKeyWindow], and we don't necessarily have another window to assign as key.
|
||||
}
|
||||
|
||||
bool MacWindow::setCaption(const char* windowText)
|
||||
{
|
||||
mTitle = windowText;
|
||||
[mCocoaWindow setTitle:[NSString stringWithUTF8String:mTitle]];
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacWindow::_doMouseLockNow()
|
||||
{
|
||||
if(!isVisible())
|
||||
return;
|
||||
|
||||
if(mShouldMouseLock == mMouseLocked && mMouseLocked != isCursorVisible())
|
||||
return;
|
||||
|
||||
if(mShouldMouseLock)
|
||||
_dissociateMouse();
|
||||
else
|
||||
_associateMouse();
|
||||
|
||||
// hide the cursor if we're locking, show it if we're unlocking
|
||||
setCursorVisible(!shouldLockMouse());
|
||||
|
||||
mMouseLocked = mShouldMouseLock;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MacWindow::_associateMouse()
|
||||
{
|
||||
CGAssociateMouseAndMouseCursorPosition(true);
|
||||
}
|
||||
|
||||
void MacWindow::_dissociateMouse()
|
||||
{
|
||||
_centerMouse();
|
||||
CGAssociateMouseAndMouseCursorPosition(false);
|
||||
}
|
||||
|
||||
void MacWindow::_centerMouse()
|
||||
{
|
||||
NSRect frame = [mCocoaWindow frame];
|
||||
|
||||
// Deal with the y flip (really fun when more than one monitor is involved)
|
||||
F32 offsetY = mMainDisplayBounds.size.height - mDisplayBounds.size.height;
|
||||
frame.origin.y = (mDisplayBounds.size.height + offsetY) - (S32)frame.origin.y - (S32)frame.size.height;
|
||||
mCursorController->setCursorPosition(frame.origin.x + frame.size.width / 2, frame.origin.y + frame.size.height / 2);
|
||||
}
|
||||
129
Engine/source/windowManager/mac/macWindowManager.h
Normal file
129
Engine/source/windowManager/mac/macWindowManager.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MACWINDOWMANAGER_H_
|
||||
#define _MACWINDOWMANAGER_H_
|
||||
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
class MacWindow;
|
||||
|
||||
class MacWindowManager : public PlatformWindowManager
|
||||
{
|
||||
private:
|
||||
typedef VectorPtr<MacWindow*> WindowList;
|
||||
WindowList mWindowList;
|
||||
U32 mFadeToken;
|
||||
Delegate<bool(void)> mNotifyShutdownDelegate;
|
||||
|
||||
public:
|
||||
MacWindowManager();
|
||||
~MacWindowManager();
|
||||
|
||||
virtual void setParentWindow(void* newParent) {
|
||||
}
|
||||
|
||||
/// Get the parent window
|
||||
virtual void* getParentWindow()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual PlatformWindow *createWindow(GFXDevice *device, const GFXVideoMode &mode);
|
||||
|
||||
/// @name Desktop Queries
|
||||
/// @{
|
||||
|
||||
/// Return the extents in window coordinates of the primary desktop
|
||||
/// area. On a single monitor system this is just the display extents.
|
||||
/// On a multi-monitor system this is the primary monitor (which Torque should
|
||||
/// launch on).
|
||||
virtual RectI getPrimaryDesktopArea();
|
||||
|
||||
/// Populate a vector with all monitors and their extents in window space.
|
||||
virtual void getMonitorRegions(Vector<RectI> ®ions);
|
||||
|
||||
/// Retrieve the currently set desktop bit depth
|
||||
/// @return The current desktop bit depth, or -1 if an error occurred
|
||||
virtual S32 getDesktopBitDepth();
|
||||
|
||||
/// Retrieve the currently set desktop resolution
|
||||
/// @return The current desktop bit depth, or Point2I(-1,-1) if an error occurred
|
||||
virtual Point2I getDesktopResolution();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Window Lookup
|
||||
/// @{
|
||||
|
||||
/// Get the number of Window's in this system
|
||||
virtual S32 getWindowCount();
|
||||
|
||||
/// Populate a list with references to all the windows created from this manager.
|
||||
virtual void getWindows(VectorPtr<PlatformWindow*> &windows);
|
||||
|
||||
/// Get a window from a device ID.
|
||||
///
|
||||
/// @return The window associated with the specified ID, or NULL if no
|
||||
/// match was found.
|
||||
virtual PlatformWindow *getWindowById(WindowId id);
|
||||
|
||||
virtual PlatformWindow *getFirstWindow();
|
||||
virtual PlatformWindow* getFocusedWindow();
|
||||
|
||||
/// During full-screen toggles we want to suppress ugly transition states,
|
||||
/// which we do (on Win32) by showing and hiding a full-monitor black window.
|
||||
///
|
||||
/// This method cues the appearance of that window ("lowering the curtain").
|
||||
virtual void lowerCurtain();
|
||||
|
||||
/// @see lowerCurtain
|
||||
///
|
||||
/// This method removes the curtain window.
|
||||
virtual void raiseCurtain();
|
||||
|
||||
/// @}
|
||||
/// @name Command Line Usage
|
||||
/// @{
|
||||
|
||||
/// Process command line arguments sent to this window manager
|
||||
/// to manipulate it's windows.
|
||||
virtual void _processCmdLineArgs(const S32 argc, const char **argv);
|
||||
|
||||
/// @}
|
||||
|
||||
// static MacWindowManager* get() { return (MacWindowManager*)PlatformWindowManager::get(); }
|
||||
void _addWindow(MacWindow* window);
|
||||
void _removeWindow(MacWindow* window);
|
||||
|
||||
void _onAppSignal(WindowId wnd, S32 event);
|
||||
|
||||
bool onShutdown();
|
||||
bool canWindowGainFocus(MacWindow* window);
|
||||
|
||||
|
||||
private:
|
||||
bool mIsShuttingDown;
|
||||
};
|
||||
|
||||
#endif
|
||||
245
Engine/source/windowManager/mac/macWindowManager.mm
Normal file
245
Engine/source/windowManager/mac/macWindowManager.mm
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "windowManager/mac/macWindowManager.h"
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
#include "core/util/journal/process.h"
|
||||
#include "console/console.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
|
||||
PlatformWindowManager* CreatePlatformWindowManager()
|
||||
{
|
||||
return new MacWindowManager();
|
||||
}
|
||||
|
||||
static inline RectI convertCGRectToRectI(NSRect r)
|
||||
{
|
||||
return RectI(r.origin.x, r.origin.y, r.size.width, r.size.height);
|
||||
}
|
||||
|
||||
MacWindowManager::MacWindowManager() : mNotifyShutdownDelegate(this, &MacWindowManager::onShutdown), mIsShuttingDown(false)
|
||||
{
|
||||
mWindowList.clear();
|
||||
Process::notifyShutdown(mNotifyShutdownDelegate);
|
||||
}
|
||||
|
||||
MacWindowManager::~MacWindowManager()
|
||||
{
|
||||
for(U32 i = 0; i < mWindowList.size(); i++)
|
||||
delete mWindowList[i];
|
||||
mWindowList.clear();
|
||||
|
||||
CGReleaseDisplayFadeReservation(mFadeToken);
|
||||
}
|
||||
|
||||
RectI MacWindowManager::getPrimaryDesktopArea()
|
||||
{
|
||||
// Get the area of the main desktop that isn't taken by the dock or menu bar.
|
||||
return convertCGRectToRectI([[NSScreen mainScreen] visibleFrame]);
|
||||
}
|
||||
|
||||
void MacWindowManager::getMonitorRegions(Vector<RectI> ®ions)
|
||||
{
|
||||
// Populate a vector with all monitors and their extents in window space.
|
||||
NSArray *screenList = [NSScreen screens];
|
||||
for(U32 i = 0; i < [screenList count]; i++)
|
||||
{
|
||||
NSRect screenBounds = [[screenList objectAtIndex: i] frame];
|
||||
regions.push_back(convertCGRectToRectI(screenBounds));
|
||||
}
|
||||
}
|
||||
|
||||
S32 MacWindowManager::getDesktopBitDepth()
|
||||
{
|
||||
// get the current desktop bit depth
|
||||
// TODO: return -1 if an error occurred
|
||||
return NSBitsPerPixelFromDepth([[NSScreen mainScreen] depth]);
|
||||
}
|
||||
|
||||
Point2I MacWindowManager::getDesktopResolution()
|
||||
{
|
||||
// get the current desktop width/height
|
||||
// TODO: return Point2I(-1,-1) if an error occurred
|
||||
NSRect desktopBounds = [[NSScreen mainScreen] frame];
|
||||
return Point2I((U32)desktopBounds.size.width, (U32)desktopBounds.size.height);
|
||||
}
|
||||
|
||||
S32 MacWindowManager::getWindowCount()
|
||||
{
|
||||
// Get the number of PlatformWindow's in this manager
|
||||
return mWindowList.size();
|
||||
}
|
||||
|
||||
void MacWindowManager::getWindows(VectorPtr<PlatformWindow*> &windows)
|
||||
{
|
||||
// Populate a list with references to all the windows created from this manager.
|
||||
windows.merge(mWindowList);
|
||||
}
|
||||
|
||||
PlatformWindow * MacWindowManager::getFirstWindow()
|
||||
{
|
||||
if (mWindowList.size() > 0)
|
||||
return mWindowList[0];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PlatformWindow* MacWindowManager::getFocusedWindow()
|
||||
{
|
||||
for (U32 i = 0; i < mWindowList.size(); i++)
|
||||
{
|
||||
if( mWindowList[i]->isFocused() )
|
||||
return mWindowList[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PlatformWindow* MacWindowManager::getWindowById(WindowId zid)
|
||||
{
|
||||
// Find the window by its arbirary WindowId.
|
||||
for(U32 i = 0; i < mWindowList.size(); i++)
|
||||
{
|
||||
PlatformWindow* w = mWindowList[i];
|
||||
if( w->getWindowId() == zid)
|
||||
return w;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MacWindowManager::lowerCurtain()
|
||||
{
|
||||
// fade all displays.
|
||||
CGError err;
|
||||
err = CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &mFadeToken);
|
||||
AssertWarn(!err, "MacWindowManager::lowerCurtain() could not get a token");
|
||||
if(err) return;
|
||||
|
||||
err = CGDisplayFade(mFadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, true);
|
||||
AssertWarn(!err, "MacWindowManager::lowerCurtain() failed the fade");
|
||||
if(err) return;
|
||||
|
||||
// we do not release the token, because that will un-fade the screen!
|
||||
// the token will last for 15 sec, and then the screen will un-fade regardless.
|
||||
//CGReleaseDisplayFadeReservation(mFadeToken);
|
||||
}
|
||||
|
||||
void MacWindowManager::raiseCurtain()
|
||||
{
|
||||
// release the fade on all displays
|
||||
CGError err;
|
||||
err = CGDisplayFade(mFadeToken, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false);
|
||||
AssertWarn(!err, "MacWindowManager::raiseCurtain() failed the fade");
|
||||
|
||||
err = CGReleaseDisplayFadeReservation(mFadeToken);
|
||||
AssertWarn(!err, "MacWindowManager::raiseCurtain() failed releasing the token");
|
||||
}
|
||||
|
||||
|
||||
void MacWindowManager::_processCmdLineArgs(const S32 argc, const char **argv)
|
||||
{
|
||||
// TODO: accept command line args if necessary.
|
||||
}
|
||||
|
||||
PlatformWindow *MacWindowManager::createWindow(GFXDevice *device, const GFXVideoMode &mode)
|
||||
{
|
||||
MacWindow* window = new MacWindow(getNextId(), getEngineProductString(), mode.resolution);
|
||||
_addWindow(window);
|
||||
|
||||
// Set the video mode on the window
|
||||
window->setVideoMode(mode);
|
||||
|
||||
// Make sure our window is shown and drawn to.
|
||||
window->show();
|
||||
|
||||
// Bind the window to the specified device.
|
||||
if(device)
|
||||
{
|
||||
window->mDevice = device;
|
||||
window->mTarget = device->allocWindowTarget(window);
|
||||
AssertISV(window->mTarget,
|
||||
"MacWindowManager::createWindow - failed to get a window target back from the device.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::warnf("MacWindowManager::createWindow - created a window with no device!");
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void MacWindowManager::_addWindow(MacWindow* window)
|
||||
{
|
||||
#ifdef TORQUE_DEBUG
|
||||
// Make sure we aren't adding the window twice
|
||||
for(U32 i = 0; i < mWindowList.size(); i++)
|
||||
AssertFatal(window != mWindowList[i], "MacWindowManager::_addWindow - Should not add a window more than once");
|
||||
#endif
|
||||
if (mWindowList.size() > 0)
|
||||
window->mNextWindow = mWindowList.last();
|
||||
else
|
||||
window->mNextWindow = NULL;
|
||||
|
||||
mWindowList.push_back(window);
|
||||
window->mOwningWindowManager = this;
|
||||
window->appEvent.notify(this, &MacWindowManager::_onAppSignal);
|
||||
}
|
||||
|
||||
void MacWindowManager::_removeWindow(MacWindow* window)
|
||||
{
|
||||
for(WindowList::iterator i = mWindowList.begin(); i != mWindowList.end(); i++)
|
||||
{
|
||||
if(*i == window)
|
||||
{
|
||||
mWindowList.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
AssertFatal(false, avar("MacWindowManager::_removeWindow - Failed to remove window %x, perhaps it was already removed?", window));
|
||||
}
|
||||
|
||||
void MacWindowManager::_onAppSignal(WindowId wnd, S32 event)
|
||||
{
|
||||
if(event != WindowHidden)
|
||||
return;
|
||||
|
||||
for(U32 i = 0; i < mWindowList.size(); i++)
|
||||
{
|
||||
if(mWindowList[i]->getWindowId() == wnd)
|
||||
continue;
|
||||
|
||||
mWindowList[i]->signalGainFocus();
|
||||
}
|
||||
}
|
||||
|
||||
bool MacWindowManager::onShutdown()
|
||||
{
|
||||
mIsShuttingDown = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacWindowManager::canWindowGainFocus(MacWindow* window)
|
||||
{
|
||||
return !mIsShuttingDown;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue