This commit is contained in:
rti 2010-10-30 23:48:55 +02:00
commit 4716854ed6
10 changed files with 431 additions and 265 deletions

View file

@ -183,11 +183,10 @@ CDriverGL::CDriverGL()
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
_ctx = nil; _ctx = nil;
_glView = nil; _glView = nil;
_backBufferHeight = 0;
_backBufferHeight = 0; _backBufferWidth = 0;
_backBufferWidth = 0;
// autorelease pool for memory management // autorelease pool for memory management
_autoreleasePool = [[NSAutoreleasePool alloc] init]; _autoreleasePool = [[NSAutoreleasePool alloc] init];
@ -873,8 +872,11 @@ bool CDriverGL::swapBuffers()
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
// TODO: maybe do this somewhere else? // TODO: maybe do this somewhere else?
[_autoreleasePool release]; if(_DestroyWindow)
_autoreleasePool = [[NSAutoreleasePool alloc] init]; {
[_autoreleasePool release];
_autoreleasePool = [[NSAutoreleasePool alloc] init];
}
[_ctx flushBuffer]; [_ctx flushBuffer];
[containerView() display]; [containerView() display];

View file

@ -116,8 +116,7 @@ bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM
#elif defined (NL_OS_MAC) #elif defined (NL_OS_MAC)
// TODO: change that bool GlWndProc(CDriverGL *driver, NSEvent* e);
bool GlWndProc(CDriverGL *driver);
#elif defined (NL_OS_UNIX) #elif defined (NL_OS_UNIX)
@ -706,9 +705,13 @@ private:
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
friend bool GlWndProc(CDriverGL*, NSEvent*);
friend void windowDidMove(NSWindow*, CDriverGL*);
friend void viewDidResize(NSView*, CDriverGL*);
NLMISC::CCocoaEventEmitter _EventEmitter; NLMISC::CCocoaEventEmitter _EventEmitter;
NSOpenGLContext* _ctx; NSOpenGLContext* _ctx;
NSOpenGLView* _glView; CocoaOpenGLView* _glView;
NSAutoreleasePool* _autoreleasePool; NSAutoreleasePool* _autoreleasePool;
uint16 _backBufferHeight; uint16 _backBufferHeight;
uint16 _backBufferWidth; uint16 _backBufferWidth;

View file

@ -19,6 +19,7 @@
#include "nel/misc/types_nl.h" #include "nel/misc/types_nl.h"
#include "nel/misc/string_common.h"
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN

View file

