From a4c9a84d1e0eb8b835d21082e889db793e84cb07 Mon Sep 17 00:00:00 2001 From: rti Date: Sat, 30 Oct 2010 22:36:20 +0200 Subject: [PATCH] Changed: #1060 Implement getWndProc() on Mac OS X --- .../src/3d/driver/opengl/driver_opengl.cpp | 9 +- code/nel/src/3d/driver/opengl/driver_opengl.h | 4 +- .../driver/opengl/driver_opengl_extension.h | 1 + .../3d/driver/opengl/driver_opengl_window.cpp | 86 +++++-------------- .../driver/opengl/mac/cocoa_event_emitter.cpp | 4 +- .../driver/opengl/mac/cocoa_event_emitter.h | 4 +- .../3d/driver/opengl/mac/cocoa_opengl_view.h | 12 ++- .../3d/driver/opengl/mac/cocoa_opengl_view.m | 54 +++++++++--- .../driver/opengl/mac/cocoa_window_delegate.h | 35 ++++++++ .../opengl/mac/cocoa_window_delegate.mm | 62 +++++++++++++ 10 files changed, 186 insertions(+), 85 deletions(-) create mode 100644 code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.h create mode 100644 code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.mm diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index f4ea1f084..39017a5b6 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -185,11 +185,10 @@ CDriverGL::CDriverGL() #elif defined(NL_OS_MAC) - _ctx = nil; - _glView = nil; - - _backBufferHeight = 0; - _backBufferWidth = 0; + _ctx = nil; + _glView = nil; + _backBufferHeight = 0; + _backBufferWidth = 0; // autorelease pool for memory management _autoreleasePool = [[NSAutoreleasePool alloc] init]; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 54071bd0f..3af14a1d5 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -705,7 +705,9 @@ private: #elif defined(NL_OS_MAC) - friend bool GlWndProc(CDriverGL* driver, NSEvent* e); + friend bool GlWndProc(CDriverGL*, NSEvent*); + friend void windowDidMove(NSWindow*, CDriverGL*); + friend void viewDidResize(NSView*, CDriverGL*); NLMISC::CCocoaEventEmitter _EventEmitter; NSOpenGLContext* _ctx; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h index 134e0bd6b..a4d71ec08 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_extension.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl_extension.h @@ -19,6 +19,7 @@ #include "nel/misc/types_nl.h" +#include "nel/misc/string_common.h" #ifdef NL_OS_WINDOWS # define WIN32_LEAN_AND_MEAN 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 1583fb8ac..f65979873 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -25,6 +25,7 @@ #ifdef NL_OS_WINDOWS # include #elif defined(NL_OS_MAC) +# import "mac/cocoa_window_delegate.h" #elif defined (NL_OS_UNIX) # include # include @@ -168,14 +169,14 @@ bool GlWndProc(CDriverGL *driver, NSEvent* e) { H_AUTO_OGL(GlWndProc) + // NSLog(@"NSEvent in GlWndProc %@", e); + if(!driver) return false; - - // NSLog(@"NSEvent in GlWndProc %@", e); switch([e type]) { - /* TODO handle window move, resize, activate, close, etc. */ + /* TODO handle window activate, close, etc. */ default: return driver->_EventEmitter.processMessage(e); } @@ -941,6 +942,9 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re if(!_glView) nlerror("cannot create view"); + // tell the view about the driver so the view is able to update "window" size + [_glView setDriver:this]; + // make the view automatically fit the super view [_glView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; @@ -1401,6 +1405,9 @@ bool CDriverGL::createWindow(const GfxMode &mode) nlerror("cannot create cocoa window"); return false; } + + // set the delegate which will handle window move events + [cocoa_window setDelegate:[[CocoaWindowDelegate alloc] initWithDriver:this]]; // set the window to non transparent [cocoa_window setOpaque:YES]; @@ -1502,8 +1509,9 @@ bool CDriverGL::destroyWindow() if(_DestroyWindow) { - [containerView() release]; [[containerView() window] release]; + [containerView() release]; + [_glView release]; } _ctx = nil; @@ -2134,9 +2142,6 @@ void CDriverGL::setWindowPos(sint32 x, sint32 y) SetWindowPos(_win, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); #elif defined(NL_OS_MAC) - - nldebug("setting window pos to %d %d", x, y); - // get the rect (position, size) of the screen with menu bar NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; @@ -2416,38 +2421,6 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height) { H_AUTO_OGL(CDriverGL_getWindowSize) -#ifdef NL_OS_MAC - - // TODO set them in windowproc, so no special impl is needed here - - // A cocoa fullscreen view stays at the native resolution of the display. - // When changing the rendering resolution, the size of the back buffer gets - // 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 of the back buffer, - // not the one from the window. - - // in fullscreen mode - if([containerView() isInFullScreenMode]) - { - // use the size stored in setWindowSize() - width = _backBufferWidth; - height = _backBufferHeight; - } - - // in windowed mode - else - { - // use the size of the view - NSRect rect = [containerView() frame]; - width = rect.size.width; - height = rect.size.height; - } - -#else // NL_OS_MAC - - // Off-screen rendering ? if (_OffScreen) { #ifdef NL_OS_WINDOWS @@ -2460,11 +2433,17 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height) } else { +#ifdef NL_OS_MAC + if([containerView() isInFullScreenMode]) + { + width = _backBufferWidth; + height = _backBufferHeight; + return; + } +#endif width = _WindowWidth; height = _WindowHeight; } - -#endif // NL_OS_MAC } void CDriverGL::setWindowSize(uint32 width, uint32 height) @@ -2497,14 +2476,14 @@ void CDriverGL::setWindowSize(uint32 width, uint32 height) #elif defined(NL_OS_MAC) - // for fullscreen mode, adjust the back buffer size to the desired resolution + // for fullscreen mode, adjust the back buffer size to desired resolution if([containerView() isInFullScreenMode]) { // disable and re-enable fullscreen // fixes #1062 (http://dev.ryzom.com/issues/1062) setWindowStyle(EWSWindowed); setWindowStyle(EWSFullscreen); - + // set the back buffer manually to match the desired rendering resolution GLint dim[2] = { width, height }; CGLError error = CGLSetParameter( @@ -2515,8 +2494,8 @@ void CDriverGL::setWindowSize(uint32 width, uint32 height) nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)", CGLErrorString(error)); - _backBufferWidth = width; _backBufferHeight = height; + _backBufferWidth = width; } else { @@ -2568,23 +2547,6 @@ void CDriverGL::getWindowPos(sint32 &x, sint32 &y) { H_AUTO_OGL(CDriverGL_getWindowPos) -#ifdef NL_OS_MAC - // TODO set them in window proc so no special impl is needed here - - // get the rect (position, size) of the screen with menu bar - NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; - - // get the rect (position, size) of the window - NSRect windowRect = [[containerView() window] frame]; - - // simply return x - x = windowRect.origin.x; - - // map y from cocoa to NeL coordinates before returning - y = screenRect.size.height - windowRect.size.height - windowRect.origin.y; - -#else // NL_OS_MAC - // Off-screen rendering ? if (_OffScreen) { @@ -2598,8 +2560,6 @@ void CDriverGL::getWindowPos(sint32 &x, sint32 &y) y = _WindowY; } } - -#endif // NL_OS_MAC } // -------------------------------------------------- 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 9d126deea..f1c5e2ad9 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 @@ -149,11 +149,13 @@ static NLMISC::TKey virtualKeycodeToNelKey(unsigned short keycode) bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text) { +#warning "OpenGL Driver: Missing Mac Implementation for pasteTextFromClipboard" return false; } bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text) { +#warning "OpenGL Driver: Missing Mac Implementation for copyTextToClipboard" return false; } @@ -406,7 +408,7 @@ bool CCocoaEventEmitter::processMessage(NSEvent* event, CEventServer* server) return true; } -typedef bool (*cocoaProc)(NL3D::IDriver*, void* e); +typedef bool (*cocoaProc)(NL3D::IDriver*, NSEvent* e); void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */) { 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 1ba60d77b..806bb4d2c 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 @@ -52,7 +52,9 @@ public: virtual void emulateMouseRawMode(bool enable); virtual bool copyTextToClipboard(const ucstring &text); - virtual bool pasteTextFromClipboard(ucstring &text);}; + virtual bool pasteTextFromClipboard(ucstring &text); +}; + } #endif diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.h b/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.h index 1a4bc76f0..f314d203f 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_opengl_view.h @@ -18,14 +18,22 @@ #import +namespace NL3D { + class CDriverGL; + void viewDidResize(NSView*, CDriverGL*); +} + @interface CocoaOpenGLView : NSOpenGLView { - NSMutableAttributedString* characterStorage; - NSRange markedRange; + NSMutableAttributedString* _characterStorage; + NSRange _markedRange; + NL3D::CDriverGL* _driver; } -(id)initWithFrame:(NSRect)frame; -(void)dealloc; -(void)keyDown:(NSEvent*)event; +-(void)setDriver:(NL3D::CDriverGL*)driver; +-(void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize; @end 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 cc0a83800..ab014f5c3 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 @@ -16,15 +16,30 @@ // along with this program. If not, see . */ +#include "../driver_opengl.h" + #import "cocoa_opengl_view.h" +#include + +namespace NL3D { + void viewDidResize(NSView* view, CDriverGL* driver) + { + NSRect rect = [[view superview] frame]; + driver->_WindowWidth = rect.size.width; + driver->_WindowHeight = rect.size.height; + } +} + + @implementation CocoaOpenGLView -(id)initWithFrame:(NSRect)frame { if((self = [super initWithFrame:frame])) { - characterStorage = [[NSMutableAttributedString alloc] initWithString:@""]; + _characterStorage = [[NSMutableAttributedString alloc] initWithString:@""]; + _driver = nil; return self; } return nil; @@ -32,7 +47,7 @@ -(void)dealloc { - [characterStorage release]; + [_characterStorage release]; [super dealloc]; } @@ -43,17 +58,32 @@ #endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER } +-(void)setDriver:(NL3D::CDriverGL*)driver +{ + _driver = driver; +} + +-(void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize +{ + [super resizeWithOldSuperviewSize:oldBoundsSize]; + + if(!_driver) + return; + + NL3D::viewDidResize(self, _driver); +} + /******************************************************************************/ /* NSTextInputClient Protocol */ -(BOOL)hasMarkedText { - return (markedRange.location == NSNotFound ? NO : YES); + return (_markedRange.location == NSNotFound ? NO : YES); } -(NSRange)markedRange { - return markedRange; + return _markedRange; } -(NSRange)selectedRange @@ -66,24 +96,24 @@ replacementRange:(NSRange)replacementRange { if(replacementRange.location == NSNotFound) - replacementRange = markedRange; + replacementRange = _markedRange; if([aString length] == 0) { - [characterStorage deleteCharactersInRange:replacementRange]; + [_characterStorage deleteCharactersInRange:replacementRange]; [self unmarkText]; } else { - markedRange = NSMakeRange(replacementRange.location, [aString length]); - [characterStorage replaceCharactersInRange:replacementRange + _markedRange = NSMakeRange(replacementRange.location, [aString length]); + [_characterStorage replaceCharactersInRange:replacementRange withString:aString]; } } -(void)unmarkText { - markedRange = NSMakeRange(NSNotFound, 0); + _markedRange = NSMakeRange(NSNotFound, 0); [[self inputContext] discardMarkedText]; } @@ -96,16 +126,16 @@ -(NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { - return [characterStorage attributedSubstringFromRange:aRange]; + return [_characterStorage attributedSubstringFromRange:aRange]; } -(void)insertText:(id)aString replacementRange:(NSRange)replacementRange { if(replacementRange.location == NSNotFound) - replacementRange = markedRange; + replacementRange = _markedRange; - [characterStorage replaceCharactersInRange:replacementRange + [_characterStorage replaceCharactersInRange:replacementRange withString:aString]; } diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.h b/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.h new file mode 100644 index 000000000..c439c363d --- /dev/null +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.h @@ -0,0 +1,35 @@ +/* +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +*/ + +#import + +namespace NL3D { + class CDriverGL; + void windowDidMove(NSWindow*, NL3D::CDriverGL*); +} + + +@interface CocoaWindowDelegate : NSObject +{ + NL3D::CDriverGL* _driver; +} + +- (id)initWithDriver:(NL3D::CDriverGL*)driver; +- (void)windowDidMove:(NSNotification*)notification; + +@end diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.mm b/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.mm new file mode 100644 index 000000000..6a7ce4c4c --- /dev/null +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_window_delegate.mm @@ -0,0 +1,62 @@ +/* +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +*/ + +#include "../driver_opengl.h" + +#import "cocoa_window_delegate.h" + +namespace NL3D { + void windowDidMove(NSWindow* window, NL3D::CDriverGL* driver) + { + // get the rect (position, size) of the screen with menu bar + NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; + + // get the rect (position, size) of the window + NSRect windowRect = [window frame]; + + // set x in driver + driver->_WindowX = windowRect.origin.x; + + // map y from cocoa to NeL coordinates before setting in driver + driver->_WindowY = + screenRect.size.height - windowRect.size.height - windowRect.origin.y; + } +} + +@implementation CocoaWindowDelegate + +-(id)initWithDriver:(NL3D::CDriverGL*)driver +{ + if((self = [super init])) + { + _driver = driver; + return self; + } + + return nil; +} + +-(void)windowDidMove:(NSNotification *)notification +{ + if(!_driver) + return; + + NL3D::windowDidMove([notification object], _driver); +} + +@end