diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index 44eea09bd..f4ea1f084 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -872,8 +872,11 @@ bool CDriverGL::swapBuffers() #elif defined(NL_OS_MAC) // TODO: maybe do this somewhere else? - [_autoreleasePool release]; - _autoreleasePool = [[NSAutoreleasePool alloc] init]; + if(_DestroyWindow) + { + [_autoreleasePool release]; + _autoreleasePool = [[NSAutoreleasePool alloc] init]; + } [_ctx flushBuffer]; [containerView() display]; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 8e6b3a9b1..54071bd0f 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -116,8 +116,7 @@ bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM #elif defined (NL_OS_MAC) -// TODO: change that -bool GlWndProc(CDriverGL *driver); +bool GlWndProc(CDriverGL *driver, NSEvent* e); #elif defined (NL_OS_UNIX) @@ -706,9 +705,11 @@ private: #elif defined(NL_OS_MAC) + friend bool GlWndProc(CDriverGL* driver, NSEvent* e); + NLMISC::CCocoaEventEmitter _EventEmitter; NSOpenGLContext* _ctx; - NSOpenGLView* _glView; + CocoaOpenGLView* _glView; NSAutoreleasePool* _autoreleasePool; uint16 _backBufferHeight; uint16 _backBufferWidth; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index 13b48c662..1583fb8ac 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -164,8 +164,22 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l #elif defined (NL_OS_MAC) -bool GlWndProc(CDriverGL *driver) +bool GlWndProc(CDriverGL *driver, NSEvent* e) { + H_AUTO_OGL(GlWndProc) + + if(!driver) + return false; + + // NSLog(@"NSEvent in GlWndProc %@", e); + + switch([e type]) + { + /* TODO handle window move, resize, activate, close, etc. */ + default: + return driver->_EventEmitter.processMessage(e); + } + return false; } @@ -951,6 +965,8 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re [_ctx flushBuffer]; [containerView() display]; + _EventEmitter.init(this, _glView); + #elif defined(NL_OS_UNIX) static int sAttribList16bpp[] = @@ -2164,7 +2180,7 @@ void CDriverGL::showWindow(bool show) #elif defined(NL_OS_MAC) - // TODO implement me +# warning "OpenGL Driver: Missing Mac Implementation for showWindow" #elif defined (NL_OS_UNIX) @@ -2601,7 +2617,7 @@ bool CDriverGL::isActive() res = (IsWindow(_win) != FALSE); #elif defined(NL_OS_MAC) -# warning "OpenGL Driver: Missing Mac Implementation for isActive" +# warning "OpenGL Driver: Missing Mac Implementation for isActive (always true if a window is set)" #elif defined (NL_OS_UNIX) #endif // NL_OS_UNIX diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp index e1ce85dea..9d126deea 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp @@ -16,13 +16,6 @@ #include "cocoa_event_emitter.h" -#include "nel/misc/event_server.h" -#include "nel/misc/events.h" -#include "nel/misc/game_device_events.h" - -#include -#import - namespace NLMISC { @@ -227,6 +220,194 @@ static bool isTextKeyEvent(NSEvent* event) return false; } +void CCocoaEventEmitter::init(NL3D::IDriver* driver, CocoaOpenGLView* glView) +{ + _driver = driver; + _glView = glView; +} + +bool CCocoaEventEmitter::processMessage(NSEvent* event, CEventServer* server) +{ + if(!server && !_server) + nlerror("no server to post events to"); + + if(!server) + server = _server; + + NSRect viewRect = [_glView frame]; + + // TODO this code assumes, that the view fills the window + // convert the mouse position to NeL style (relative) + float mouseX = event.locationInWindow.x / (float)viewRect.size.width; + float mouseY = event.locationInWindow.y / (float)viewRect.size.height; + + // if the mouse event was placed outside the view, don't tell NeL :) + if((mouseX < 0.0 || mouseX > 1.0 || mouseY < 0.0 || mouseY > 1.0) && + event.type != NSKeyDown && event.type != NSKeyUp) + { + [NSApp sendEvent:event]; + return false; + } + + // convert the modifiers for nel to pass them with the events + NLMISC::TKeyButton modifiers = + modifierFlagsToNelKeyButton([event modifierFlags]); + + switch(event.type) + { + case NSLeftMouseDown: + { + server->postEvent(new NLMISC::CEventMouseDown( + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this)); + } + break; + case NSLeftMouseUp: + { + server->postEvent(new NLMISC::CEventMouseUp( + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this)); + break; + } + case NSRightMouseDown: + { + server->postEvent(new NLMISC::CEventMouseDown( + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this)); + break; + } + case NSRightMouseUp: + { + server->postEvent(new NLMISC::CEventMouseUp( + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this)); + break; + } + case NSMouseMoved: + { + NLMISC::CEvent* nelEvent; + + // when emulating raw mode, send the delta in a CGDMouseMove event + if(_emulateRawMode) + nelEvent = new NLMISC::CGDMouseMove( + this, NULL /* no mouse device */, event.deltaX, -event.deltaY); + + // normally send position in a CEventMouseMove + else + nelEvent = new NLMISC::CEventMouseMove( + mouseX, mouseY, (NLMISC::TMouseButton)modifiers, this); + + server->postEvent(nelEvent); + break; + } + case NSLeftMouseDragged: + { + NLMISC::CEvent* nelEvent; + + // when emulating raw mode, send the delta in a CGDMouseMove event + if(_emulateRawMode) + nelEvent = new NLMISC::CGDMouseMove( + this, NULL /* no mouse device */, event.deltaX, -event.deltaY); + + // normally send position in a CEventMouseMove + else + nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this); + + server->postEvent(nelEvent); + break; + } + case NSRightMouseDragged: + { + NLMISC::CEvent* nelEvent; + + // when emulating raw mode, send the delta in a CGDMouseMove event + if(_emulateRawMode) + nelEvent = new NLMISC::CGDMouseMove( + this, NULL /* no mouse device */, event.deltaX, -event.deltaY); + + // normally send position in a CEventMouseMove + else + nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this); + + server->postEvent(nelEvent); + break; + } + case NSMouseEntered:break; + case NSMouseExited:break; + case NSKeyDown: + { + // push the key press event to the event server + server->postEvent(new NLMISC::CEventKeyDown( + virtualKeycodeToNelKey([event keyCode]), + modifierFlagsToNelKeyButton([event modifierFlags]), + [event isARepeat] == NO, this)); + + // if this was a text event + if(isTextKeyEvent(event)) + { + ucstring ucstr; + + // get the string associated with the key press event + ucstr.fromUtf8([[event characters] UTF8String]); + + // push the text event to event server as well + server->postEvent(new NLMISC::CEventChar( + ucstr[0], NLMISC::noKeyButton, this)); + } + break; + } + case NSKeyUp: + { + // push the key release event to the event server + server->postEvent(new NLMISC::CEventKeyUp( + virtualKeycodeToNelKey([event keyCode]), + modifierFlagsToNelKeyButton([event modifierFlags]), this)); + break; + } + case NSFlagsChanged:break; + case NSAppKitDefined:break; + case NSSystemDefined:break; + case NSApplicationDefined:break; + case NSPeriodic:break; + case NSCursorUpdate:break; + case NSScrollWheel: + { + if(fabs(event.deltaY) > 0.1) + server->postEvent(new NLMISC::CEventMouseWheel( + mouseX, mouseY, (NLMISC::TMouseButton)modifiers, + (event.deltaY > 0), this)); + + break; + } + case NSTabletPoint:break; + case NSTabletProximity:break; + case NSOtherMouseDown:break; + case NSOtherMouseUp:break; + case NSOtherMouseDragged:break; +#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + case NSEventTypeGesture:break; + case NSEventTypeMagnify:break; + case NSEventTypeSwipe:break; + case NSEventTypeRotate:break; + case NSEventTypeBeginGesture:break; + case NSEventTypeEndGesture:break; +#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + default: + { + nlwarning("Unknown event type. dropping."); + // NSLog(@"%@", event); + break; + } + } + + [NSApp sendEvent:event]; + return true; +} + +typedef bool (*cocoaProc)(NL3D::IDriver*, void* e); + void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */) { // break if there was no event to handle @@ -241,177 +422,22 @@ void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */) if(!event) break; - NSView* glView = [[[[event window] contentView] subviews] lastObject]; - NSRect viewRect = [glView frame]; - - // TODO this code assumes, that the view fills the window - // convert the mouse position to NeL style (relative) - float mouseX = event.locationInWindow.x / (float)viewRect.size.width; - float mouseY = event.locationInWindow.y / (float)viewRect.size.height; - - // if the mouse event was placed outside the view, don't tell NeL :) - if((mouseX < 0.0 || mouseX > 1.0 || mouseY < 0.0 || mouseY > 1.0) && - event.type != NSKeyDown && event.type != NSKeyUp) + if(_driver) { - [NSApp sendEvent:event]; - continue; + cocoaProc proc = (cocoaProc)_driver->getWindowProc(); + + if(proc) + proc(_driver, event); } - - // convert the modifiers for nel to pass them with the events - NLMISC::TKeyButton modifiers = - modifierFlagsToNelKeyButton([event modifierFlags]); - - switch(event.type) + else { - case NSLeftMouseDown: - { - server.postEvent(new NLMISC::CEventMouseDown( - mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this)); + processMessage(event, &server); } - break; - case NSLeftMouseUp: - { - server.postEvent(new NLMISC::CEventMouseUp( - mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this)); - break; - } - case NSRightMouseDown: - { - server.postEvent(new NLMISC::CEventMouseDown( - mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this)); - break; - } - case NSRightMouseUp: - { - server.postEvent(new NLMISC::CEventMouseUp( - mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this)); - break; - } - case NSMouseMoved: - { - NLMISC::CEvent* nelEvent; - - // when emulating raw mode, send the delta in a CGDMouseMove event - if(_emulateRawMode) - nelEvent = new NLMISC::CGDMouseMove( - this, NULL /* no mouse device */, event.deltaX, -event.deltaY); - - // normally send position in a CEventMouseMove - else - nelEvent = new NLMISC::CEventMouseMove( - mouseX, mouseY, (NLMISC::TMouseButton)modifiers, this); - - server.postEvent(nelEvent); - break; - } - case NSLeftMouseDragged: - { - NLMISC::CEvent* nelEvent; - - // when emulating raw mode, send the delta in a CGDMouseMove event - if(_emulateRawMode) - nelEvent = new NLMISC::CGDMouseMove( - this, NULL /* no mouse device */, event.deltaX, -event.deltaY); - - // normally send position in a CEventMouseMove - else - nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), this); - - server.postEvent(nelEvent); - break; - } - case NSRightMouseDragged: - { - NLMISC::CEvent* nelEvent; - - // when emulating raw mode, send the delta in a CGDMouseMove event - if(_emulateRawMode) - nelEvent = new NLMISC::CGDMouseMove( - this, NULL /* no mouse device */, event.deltaX, -event.deltaY); - - // normally send position in a CEventMouseMove - else - nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, - (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), this); - - server.postEvent(nelEvent); - break; - } - case NSMouseEntered:break; - case NSMouseExited:break; - case NSKeyDown: - { - // push the key press event to the event server - server.postEvent(new NLMISC::CEventKeyDown( - virtualKeycodeToNelKey([event keyCode]), - modifierFlagsToNelKeyButton([event modifierFlags]), - [event isARepeat] == NO, this)); - - // if this was a text event - if(isTextKeyEvent(event)) - { - ucstring ucstr; - - // get the string associated with the key press event - ucstr.fromUtf8([[event characters] UTF8String]); - - // push the text event to event server as well - server.postEvent(new NLMISC::CEventChar( - ucstr[0], NLMISC::noKeyButton, this)); - } - break; - } - case NSKeyUp: - { - // push the key release event to the event server - server.postEvent(new NLMISC::CEventKeyUp( - virtualKeycodeToNelKey([event keyCode]), - modifierFlagsToNelKeyButton([event modifierFlags]), this)); - break; - } - case NSFlagsChanged:break; - case NSAppKitDefined:break; - case NSSystemDefined:break; - case NSApplicationDefined:break; - case NSPeriodic:break; - case NSCursorUpdate:break; - case NSScrollWheel: - { - if(fabs(event.deltaY) > 0.1) - server.postEvent(new NLMISC::CEventMouseWheel( - mouseX, mouseY, (NLMISC::TMouseButton)modifiers, - (event.deltaY > 0), this)); - - break; - } - case NSTabletPoint:break; - case NSTabletProximity:break; - case NSOtherMouseDown:break; - case NSOtherMouseUp:break; - case NSOtherMouseDragged:break; -#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER - case NSEventTypeGesture:break; - case NSEventTypeMagnify:break; - case NSEventTypeSwipe:break; - case NSEventTypeRotate:break; - case NSEventTypeBeginGesture:break; - case NSEventTypeEndGesture:break; -#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER - default: - { - nlwarning("Unknown event type. dropping."); - // NSLog(@"%@", event); - break; - } - } - - [NSApp sendEvent:event]; } + + // TODO like internal server in unix event emitter... review! + _server = &server; + // _server->pump(); } void CCocoaEventEmitter::emulateMouseRawMode(bool enable) diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h index 6680552b7..1ba60d77b 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h @@ -17,19 +17,38 @@ #ifndef NL_COCOA_EVENT_EMITTER_H #define NL_COCOA_EVENT_EMITTER_H -#include +#include "nel/misc/event_emitter.h" +#include "nel/misc/event_server.h" +#include "nel/misc/events.h" +#include "nel/misc/game_device_events.h" +#include "nel/3d/driver.h" +#import "cocoa_opengl_view.h" + +#include +#import namespace NLMISC { class CCocoaEventEmitter : public IEventEmitter { - bool _emulateRawMode; + bool _emulateRawMode; + NL3D::IDriver* _driver; + CocoaOpenGLView* _glView; + + // TODO like internal server in unix event emitter... review! + CEventServer* _server; public: - CCocoaEventEmitter() : _emulateRawMode(false) { } + CCocoaEventEmitter() : + _emulateRawMode(false), + _driver(NULL), + _glView(nil), + _server(NULL) { } - virtual void submitEvents(CEventServer & server, bool allWindows); + void init(NL3D::IDriver* driver, CocoaOpenGLView* glView); + bool processMessage(NSEvent* event, CEventServer* server = NULL); + virtual void submitEvents(CEventServer& server, bool allWindows); virtual void emulateMouseRawMode(bool enable); virtual bool copyTextToClipboard(const ucstring &text);