diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index be6048d5c..2f8d92f93 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -1006,8 +1006,8 @@ bool CDriverGL::release() } #elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE) -# warning "OpenGL Driver: Missing Mac Implementation" - nlwarning("OpenGL Driver: Missing Mac Implementation"); + + NL3D::MAC::release(); #elif defined (NL_OS_UNIX) if(_FullScreen) 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 3cea940c6..4a7871606 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -1288,8 +1288,8 @@ void CDriverGL::showCursor(bool b) ; } #elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE) -# warning "OpenGL Driver: Missing Mac Implementation" - nlwarning("OpenGL Driver: Missing Mac Implementation"); + + NL3D::MAC::showCursor(b); #elif defined (NL_OS_UNIX) @@ -1335,8 +1335,8 @@ void CDriverGL::setMousePos(float x, float y) SetCursorPos(pt.x, pt.y); } #elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE) -# warning "OpenGL Driver: Missing Mac Implementation" - nlwarning("OpenGL Driver: Missing Mac Implementation"); + + NL3D::MAC::setMousePos(x, y); #elif defined (NL_OS_UNIX) XWindowAttributes xwa; @@ -1459,8 +1459,8 @@ void CDriverGL::setCapture (bool b) */ #elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE) -# warning "OpenGL Driver: Missing Mac Implementation" - nlwarning("OpenGL Driver: Missing Mac Implementation"); + + NL3D::MAC::setCapture(b); #elif defined (NL_OS_UNIX) diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h index 478f4b024..334fa1664 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h @@ -73,6 +73,18 @@ void setWindowTitle(const ucstring &title); /// mac specific stuff while calling CDriverGL::swapBuffers() void swapBuffers(); +/// mac specific stuff while calling CDriverGL::setCapture() +void setCapture(bool b); + +/// mac specific stuff while calling CDriverGL::showCursor() +void showCursor(bool b); + +/// mac specific stuff while calling CDriverGL::setMousePos() +void setMousePos(float x, float y); + +/// mac specific stuff while calling CDriverGL::release() +void release(); + /// mac specific stuff while calling CCocoaEventEmitter::submitEvents() void submitEvents(NLMISC::CEventServer& server, bool allWindows, NLMISC::CCocoaEventEmitter* eventEmitter); diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm index 6270e5b11..925e88780 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm @@ -74,6 +74,10 @@ bool init(uint windowIcon, emptyProc exitFunc) bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) { + /* + TODO use show and resizable flags + */ + // create a cocoa window with the size provided by the mode parameter g_window = [[CocoaWindow alloc] initWithContentRect:NSMakeRect(0, 0, mode.Width, mode.Height) @@ -126,6 +130,9 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) // enable mouse move events, NeL wants them [g_window setAcceptsMouseMovedEvents:YES]; + // there are no overlapping subview, so we can use the magical optimization! + [g_window useOptimizedDrawing:YES]; + // create a opengl context for the view g_glctx = [g_glview openGLContext]; @@ -138,6 +145,9 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) // put the window to the front and make it the key window [g_window makeKeyAndOrderFront:nil]; + // this is our main window + [g_window makeMainWindow]; + // tell the application that we are running now [g_app finishLaunching]; @@ -168,11 +178,11 @@ bool setMode(const GfxMode& mode) // leave fullscreen mode, enter windowed mode if(mode.Windowed && [g_glview isInFullScreenMode]) { - // pull the view back from fullscreen restoring windows options + // pull the view back from fullscreen restoring window options [g_glview exitFullScreenModeWithOptions:nil]; // disable manual setting of back buffer size, cocoa handles this - // automatically as soon as the window gets resized + // automatically as soon as the view gets resized CGLError error = CGLDisable((CGLContextObj)[g_glctx CGLContextObj], kCGLCESurfaceBackingSize); @@ -197,7 +207,7 @@ bool setMode(const GfxMode& mode) // NOTE: withOptions:nil disables + application switching! /* TODO check if simply using NSView enterFullScreenMode is a good idea. - the context can be set to full screen as well? performance differences? + the context can be set to full screen as well, performance differences? */ [g_glview enterFullScreenMode:[NSScreen mainScreen] withOptions: [NSDictionary dictionaryWithObjectsAndKeys: @@ -207,8 +217,8 @@ bool setMode(const GfxMode& mode) NSFullScreenModeApplicationPresentationOptions, nil]]; } - #ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND + // due to the back buffer size reading problem, just store the size g_bufferSize[0] = mode.Width; g_bufferSize[1] = mode.Height; #endif @@ -226,11 +236,9 @@ void getWindowSize(uint32 &width, uint32 &height) // changed, but the view still stays at full resolution. So the scaling of // the image from the rendered resolution to the view's resolution is done // by cocoa automatically while flushing buffers. - // That's why, in fullscreen mode, return the resolution from the back buffer, + // That's why, in fullscreen mode, return the resolution of the back buffer, // not the one from the window. - // check if manual back buffer sizing is enabled (thats only in fullscreen) - #ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND if([g_glview isInFullScreenMode]) { @@ -244,10 +252,10 @@ void getWindowSize(uint32 &width, uint32 &height) height = rect.size.height; } #else - /* TODO does not work atm, "invalid enumeration" */ + // check if manual back buffer sizing is enabled (thats only in fullscreen) GLint surfaceBackingSizeSet = 0; CGLError error = CGLIsEnabled((CGLContextObj)[g_glctx CGLContextObj], kCGLCESurfaceBackingSize, &surfaceBackingSizeSet); @@ -291,10 +299,10 @@ void getWindowSize(uint32 &width, uint32 &height) void getWindowPos(uint32 &x, uint32 &y) { - // get the size of the screen + // get the rect (position, size) of the screen NSRect screenRect = [[g_window screen] frame]; - // get the size of the window + // get the rect (position, size) of the window NSRect windowRect = [g_window frame]; // simply return x @@ -331,6 +339,92 @@ void swapBuffers() [g_glctx flushBuffer]; } +void setCapture(bool b) +{ + /* + TODO implement capture cursor, no need to fake using pull back to 0.5 / 0.5 + set a flag and then act accordingly in event loop? + + // no screen bounds... + void CGGetLastMouseDelta(CGMouseDelta* deltaX, CGMouseDelta* deltaY); + */ + nlwarning("not implemented"); +} + +void showCursor(bool b) +{ + // Mac OS manages a show/hide counter for the cursor, so hiding the cursor + // twice requires two calls to show to make the cursor visible again. + // Since other platforms seem to not do this, the functionality is masked here + // by only calling hide if the cursor is visible and only calling show if + // the cursor was hidden. + + CGDisplayErr error = kCGErrorSuccess; + static bool visible = true; + + if(b && !visible) + { + error = CGDisplayShowCursor(kCGDirectMainDisplay); + visible = true; + } + else if(!b && visible) + { + error = CGDisplayHideCursor(kCGDirectMainDisplay); + visible = false; + } + + if(error != kCGErrorSuccess) + nlerror("cannot get capture / un-capture cursor"); +} + +void setMousePos(float x, float y) +{ + // CG wants absolute coordinates related to screen top left + CGFloat fromScreenLeft = 0.0; + CGFloat fromScreenTop = 0.0; + + // get the gl view's rect for height and width + NSRect viewRect = [g_glview frame]; + + // if the view is not fullscreen, window top left is needed as offset + if(![g_glview isInFullScreenMode]) + { + // get the rect (position, size) of the screen + NSRect screenRect = [[g_window screen] frame]; + + // get the rect (position, size) of the window + NSRect windowRect = [g_window frame]; + + // window's x is ok + fromScreenLeft = windowRect.origin.x; + + // TODO this code assumes, that the view fills the window + + // map window bottom to view top + fromScreenTop = screenRect.size.height - + viewRect.size.height - windowRect.origin.y; + } + + // position inside the view + fromScreenLeft += (viewRect.size.width * x); + fromScreenTop += (viewRect.size.height * (1 - y)); + + // actually set the mouse position + CGDisplayErr error = CGDisplayMoveCursorToPoint( + kCGDirectMainDisplay, CGPointMake(fromScreenLeft, fromScreenTop)); + + if(error != kCGErrorSuccess) + nlerror("cannot set mouse position"); +} + +void release() +{ + /* + TODO release some stuff + */ + nlwarning("not implemented"); +} + /* TODO: this function has to be moved to a more central place to handle key mapping on mac x11 as well @@ -552,10 +646,19 @@ void submitEvents(NLMISC::CEventServer& server, // get the views size NSRect rect = [g_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)rect.size.width; float mouseY = event.locationInWindow.y / (float)rect.size.height; + // if the mouse event was placed on the window's titlebar, ignore it + if(mouseY > 1.0 && event.type != NSKeyDown && event.type != NSKeyUp) + { + [g_app sendEvent:event]; + [g_app updateWindows]; + continue; + } + switch(event.type) { case NSLeftMouseDown: @@ -597,6 +700,8 @@ void submitEvents(NLMISC::CEventServer& server, /* TODO modifiers with mouse events */ + // nldebug("mouse left drag %f %f", mouseX, mouseY); + server.postEvent(new NLMISC::CEventMouseMove( mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter)); break; diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.m b/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.m index eb23fd65a..c9c080dd6 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.m +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.m @@ -35,6 +35,7 @@ [characterStorage release]; [super dealloc]; } + -(BOOL)acceptsFirstResponder { return YES; diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index 44488eb0f..b4bd5359d 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -66,7 +66,7 @@ bool SetMousePosFirstTime = true; uint DownMouseButtons = 0; #ifdef NL_OS_UNIX -// on X11, store whether the mouse was captured or not +// on X11 and cocoa, store whether the mouse was captured or not bool MouseCapture = false; #endif @@ -251,8 +251,8 @@ void SetMouseFreeLook () } #ifdef NL_OS_UNIX - // on X11 the mouse needs to get pulled into the middle each update, else - // the cursor would reach the border of the window / desktop + // on X11 and cocoa the mouse needs to get pulled into the middle each update, + // else the cursor would reach the border of the window / desktop // and freelook would hang Driver->setMousePos(0.5f, 0.5f); #endif @@ -373,7 +373,7 @@ void CaptureSystemCursor() if (!drvWnd) return; SetCapture(drvWnd); #else - // on X11, set driver mouse capture on and store it locally as well + // on X11 and cocoa, set driver mouse capture on and store it locally as well Driver->setCapture(MouseCapture = true); #endif } @@ -392,7 +392,7 @@ void ReleaseSystemCursor() } ReleaseCapture(); #else - // on X11, set driver mouse capture off and store it locally as well + // on X11 and cocoa, set driver mouse capture off and store it locally as well Driver->setCapture(MouseCapture = false); #endif } diff --git a/code/ryzom/client/src/motion/user_controls.cpp b/code/ryzom/client/src/motion/user_controls.cpp index 29f2948a2..69e2efeea 100644 --- a/code/ryzom/client/src/motion/user_controls.cpp +++ b/code/ryzom/client/src/motion/user_controls.cpp @@ -458,25 +458,24 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy) { float dmpx, dmpy; -#ifndef NL_MAC_NATIVE - // On X11 in free look mode, the mouse is pulled back to (0.5, 0.5) + // On X11 and Cocoa in free look mode, the mouse is pulled back to (0.5, 0.5) // every update to prevent reaching a border and get stuck. if(IsMouseFreeLook()) { /* - TODO use setCapture to not fake it + TODO on X11, use setCapture to not fake it, capture on mac? */ dmpx = EventsListener.getMousePosX() - 0.5; dmpy = EventsListener.getMousePosY() - 0.5; } else -#endif { dmpx = EventsListener.getMousePosX() - _LastFrameMousePosX; dmpy = EventsListener.getMousePosY() - _LastFrameMousePosY; } - // TODO: read desktop mouse speed value on X11 / implement X11MouseDevice + // TODO: read desktop mouse speed value on X11 and Cocoa + // implement X11MouseDevice/CocoaMouseDevice? dmpx *= 450.0f; dmpy *= 450.0f;