@ -25,6 +25,7 @@
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
# include <windowsx.h> # include <windowsx.h>
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
# import "mac/cocoa_window_delegate.h"
#elif defined (NL_OS_UNIX) #elif defined (NL_OS_UNIX)
# include <GL/gl.h> # include <GL/gl.h>
# include <GL/glx.h> # include <GL/glx.h>
@ -164,8 +165,22 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
#elif defined (NL_OS_MAC) #elif defined (NL_OS_MAC)
bool GlWndProc(CDriverGL *driver) bool GlWndProc(CDriverGL *driver, NSEvent* e)
{ {
H_AUTO_OGL(GlWndProc)
// NSLog(@"NSEvent in GlWndProc %@", e);
if(!driver)
return false;
switch([e type])
{
/* TODO handle window activate, close, etc. */
default:
return driver->_EventEmitter.processMessage(e);
}
return false; return false;
} }
@ -927,6 +942,9 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
if(!_glView) if(!_glView)
nlerror("cannot create view"); 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 // make the view automatically fit the super view
[_glView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [_glView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];
@ -951,6 +969,8 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
[_ctx flushBuffer]; [_ctx flushBuffer];
[containerView() display]; [containerView() display];
_EventEmitter.init(this, _glView);
#elif defined(NL_OS_UNIX) #elif defined(NL_OS_UNIX)
static int sAttribList16bpp[] = static int sAttribList16bpp[] =
@ -1386,6 +1406,9 @@ bool CDriverGL::createWindow(const GfxMode &mode)
return false; return false;
} }
// set the delegate which will handle window move events
[cocoa_window setDelegate:[[CocoaWindowDelegate alloc] initWithDriver:this]];
// set the window to non transparent // set the window to non transparent
[cocoa_window setOpaque:YES]; [cocoa_window setOpaque:YES];
@ -1486,8 +1509,9 @@ bool CDriverGL::destroyWindow()
if(_DestroyWindow) if(_DestroyWindow)
{ {
[containerView() release];
[[containerView() window] release]; [[containerView() window] release];
[containerView() release];
[_glView release];
} }
_ctx = nil; _ctx = nil;
@ -2118,9 +2142,6 @@ void CDriverGL::setWindowPos(sint32 x, sint32 y)
SetWindowPos(_win, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); SetWindowPos(_win, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
#elif defined(NL_OS_MAC) #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 // get the rect (position, size) of the screen with menu bar
NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame]; NSRect screenRect = [[[NSScreen screens] objectAtIndex:0] frame];
@ -2164,7 +2185,7 @@ void CDriverGL::showWindow(bool show)
#elif defined(NL_OS_MAC) #elif defined(NL_OS_MAC)
// TODO implement me # warning "OpenGL Driver: Missing Mac Implementation for showWindow"
#elif defined (NL_OS_UNIX) #elif defined (NL_OS_UNIX)
@ -2400,38 +2421,6 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
{ {
H_AUTO_OGL(CDriverGL_getWindowSize) 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) if (_OffScreen)
{ {
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
@ -2444,11 +2433,17 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
} }
else else
{ {
#ifdef NL_OS_MAC
if([containerView() isInFullScreenMode])
{
width = _backBufferWidth;
height = _backBufferHeight;
return;
}
#endif
width = _WindowWidth; width = _WindowWidth;
height = _WindowHeight; height = _WindowHeight;
} }
#endif // NL_OS_MAC
} }
void CDriverGL::setWindowSize(uint32 width, uint32 height) void CDriverGL::setWindowSize(uint32 width, uint32 height)
@ -2481,7 +2476,7 @@ void CDriverGL::setWindowSize(uint32 width, uint32 height)
#elif defined(NL_OS_MAC) #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]) if([containerView() isInFullScreenMode])
{ {
// disable and re-enable fullscreen // disable and re-enable fullscreen
@ -2499,8 +2494,8 @@ void CDriverGL::setWindowSize(uint32 width, uint32 height)
nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)", nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)",
CGLErrorString(error)); CGLErrorString(error));
_backBufferWidth = width;
_backBufferHeight = height; _backBufferHeight = height;
_backBufferWidth = width;
} }
else else
{ {
@ -2552,23 +2547,6 @@ void CDriverGL::getWindowPos(sint32 &x, sint32 &y)
{ {
H_AUTO_OGL(CDriverGL_getWindowPos) 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 ? // Off-screen rendering ?
if (_OffScreen) if (_OffScreen)
{ {
@ -2582,8 +2560,6 @@ void CDriverGL::getWindowPos(sint32 &x, sint32 &y)
y = _WindowY; y = _WindowY;
} }
} }
#endif // NL_OS_MAC
} }
// -------------------------------------------------- // --------------------------------------------------
@ -2601,7 +2577,7 @@ bool CDriverGL::isActive()
res = (IsWindow(_win) != FALSE); res = (IsWindow(_win) != FALSE);
#elif defined(NL_OS_MAC) #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) #elif defined (NL_OS_UNIX)
#endif // NL_OS_UNIX #endif // NL_OS_UNIX

View file

@ -16,13 +16,6 @@
#include "cocoa_event_emitter.h" #include "cocoa_event_emitter.h"
#include "nel/misc/event_server.h"
#include "nel/misc/events.h"
#include "nel/misc/game_device_events.h"
#include <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
namespace NLMISC namespace NLMISC
{ {
@ -156,11 +149,13 @@ static NLMISC::TKey virtualKeycodeToNelKey(unsigned short keycode)
bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text) bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text)
{ {
#warning "OpenGL Driver: Missing Mac Implementation for pasteTextFromClipboard"
return false; return false;
} }
bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text) bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text)
{ {
#warning "OpenGL Driver: Missing Mac Implementation for copyTextToClipboard"
return false; return false;
} }
@ -227,6 +222,194 @@ static bool isTextKeyEvent(NSEvent* event)
return false; 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*, NSEvent* e);
void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */) void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */)
{ {
// break if there was no event to handle // break if there was no event to handle
@ -241,177 +424,22 @@ void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */)
if(!event) if(!event)
break; break;
NSView* glView = [[[[event window] contentView] subviews] lastObject]; if(_driver)
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]; cocoaProc proc = (cocoaProc)_driver->getWindowProc();
continue;
if(proc)
proc(_driver, event);
} }
else
// convert the modifiers for nel to pass them with the events
NLMISC::TKeyButton modifiers =
modifierFlagsToNelKeyButton([event modifierFlags]);
switch(event.type)
{ {
case NSLeftMouseDown: processMessage(event, &server);
{
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];
} }
// TODO like internal server in unix event emitter... review!
_server = &server;
// _server->pump();
} }
void CCocoaEventEmitter::emulateMouseRawMode(bool enable) void CCocoaEventEmitter::emulateMouseRawMode(bool enable)

View file

@ -17,23 +17,44 @@
#ifndef NL_COCOA_EVENT_EMITTER_H #ifndef NL_COCOA_EVENT_EMITTER_H
#define NL_COCOA_EVENT_EMITTER_H #define NL_COCOA_EVENT_EMITTER_H
#include <nel/misc/event_emitter.h> #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 <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
namespace NLMISC namespace NLMISC
{ {
class CCocoaEventEmitter : public IEventEmitter 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: 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 void emulateMouseRawMode(bool enable);
virtual bool copyTextToClipboard(const ucstring &text); virtual bool copyTextToClipboard(const ucstring &text);
virtual bool pasteTextFromClipboard(ucstring &text);}; virtual bool pasteTextFromClipboard(ucstring &text);
};
} }
#endif #endif

