604 lines
16 KiB
Plaintext
604 lines
16 KiB
Plaintext
/*
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
|
|
|
Mitsuba is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License Version 3
|
|
as published by the Free Software Foundation.
|
|
|
|
Mitsuba is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <mitsuba/hw/glrenderer.h>
|
|
#include <mitsuba/hw/nsgldevice.h>
|
|
#include <mitsuba/hw/nsglkeys.h>
|
|
#include <mitsuba/hw/nsglrenderer.h>
|
|
|
|
using namespace mitsuba;
|
|
|
|
#define DEFINE_KEY(xsym, sym) m_keymap[xsym] = Device::sym
|
|
|
|
@implementation CustomView
|
|
- (id) initWithFrame: (NSRect) frame {
|
|
self = [super initWithFrame: frame];
|
|
if (self) {
|
|
m_modifiers = 0;
|
|
m_firstMouseMotion = true;
|
|
m_focused = false;
|
|
m_mouseInWindow = false;
|
|
m_ignoreNextMouseEvent = false;
|
|
|
|
/* Cocoa <-> Mitsuba keyboard mappings */
|
|
for (uint i=0; i<0xFF; i++)
|
|
m_keymap[i] = Device::ENoSpecial;
|
|
DEFINE_KEY(QZ_BACKSPACE, EKeyBackspace);
|
|
DEFINE_KEY(QZ_TAB, EKeyTab);
|
|
DEFINE_KEY(QZ_RETURN, EKeyReturn);
|
|
DEFINE_KEY(QZ_PAUSE, EKeyPause);
|
|
DEFINE_KEY(QZ_ESCAPE, EKeyEscape);
|
|
DEFINE_KEY(QZ_DELETE, EKeyDelete);
|
|
DEFINE_KEY(QZ_KP0, EKeyKeyPad0);
|
|
DEFINE_KEY(QZ_KP1, EKeyKeyPad1);
|
|
DEFINE_KEY(QZ_KP2, EKeyKeyPad2);
|
|
DEFINE_KEY(QZ_KP3, EKeyKeyPad3);
|
|
DEFINE_KEY(QZ_KP4, EKeyKeyPad4);
|
|
DEFINE_KEY(QZ_KP5, EKeyKeyPad5);
|
|
DEFINE_KEY(QZ_KP6, EKeyKeyPad6);
|
|
DEFINE_KEY(QZ_KP7, EKeyKeyPad7);
|
|
DEFINE_KEY(QZ_KP8, EKeyKeyPad8);
|
|
DEFINE_KEY(QZ_KP9, EKeyKeyPad9);
|
|
DEFINE_KEY(QZ_KP_PERIOD, EKeyKeyPadPeriod);
|
|
DEFINE_KEY(QZ_KP_DIVIDE, EKeyKeyPadDivide);
|
|
DEFINE_KEY(QZ_KP_MULTIPLY, EKeyKeyPadMultiply);
|
|
DEFINE_KEY(QZ_KP_MINUS, EKeyKeyPadMinus);
|
|
DEFINE_KEY(QZ_KP_PLUS, EKeyKeyPadPlus);
|
|
DEFINE_KEY(QZ_KP_ENTER, EKeyKeyPadEnter);
|
|
DEFINE_KEY(QZ_KP_EQUALS, EKeyKeyPadEquals);
|
|
DEFINE_KEY(QZ_UP, EKeyUp);
|
|
DEFINE_KEY(QZ_DOWN, EKeyDown);
|
|
DEFINE_KEY(QZ_RIGHT, EKeyRight);
|
|
DEFINE_KEY(QZ_LEFT, EKeyLeft);
|
|
DEFINE_KEY(QZ_INSERT, EKeyInsert);
|
|
DEFINE_KEY(QZ_HOME, EKeyHome);
|
|
DEFINE_KEY(QZ_END, EKeyEnd);
|
|
DEFINE_KEY(QZ_PAGEUP, EKeyPageUp);
|
|
DEFINE_KEY(QZ_PAGEDOWN, EKeyPageDown);
|
|
DEFINE_KEY(QZ_F1, EKeyF1);
|
|
DEFINE_KEY(QZ_F2, EKeyF2);
|
|
DEFINE_KEY(QZ_F3, EKeyF3);
|
|
DEFINE_KEY(QZ_F4, EKeyF4);
|
|
DEFINE_KEY(QZ_F5, EKeyF5);
|
|
DEFINE_KEY(QZ_F6, EKeyF6);
|
|
DEFINE_KEY(QZ_F7, EKeyF7);
|
|
DEFINE_KEY(QZ_F8, EKeyF8);
|
|
DEFINE_KEY(QZ_F9, EKeyF9);
|
|
DEFINE_KEY(QZ_F10, EKeyF10);
|
|
DEFINE_KEY(QZ_F11, EKeyF11);
|
|
DEFINE_KEY(QZ_F12, EKeyF12);
|
|
DEFINE_KEY(QZ_NUMLOCK, EKeyNumLock);
|
|
DEFINE_KEY(QZ_CAPSLOCK, EKeyCapsLock);
|
|
DEFINE_KEY(QZ_SCROLLOCK, EKeyScrollLock);
|
|
DEFINE_KEY(QZ_LSHIFT, EKeyLShift);
|
|
DEFINE_KEY(QZ_RSHIFT, EKeyRShift);
|
|
DEFINE_KEY(QZ_LMETA, EKeyLMeta);
|
|
DEFINE_KEY(QZ_RMETA, EKeyRMeta);
|
|
DEFINE_KEY(QZ_LALT, EKeyLAlt);
|
|
DEFINE_KEY(QZ_RALT, EKeyRAlt);
|
|
DEFINE_KEY(QZ_LCTRL, EKeyLControl);
|
|
DEFINE_KEY(QZ_RCTRL, EKeyRControl);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void) setDevice: (NSGLDevice *) device {
|
|
m_device = device;
|
|
}
|
|
|
|
- (void) ignoreNextMouseEvent {
|
|
m_ignoreNextMouseEvent = true;
|
|
}
|
|
|
|
- (void) ignoreFirstMouseMotion {
|
|
m_firstMouseMotion = false;
|
|
}
|
|
|
|
- (BOOL) focused {
|
|
return m_focused;
|
|
}
|
|
|
|
- (BOOL) acceptsFirstResponder {
|
|
return YES;
|
|
}
|
|
|
|
- (uint) extractModifiers: (uint) modifiers {
|
|
uint result = 0;
|
|
|
|
if (modifiers & NSAlphaShiftKeyMask)
|
|
result |= 0x10;
|
|
if (modifiers & NSShiftKeyMask)
|
|
result |= Device::EShiftModifier;
|
|
if (modifiers & NSControlKeyMask)
|
|
result |= Device::EControlModifier;
|
|
if (modifiers & NSAlternateKeyMask)
|
|
result |= Device::EAltModifier;
|
|
if (modifiers & NSCommandKeyMask)
|
|
result |= Device::EMetaModifier;
|
|
return result;
|
|
}
|
|
|
|
- (void) windowDidBecomeKey: (NSNotification *) notification {
|
|
bool cursorInWindow = m_device->isMouseInWindow();
|
|
m_focused = true;
|
|
m_device->pushEvent(DeviceEvent(Device::EGainFocusEvent));
|
|
m_buttonMask = 0;
|
|
if (!m_device->getCursor() && cursorInWindow) {
|
|
m_mouseInWindow = true;
|
|
[NSCursor hide];
|
|
}
|
|
}
|
|
|
|
- (void) windowDidResignKey: (NSNotification *) notification {
|
|
m_focused = false;
|
|
m_device->pushEvent(DeviceEvent(Device::ELoseFocusEvent));
|
|
m_buttonMask = 0;
|
|
if (!m_device->getCursor()) {
|
|
[NSCursor unhide];
|
|
}
|
|
}
|
|
|
|
- (void) handleEvent: (NSEvent *) event {
|
|
DeviceEvent deviceEvent(Device::ENoEvent);
|
|
uint type = [event type];
|
|
|
|
switch (type) {
|
|
case NSFlagsChanged: {
|
|
const uint list1[] = { Device::EShiftModifier, Device::EControlModifier, Device::EAltModifier, Device::EMetaModifier, 0x10};
|
|
const uint list2[] = { Device::EKeyLShift, Device::EKeyLControl, Device::EKeyLAlt, Device::EKeyLMeta, Device::EKeyCapsLock};
|
|
uint newModifiers = [self extractModifiers: [event modifierFlags]];
|
|
uint difference = m_modifiers ^ newModifiers;
|
|
m_modifiers = newModifiers;
|
|
|
|
for (uint i=0; i<5; i++) {
|
|
if ((difference & list1[i]) != 0) {
|
|
deviceEvent.setType((m_modifiers & list1[i]) == 0 ? Device::EKeyUpEvent : Device::EKeyDownEvent);
|
|
deviceEvent.getKeyboardInterpreted()[0] = '\0';
|
|
deviceEvent.setKeyboardSpecial(list2[i]);
|
|
deviceEvent.setKeyboardKey('\0');
|
|
deviceEvent.setKeyboardModifiers(m_modifiers);
|
|
m_device->pushEvent(deviceEvent);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
case NSLeftMouseUp:
|
|
case NSRightMouseUp:
|
|
case NSOtherMouseUp:
|
|
deviceEvent.setType(Device::EMouseButtonUpEvent);
|
|
case NSLeftMouseDown:
|
|
case NSRightMouseDown:
|
|
case NSOtherMouseDown: {
|
|
NSPoint location = [((NSWindow *) m_device->getWindow()) mouseLocationOutsideOfEventStream];
|
|
if (deviceEvent.getType() == Device::ENoEvent)
|
|
deviceEvent.setType(Device::EMouseButtonDownEvent);
|
|
deviceEvent.setMousePosition(Point2i((int) location.x, m_device->getSize().y - (int) location.y));
|
|
deviceEvent.setMouseRelative(Vector2i(0, 0));
|
|
uint buttonNumber = [event buttonNumber];
|
|
uint buttonMask = 0;
|
|
if (buttonNumber == 0)
|
|
buttonMask = Device::ELeftButton;
|
|
else if (buttonNumber == 1)
|
|
buttonMask = Device::ERightButton;
|
|
else if (buttonNumber == 2)
|
|
buttonMask = Device::EMiddleButton;
|
|
else
|
|
return;
|
|
if (deviceEvent.getType() == Device::EMouseButtonDownEvent)
|
|
m_buttonMask |= buttonMask;
|
|
else
|
|
m_buttonMask &= ~buttonMask;
|
|
deviceEvent.setMouseButton(buttonMask);
|
|
}
|
|
break;
|
|
case NSScrollWheel: {
|
|
NSPoint location = [((NSWindow *) m_device->getWindow()) mouseLocationOutsideOfEventStream];
|
|
float deltaX = [event deltaX], deltaY = [event deltaY];
|
|
if (deltaX > 0 || deltaY > 0)
|
|
deviceEvent.setMouseButton(Device::EWheelUpButton);
|
|
else
|
|
deviceEvent.setMouseButton(Device::EWheelDownButton);
|
|
deviceEvent.setMousePosition(Point2i((int) location.x, m_device->getSize().y - (int) location.y));
|
|
deviceEvent.setMouseRelative(Vector2i(0, 0));
|
|
deviceEvent.setType(Device::EMouseButtonDownEvent);
|
|
m_device->pushEvent(deviceEvent);
|
|
deviceEvent.setType(Device::EMouseButtonUpEvent);
|
|
m_device->pushEvent(deviceEvent);
|
|
return;
|
|
}
|
|
break;
|
|
case NSLeftMouseDragged:
|
|
case NSRightMouseDragged:
|
|
case NSOtherMouseDragged:
|
|
case NSMouseMoved: {
|
|
if (m_ignoreNextMouseEvent) {
|
|
m_ignoreNextMouseEvent = false;
|
|
return;
|
|
}
|
|
NSPoint location = [((NSWindow *) m_device->getWindow()) mouseLocationOutsideOfEventStream];
|
|
Point2i absolute((int) location.x, m_device->getSize().y - (int) location.y);
|
|
|
|
bool cursorInWindow = m_device->isMouseInWindow();
|
|
if (m_buttonMask == 0)
|
|
deviceEvent.setType(Device::EMouseMotionEvent);
|
|
else
|
|
deviceEvent.setType(Device::EMouseDragEvent);
|
|
deviceEvent.setMousePosition(absolute);
|
|
deviceEvent.setMouseButton(m_buttonMask);
|
|
if (m_firstMouseMotion) {
|
|
deviceEvent.setMouseRelative(Vector2i(absolute.x, absolute.y));
|
|
m_firstMouseMotion = false;
|
|
} else {
|
|
deviceEvent.setMouseRelative(Vector2i((int) [event deltaX], (int) [event deltaY]));
|
|
}
|
|
|
|
if (!cursorInWindow && m_focused && !m_device->getCursor()) {
|
|
if (m_mouseInWindow) {
|
|
m_mouseInWindow = false;
|
|
[NSCursor unhide];
|
|
}
|
|
} else if (cursorInWindow && m_focused && !m_device->getCursor()) {
|
|
if (!m_mouseInWindow) {
|
|
m_mouseInWindow = true;
|
|
[NSCursor hide];
|
|
}
|
|
}
|
|
|
|
if (cursorInWindow)
|
|
m_mouseInWindow = true;
|
|
|
|
if (absolute.x > m_device->getSize().x || absolute.x < 0
|
|
|| absolute.y > m_device->getSize().y || absolute.y< 0)
|
|
return;
|
|
}
|
|
break;
|
|
case NSKeyUp:
|
|
deviceEvent.setType(Device::EKeyUpEvent);
|
|
case NSKeyDown: {
|
|
if (deviceEvent.getType() == Device::ENoEvent)
|
|
deviceEvent.setType(Device::EKeyDownEvent);
|
|
if ([event isARepeat])
|
|
return;
|
|
|
|
NSString *characters = [event characters];
|
|
uint count = [characters length];
|
|
|
|
if (count == 0 || count == 1) {
|
|
unsigned char scanCode = [event keyCode];
|
|
uint special = m_keymap[scanCode];
|
|
|
|
strncpy(deviceEvent.getKeyboardInterpreted(), [characters UTF8String], 15);
|
|
|
|
if (special != 0) {
|
|
deviceEvent.setKeyboardKey('\0');
|
|
deviceEvent.setKeyboardSpecial(m_keymap[scanCode]);
|
|
deviceEvent.setKeyboardModifiers([self extractModifiers: [event modifierFlags]]);
|
|
} else {
|
|
if (count > 0)
|
|
deviceEvent.setKeyboardKey([[event charactersIgnoringModifiers] UTF8String][0]);
|
|
else
|
|
deviceEvent.setKeyboardKey('\0');
|
|
deviceEvent.setKeyboardSpecial(Device::ENoSpecial);
|
|
deviceEvent.setKeyboardModifiers(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (deviceEvent.getType() != Device::ENoEvent)
|
|
m_device->pushEvent(deviceEvent);
|
|
}
|
|
|
|
- (void) mouseDown: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) mouseUp: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) mouseMoved: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) mouseDragged: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) rightMouseDown: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) rightMouseUp: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) rightMouseMoved: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) rightMouseDragged: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) otherMouseDown: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) otherMouseUp: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) otherMouseMoved: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) otherMouseDragged: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) scrollWheel: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) keyDown: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) keyUp: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (void) flagsChanged: (NSEvent *) event {
|
|
[self handleEvent: event];
|
|
}
|
|
|
|
- (BOOL) windowShouldClose: (id) sender {
|
|
m_device->pushEvent(DeviceEvent(Device::EQuitEvent));
|
|
return NO;
|
|
}
|
|
|
|
@end
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
NSGLDevice::NSGLDevice(NSGLSession *session)
|
|
: Device(session), m_visible(false), m_cursor(true) {
|
|
m_title = "Mitsuba [nsgl]";
|
|
}
|
|
|
|
NSGLDevice::~NSGLDevice() {
|
|
Log(EDebug, "Destroying NSGL device");
|
|
if (m_initialized)
|
|
shutdown();
|
|
}
|
|
|
|
void NSGLDevice::init(Device *other) {
|
|
Device::init(other);
|
|
|
|
__mts_init_cocoa();
|
|
|
|
NSOpenGLPixelFormatAttribute attribs[32];
|
|
uint i=0;
|
|
|
|
Device::init();
|
|
|
|
m_currentContext = NULL;
|
|
|
|
Log(EDebug, "Initializing NSGL device");
|
|
|
|
NSRect contentRect = NSMakeRect(m_position.x, m_position.y,
|
|
m_size.x, m_size.y);
|
|
|
|
/* Protect the event queue */
|
|
m_mutex = new Mutex();
|
|
|
|
/* Create the device window */
|
|
m_window = [[NSWindow alloc] initWithContentRect: contentRect
|
|
styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
|
|
backing: NSBackingStoreBuffered defer: NO];
|
|
if (m_window == nil)
|
|
Log(EError, "Could not create window");
|
|
|
|
if (m_center)
|
|
[m_window center];
|
|
|
|
/* Create a sub-view as drawing destination and in order to catch events */
|
|
m_view = [[CustomView alloc] initWithFrame: contentRect];
|
|
if (m_view == nil)
|
|
Log(EError, "Could not create view");
|
|
|
|
[m_view setDevice: this];
|
|
[[m_window contentView] addSubview: m_view];
|
|
[m_window setDelegate: m_view];
|
|
[m_window setAcceptsMouseMovedEvents: YES];
|
|
|
|
/* Pixel format setup */
|
|
AssertEx(m_redBits == m_blueBits || m_redBits == m_greenBits, "NSGL does not support individual color depths");
|
|
|
|
attribs[i++] = NSOpenGLPFAColorSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) m_redBits;
|
|
|
|
attribs[i++] = NSOpenGLPFAAlphaSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) m_alphaBits;
|
|
|
|
attribs[i++] = NSOpenGLPFADepthSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) m_depthBits;
|
|
|
|
attribs[i++] = NSOpenGLPFAStencilSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) m_stencilBits;
|
|
|
|
if (m_doubleBuffer) {
|
|
attribs[i++] = NSOpenGLPFADoubleBuffer;
|
|
}
|
|
|
|
if (m_fsaa > 1) {
|
|
attribs[i++] = NSOpenGLPFASampleBuffers; attribs[i++] = (NSOpenGLPixelFormatAttribute) 1;
|
|
attribs[i++] = NSOpenGLPFASamples; attribs[i++] = (NSOpenGLPixelFormatAttribute) m_fsaa;
|
|
}
|
|
|
|
attribs[i++] = NSOpenGLPFANoRecovery; // Never switch renderers
|
|
attribs[i++] = NSOpenGLPFAWindow;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) 0;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute) 0;
|
|
|
|
m_fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
|
|
|
|
if (m_fmt == nil)
|
|
Log(EError, "Could not create OpenGL pixel format!");
|
|
|
|
m_initialized = true;
|
|
setTitle(m_title);
|
|
}
|
|
|
|
void NSGLDevice::shutdown() {
|
|
Device::shutdown();
|
|
Log(EDebug, "Shutting down NSGL device");
|
|
setVisible(false);
|
|
[m_fmt release];
|
|
[m_view release];
|
|
[m_window release];
|
|
m_initialized = false;
|
|
}
|
|
|
|
|
|
void NSGLDevice::setTitle(const std::string &title) {
|
|
std::string finalTitle;
|
|
|
|
Assert(m_initialized);
|
|
if (m_showFPS && m_fps != 0) {
|
|
finalTitle = formatString("%s - %i FPS", title.c_str(), m_fps);
|
|
} else {
|
|
finalTitle = title;
|
|
}
|
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
NSString *string = [NSString stringWithUTF8String: finalTitle.c_str()];
|
|
[m_window setTitle: string];
|
|
Device::setTitle(title);
|
|
|
|
[pool release];
|
|
}
|
|
|
|
void NSGLDevice::setPosition(const Point2i &position) {
|
|
Assert(m_initialized);
|
|
|
|
NSPoint point = NSMakePoint(position.x,
|
|
CGDisplayPixelsHigh(kCGDirectMainDisplay) - position.y);
|
|
|
|
[m_window setFrameTopLeftPoint: point];
|
|
Device::setPosition(position);
|
|
}
|
|
|
|
void NSGLDevice::setVisible(bool visible) {
|
|
Assert(m_initialized);
|
|
|
|
if (visible && !m_visible) {
|
|
[m_window makeKeyAndOrderFront: nil];
|
|
m_visible = true;
|
|
} else if (!visible && m_visible) {
|
|
[m_window orderOut: nil];
|
|
m_visible = false;
|
|
}
|
|
}
|
|
|
|
void NSGLDevice::warpMouse(const Point2i &position) {
|
|
Assert(m_initialized);
|
|
|
|
NSRect frame = [m_window frame];
|
|
|
|
CGPoint point;
|
|
point.x = position.x + frame.origin.x;
|
|
point.y = position.y + frame.origin.y;
|
|
|
|
/* Avoids cursor freezing */
|
|
[m_view ignoreNextMouseEvent];
|
|
CGSetLocalEventsSuppressionInterval(0.0f);
|
|
CGWarpMouseCursorPosition(point);
|
|
}
|
|
|
|
void NSGLDevice::setGrab(bool grab) {
|
|
Assert(m_initialized);
|
|
|
|
if (grab) {
|
|
warpMouse(Point2i(getSize().x / 2, getSize().y/2));
|
|
CGAssociateMouseAndMouseCursorPosition(false);
|
|
} else {
|
|
CGAssociateMouseAndMouseCursorPosition(true);
|
|
}
|
|
[m_view ignoreFirstMouseMotion];
|
|
showCursor(!grab);
|
|
}
|
|
|
|
void NSGLDevice::showCursor(bool enabled) {
|
|
Assert(m_initialized);
|
|
|
|
if (!m_cursor && enabled) {
|
|
[NSCursor unhide];
|
|
m_cursor = true;
|
|
} else if (m_cursor && !enabled) {
|
|
m_cursor = false;
|
|
if (isMouseInWindow() && [m_view focused]) {
|
|
[NSCursor hide];
|
|
}
|
|
}
|
|
}
|
|
|
|
void NSGLDevice::flip() {
|
|
Assert(m_initialized);
|
|
|
|
Device::flip();
|
|
|
|
if (m_doubleBuffer) {
|
|
Assert(m_currentContext != NULL);
|
|
[m_currentContext flushBuffer];
|
|
}
|
|
}
|
|
|
|
void NSGLDevice::pushEvent(const DeviceEvent &event) {
|
|
m_mutex->lock();
|
|
m_deviceEvents.push_back(event);
|
|
m_mutex->unlock();
|
|
}
|
|
|
|
void NSGLDevice::processEvents() {
|
|
Assert(m_initialized);
|
|
|
|
m_mutex->lock();
|
|
for (std::vector<DeviceEvent>::iterator it = m_deviceEvents.begin(); it!=m_deviceEvents.end(); ++it)
|
|
fireDeviceEvent(*it);
|
|
m_deviceEvents.clear();
|
|
m_mutex->unlock();
|
|
}
|
|
|
|
bool NSGLDevice::isMouseInWindow() {
|
|
return m_fullscreen || NSPointInRect([m_window mouseLocationOutsideOfEventStream], [m_view frame]);
|
|
}
|
|
|
|
void NSGLDevice::makeCurrent(Renderer *renderer) {
|
|
Assert(m_initialized);
|
|
|
|
m_currentContext = static_cast<NSOpenGLContext *>(static_cast<NSGLRenderer *>(renderer)->getContext());
|
|
[m_currentContext setView: m_view];
|
|
[m_currentContext makeCurrentContext];
|
|
}
|
|
|
|
MTS_IMPLEMENT_CLASS(NSGLDevice, false, Device)
|
|
MTS_NAMESPACE_END
|