View file

@ -18,14 +18,22 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
namespace NL3D {
class CDriverGL;
void viewDidResize(NSView*, CDriverGL*);
}
@interface CocoaOpenGLView : NSOpenGLView<NSTextInputClient> @interface CocoaOpenGLView : NSOpenGLView<NSTextInputClient>
{ {
NSMutableAttributedString* characterStorage; NSMutableAttributedString* _characterStorage;
NSRange markedRange; NSRange _markedRange;
NL3D::CDriverGL* _driver;
} }
-(id)initWithFrame:(NSRect)frame; -(id)initWithFrame:(NSRect)frame;
-(void)dealloc; -(void)dealloc;
-(void)keyDown:(NSEvent*)event; -(void)keyDown:(NSEvent*)event;
-(void)setDriver:(NL3D::CDriverGL*)driver;
-(void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize;
@end @end

View file

@ -16,15 +16,30 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver_opengl.h"
#import "cocoa_opengl_view.h" #import "cocoa_opengl_view.h"
#include <stdio.h>
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 @implementation CocoaOpenGLView
-(id)initWithFrame:(NSRect)frame -(id)initWithFrame:(NSRect)frame
{ {
if((self = [super initWithFrame:frame])) if((self = [super initWithFrame:frame]))
{ {
characterStorage = [[NSMutableAttributedString alloc] initWithString:@""]; _characterStorage = [[NSMutableAttributedString alloc] initWithString:@""];
_driver = nil;
return self; return self;
} }
return nil; return nil;
@ -32,7 +47,7 @@
-(void)dealloc -(void)dealloc
{ {
[characterStorage release]; [_characterStorage release];
[super dealloc]; [super dealloc];
} }
@ -43,17 +58,32 @@
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER #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 */ /* NSTextInputClient Protocol */
-(BOOL)hasMarkedText -(BOOL)hasMarkedText
{ {
return (markedRange.location == NSNotFound ? NO : YES); return (_markedRange.location == NSNotFound ? NO : YES);
} }
-(NSRange)markedRange -(NSRange)markedRange
{ {
return markedRange; return _markedRange;
} }
-(NSRange)selectedRange -(NSRange)selectedRange
@ -66,24 +96,24 @@
replacementRange:(NSRange)replacementRange replacementRange:(NSRange)replacementRange
{ {
if(replacementRange.location == NSNotFound) if(replacementRange.location == NSNotFound)
replacementRange = markedRange; replacementRange = _markedRange;
if([aString length] == 0) if([aString length] == 0)
{ {
[characterStorage deleteCharactersInRange:replacementRange]; [_characterStorage deleteCharactersInRange:replacementRange];
[self unmarkText]; [self unmarkText];
} }
else else
{ {
markedRange = NSMakeRange(replacementRange.location, [aString length]); _markedRange = NSMakeRange(replacementRange.location, [aString length]);
[characterStorage replaceCharactersInRange:replacementRange [_characterStorage replaceCharactersInRange:replacementRange
withString:aString]; withString:aString];
} }
} }
-(void)unmarkText -(void)unmarkText
{ {
markedRange = NSMakeRange(NSNotFound, 0); _markedRange = NSMakeRange(NSNotFound, 0);
[[self inputContext] discardMarkedText]; [[self inputContext] discardMarkedText];
} }
@ -96,16 +126,16 @@
-(NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange -(NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange
actualRange:(NSRangePointer)actualRange actualRange:(NSRangePointer)actualRange
{ {
return [characterStorage attributedSubstringFromRange:aRange]; return [_characterStorage attributedSubstringFromRange:aRange];
} }
-(void)insertText:(id)aString -(void)insertText:(id)aString
replacementRange:(NSRange)replacementRange replacementRange:(NSRange)replacementRange
{ {
if(replacementRange.location == NSNotFound) if(replacementRange.location == NSNotFound)
replacementRange = markedRange; replacementRange = _markedRange;
[characterStorage replaceCharactersInRange:replacementRange [_characterStorage replaceCharactersInRange:replacementRange
withString:aString]; withString:aString];
} }

View file

@ -0,0 +1,35 @@
/*
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
namespace NL3D {
class CDriverGL;
void windowDidMove(NSWindow*, NL3D::CDriverGL*);
}
@interface CocoaWindowDelegate : NSObject<NSWindowDelegate>
{
NL3D::CDriverGL* _driver;
}
- (id)initWithDriver:(NL3D::CDriverGL*)driver;
- (void)windowDidMove:(NSNotification*)notification;
@end

View file

@ -0,0 +1,62 @@
/*
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
*/
#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