Fixed: #1130 Merge cocoa_adapter.mm code into driver_opengl*.cpp (and cocoa_event_emitter.cpp)
This commit is contained in:
parent
92a682bc1b
commit
120af2580d
11 changed files with 1006 additions and 1407 deletions
|
@ -48,6 +48,8 @@
|
|||
typedef HWND nlWindow;
|
||||
#define EmptyWindow NULL
|
||||
#elif defined(NL_OS_MAC)
|
||||
// TODO This should be NSView*, but then we would need to include Cocoa.h
|
||||
// and compile with "-x objective-c++" ... everything including this file.
|
||||
typedef void* nlWindow;
|
||||
#define EmptyWindow NULL
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
|
|
@ -2,6 +2,8 @@ FILE(GLOB SRC *.cpp *.h *.def)
|
|||
IF(APPLE)
|
||||
FILE(GLOB MAC_SRC mac/*.h mac/*.m mac/*.mm mac/*.cpp)
|
||||
SET(SRC ${SRC} ${MAC_SRC})
|
||||
SET_SOURCE_FILES_PROPERTIES(${SRC}
|
||||
PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
ENDIF(APPLE)
|
||||
|
||||
IF(WIN32)
|
||||
|
|
|
@ -29,10 +29,6 @@
|
|||
# include <string>
|
||||
# include <GL/gl.h>
|
||||
#elif defined(NL_OS_MAC)
|
||||
# define GL_GLEXT_LEGACY
|
||||
# include <OpenGL/gl.h>
|
||||
# include "mac/glext.h"
|
||||
# include "mac/cocoa_adapter.h"
|
||||
#elif defined (NL_OS_UNIX)
|
||||
# include <GL/gl.h>
|
||||
# include <GL/glx.h>
|
||||
|
@ -189,7 +185,23 @@ CDriverGL::CDriverGL()
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::ctor();
|
||||
_ctx = nil;
|
||||
_glView = nil;
|
||||
|
||||
_backBufferHeight = 0;
|
||||
_backBufferWidth = 0;
|
||||
|
||||
// autorelease pool for memory management
|
||||
_autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// init the application object
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
// create the menu in the top screen bar
|
||||
setupApplicationMenu();
|
||||
|
||||
// finish the application launching
|
||||
[NSApp finishLaunching];
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -331,7 +343,7 @@ CDriverGL::~CDriverGL()
|
|||
release();
|
||||
|
||||
#if defined(NL_OS_MAC)
|
||||
NL3D::MAC::dtor();
|
||||
[_autoreleasePool release];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -860,7 +872,12 @@ bool CDriverGL::swapBuffers()
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::swapBuffers(_win);
|
||||
// TODO: maybe do this somewhere else?
|
||||
[_autoreleasePool release];
|
||||
_autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[_ctx flushBuffer];
|
||||
[containerView() display];
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2307,8 +2324,8 @@ void CDriverGL::retrieveATIDriverVersion()
|
|||
RegCloseKey(parentKey);
|
||||
}
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
# warning "OpenGL Driver: Missing Mac Implementation for ATI version retrieval"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation for ATI version retrieval");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
// TODO for Linux: implement retrieveATIDriverVersion... assuming versions under linux are probably different
|
||||
|
|
|
@ -33,7 +33,10 @@
|
|||
# include <GL/gl.h>
|
||||
#elif defined(NL_OS_MAC)
|
||||
# define GL_GLEXT_LEGACY
|
||||
# import <Cocoa/Cocoa.h>
|
||||
# include <OpenGL/gl.h>
|
||||
# include "mac/glext.h"
|
||||
# import "mac/cocoa_opengl_view.h"
|
||||
#elif defined (NL_OS_UNIX)
|
||||
# define GLX_GLXEXT_PROTOTYPES
|
||||
# include <GL/gl.h>
|
||||
|
@ -701,6 +704,14 @@ private:
|
|||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NLMISC::CCocoaEventEmitter _EventEmitter;
|
||||
NSOpenGLContext* _ctx;
|
||||
NSOpenGLView* _glView;
|
||||
NSAutoreleasePool* _autoreleasePool;
|
||||
uint16 _backBufferHeight;
|
||||
uint16 _backBufferWidth;
|
||||
|
||||
NSView* containerView() { return (NSView*)_win; }
|
||||
void setupApplicationMenu();
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -1388,11 +1399,6 @@ public:
|
|||
CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInfoPtrList it);
|
||||
};
|
||||
|
||||
#ifdef NL_OS_MAC
|
||||
// Specific mac functions
|
||||
extern bool getMacModes(std::vector<GfxMode> &modes);
|
||||
#endif
|
||||
|
||||
} // NL3D
|
||||
|
||||
#endif // NL_DRIVER_OPENGL_H
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
#ifdef NL_OS_WINDOWS
|
||||
# include <windowsx.h>
|
||||
#elif defined(NL_OS_MAC)
|
||||
# define GL_GLEXT_LEGACY
|
||||
# include <OpenGL/gl.h>
|
||||
# include "mac/glext.h"
|
||||
# include "mac/cocoa_adapter.h"
|
||||
#elif defined (NL_OS_UNIX)
|
||||
# include <GL/gl.h>
|
||||
# include <GL/glx.h>
|
||||
|
@ -298,11 +294,7 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
|
|||
retrieveATIDriverVersion();
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
if(!NL3D::MAC::init(windowIcon, exitFunc))
|
||||
{
|
||||
nldebug("cannot init");
|
||||
return false;
|
||||
}
|
||||
// nothing to do
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -393,11 +385,7 @@ bool CDriverGL::unInit()
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
if(!NL3D::MAC::unInit())
|
||||
{
|
||||
nldebug("cannot uninit");
|
||||
return false;
|
||||
}
|
||||
// nothing to do
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -478,7 +466,7 @@ void CDriverGL::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
// nothing to do
|
||||
// nothing to do, on Mac OS X, only windows representing a file have icons
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
|
@ -901,10 +889,67 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
_win = NL3D::MAC::setDisplay(wnd, mode, show, resizeable);
|
||||
if (wnd == EmptyWindow)
|
||||
{
|
||||
if (!createWindow(mode))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_win = wnd;
|
||||
}
|
||||
|
||||
if(_win != EmptyWindow)
|
||||
_DestroyWindow = true;
|
||||
// setup opengl settings
|
||||
NSOpenGLPixelFormatAttribute att[] =
|
||||
{
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAColorSize, 24,
|
||||
NSOpenGLPFADepthSize, 24,
|
||||
NSOpenGLPFAAlphaSize, 8,
|
||||
NSOpenGLPFAStencilSize, 8,
|
||||
NSOpenGLPFANoRecovery,
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFABackingStore,
|
||||
0
|
||||
};
|
||||
|
||||
// put the settings into a format object
|
||||
NSOpenGLPixelFormat* format =
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:att];
|
||||
|
||||
if(!format)
|
||||
nlerror("cannot create NSOpenGLPixelFormat");
|
||||
|
||||
// create a opengl view with the created format
|
||||
_glView = [[CocoaOpenGLView alloc]
|
||||
initWithFrame:NSMakeRect(0, 0, 0, 0) pixelFormat: format];
|
||||
|
||||
if(!_glView)
|
||||
nlerror("cannot create view");
|
||||
|
||||
// make the view automatically fit the super view
|
||||
[_glView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];
|
||||
|
||||
// put the open gl view into the dummy view contained in the window
|
||||
[containerView() addSubview:_glView];
|
||||
|
||||
// adjust size
|
||||
[_glView setFrame: [containerView() frame]];
|
||||
|
||||
// create a opengl context for the view
|
||||
_ctx = [_glView openGLContext];
|
||||
|
||||
if(!_ctx)
|
||||
nlerror("cannot create context");
|
||||
|
||||
// free the pixel format object
|
||||
[format release];
|
||||
|
||||
// let the open gl view handle the input
|
||||
[[containerView() window] makeFirstResponder:_glView];
|
||||
|
||||
[_ctx flushBuffer];
|
||||
[containerView() display];
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
|
@ -1145,7 +1190,8 @@ bool CDriverGL::restoreScreenMode()
|
|||
return res;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// ***************************************************************************
|
||||
|
||||
#ifdef XF86VIDMODE
|
||||
static sint modeInfoToFrequency(XF86VidModeModeInfo *info)
|
||||
{
|
||||
|
@ -1153,7 +1199,8 @@ static sint modeInfoToFrequency(XF86VidModeModeInfo *info)
|
|||
}
|
||||
#endif // XF86VIDMODE
|
||||
|
||||
// --------------------------------------------------
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverGL::setScreenMode(const GfxMode &mode)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_setScreenMode)
|
||||
|
@ -1324,11 +1371,45 @@ bool CDriverGL::createWindow(const GfxMode &mode)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
window = NL3D::MAC::createWindow(mode);
|
||||
// describe how the window should look like and behave
|
||||
unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask |
|
||||
NSMiniaturizableWindowMask | NSResizableWindowMask;
|
||||
|
||||
// create a cocoa window with the size provided by the mode parameter
|
||||
NSWindow* cocoa_window = [[NSWindow alloc]
|
||||
initWithContentRect:NSMakeRect(0, 0, mode.Width, mode.Height)
|
||||
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
|
||||
|
||||
if(!cocoa_window)
|
||||
{
|
||||
nlerror("cannot create cocoa window");
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the window to non transparent
|
||||
[cocoa_window setOpaque:YES];
|
||||
|
||||
// enable mouse move events, NeL wants them
|
||||
[cocoa_window setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
// there are no overlapping subviews, can use the magical optimization :)
|
||||
[cocoa_window useOptimizedDrawing:YES];
|
||||
|
||||
// put the window to the front and make it the key window
|
||||
[cocoa_window makeKeyAndOrderFront:nil];
|
||||
|
||||
// this is our main window
|
||||
[cocoa_window makeMainWindow];
|
||||
|
||||
// create a dummy view which works like the window on other platforms
|
||||
// the open gl view will be created as subview of this one.
|
||||
window = [[NSView alloc] init];
|
||||
|
||||
[cocoa_window setContentView: (NSView*)window];
|
||||
|
||||
if(window == EmptyWindow)
|
||||
{
|
||||
nldebug("cannot create window");
|
||||
nldebug("cannot create cocoa view for cocoa window");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1368,6 +1449,7 @@ bool CDriverGL::createWindow(const GfxMode &mode)
|
|||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverGL::destroyWindow()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_destroyWindow)
|
||||
|
@ -1404,13 +1486,12 @@ bool CDriverGL::destroyWindow()
|
|||
|
||||
if(_DestroyWindow)
|
||||
{
|
||||
if(!NL3D::MAC::destroyWindow(_win))
|
||||
{
|
||||
nldebug("cannot destroy window");
|
||||
return false;
|
||||
}
|
||||
[containerView() release];
|
||||
[[containerView() window] release];
|
||||
}
|
||||
|
||||
_ctx = nil;
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
if (_DestroyWindow)
|
||||
|
@ -1436,6 +1517,8 @@ bool CDriverGL::destroyWindow()
|
|||
return true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
CDriverGL::EWindowStyle CDriverGL::getWindowStyle() const
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_getWindowStyle)
|
||||
|
@ -1446,6 +1529,8 @@ CDriverGL::EWindowStyle CDriverGL::getWindowStyle() const
|
|||
return EWSWindowed;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverGL::setWindowStyle(EWindowStyle windowStyle)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_setWindowStyle)
|
||||
|
@ -1500,10 +1585,57 @@ bool CDriverGL::setWindowStyle(EWindowStyle windowStyle)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
if(!NL3D::MAC::setWindowStyle(_win, windowStyle == EWSFullscreen))
|
||||
// leave fullscreen mode, enter windowed mode
|
||||
if(windowStyle == EWSWindowed && [containerView() isInFullScreenMode])
|
||||
{
|
||||
nldebug("cannot set window style");
|
||||
return false;
|
||||
// disable manual setting of back buffer size, cocoa handles this
|
||||
// automatically as soon as the view gets resized
|
||||
CGLError error = CGLDisable((CGLContextObj)[_ctx CGLContextObj],
|
||||
kCGLCESurfaceBackingSize);
|
||||
|
||||
if(error != kCGLNoError)
|
||||
nlerror("cannot disable kCGLCESurfaceBackingSize (%s)",
|
||||
CGLErrorString(error));
|
||||
|
||||
// pull the view back from fullscreen restoring window options
|
||||
[containerView() exitFullScreenModeWithOptions:nil];
|
||||
|
||||
// let the gl view receive key events
|
||||
[[containerView() window] makeFirstResponder:_glView];
|
||||
|
||||
// bring the window containing the gl view to the front
|
||||
[[containerView() window] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
// enter fullscreen, leave windowed mode
|
||||
else if(windowStyle == EWSFullscreen && ![containerView() isInFullScreenMode])
|
||||
{
|
||||
// enable manual back buffer size for mode setting in fullscreen
|
||||
CGLError error = CGLEnable((CGLContextObj)[_ctx CGLContextObj],
|
||||
kCGLCESurfaceBackingSize);
|
||||
|
||||
if(error != kCGLNoError)
|
||||
nlerror("cannot enable kCGLCESurfaceBackingSize (%s)",
|
||||
CGLErrorString(error));
|
||||
|
||||
// put the view in fullscreen mode, hiding the dock but enabling the menubar
|
||||
// to pop up if the mouse hits the top screen border.
|
||||
// NOTE: withOptions:nil disables <CMD>+<Tab> application switching!
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
[containerView() enterFullScreenMode:[NSScreen mainScreen] withOptions:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt:
|
||||
NSApplicationPresentationHideDock |
|
||||
NSApplicationPresentationAutoHideMenuBar],
|
||||
NSFullScreenModeApplicationPresentationOptions, nil]];
|
||||
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
/*
|
||||
TODO check if simply using NSView enterFullScreenMode is a good idea.
|
||||
the context can be set to full screen as well, performance differences?
|
||||
*/
|
||||
|
||||
// let the gl view receive key events
|
||||
[[containerView() window] makeFirstResponder:_glView];
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
@ -1558,6 +1690,8 @@ bool CDriverGL::setWindowStyle(EWindowStyle windowStyle)
|
|||
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
_FullScreen = (windowStyle == EWSFullscreen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1575,14 +1709,49 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
if (!mode.Windowed)
|
||||
_Depth = mode.Depth;
|
||||
|
||||
_FullScreen = !mode.Windowed;
|
||||
|
||||
setWindowSize(mode.Width, mode.Height);
|
||||
setWindowPos(_WindowX, _WindowY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(NL_OS_MAC) && defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
|
||||
|
||||
/// helper to extract bits per pixel value from screen mode, only 16 or 32 bits
|
||||
static int bppFromDisplayMode(CGDisplayModeRef mode)
|
||||
{
|
||||
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
|
||||
|
||||
if(CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
return 32;
|
||||
|
||||
else if(CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
return 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && !defined(AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER)
|
||||
|
||||
long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
|
||||
{
|
||||
long value = 0;
|
||||
CFNumberRef numRef;
|
||||
numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key);
|
||||
if (numRef != NULL)
|
||||
CFNumberGetValue(numRef, kCFNumberLongType, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
// some macros to make code more readable.
|
||||
#define GetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth)
|
||||
#define GetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight)
|
||||
#define GetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel)
|
||||
|
||||
#endif // defined(NL_OS_MAC)
|
||||
|
||||
// --------------------------------------------------
|
||||
bool CDriverGL::getModes(std::vector<GfxMode> &modes)
|
||||
{
|
||||
|
@ -1611,7 +1780,71 @@ bool CDriverGL::getModes(std::vector<GfxMode> &modes)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::getModes(modes);
|
||||
static const CGDisplayCount kMaxDisplays = 16;
|
||||
CGDirectDisplayID display[kMaxDisplays];
|
||||
CGDisplayCount numDisplays;
|
||||
|
||||
CGDisplayErr err = CGGetActiveDisplayList(kMaxDisplays, display, &numDisplays);
|
||||
if(err != CGDisplayNoErr)
|
||||
{
|
||||
nlwarning("Cannot get displays (%d)", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
// nldebug("3D: %d displays found", (int)numDisplays);
|
||||
|
||||
for (CGDisplayCount i = 0; i < numDisplays; ++i)
|
||||
{
|
||||
CGDirectDisplayID dspy = display[i];
|
||||
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
CFArrayRef modeList = CGDisplayCopyAllDisplayModes(dspy, NULL);
|
||||
#else
|
||||
CFArrayRef modeList = CGDisplayAvailableModes(dspy);
|
||||
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
|
||||
if (modeList == NULL)
|
||||
{
|
||||
nlwarning("Display is invalid");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (CFIndex j = 0; j < CFArrayGetCount(modeList); ++j)
|
||||
{
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modeList, j);
|
||||
uint8 bpp = bppFromDisplayMode(mode);
|
||||
#else
|
||||
CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(modeList, j);
|
||||
uint8 bpp = (uint8)GetModeBitsPerPixel(mode);
|
||||
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
|
||||
if (bpp >= 16)
|
||||
{
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
uint16 w = CGDisplayModeGetWidth(mode);
|
||||
uint16 h = CGDisplayModeGetHeight(mode);
|
||||
#else
|
||||
uint16 w = (uint16)GetModeWidth(mode);
|
||||
uint16 h = (uint16)GetModeHeight(mode);
|
||||
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
|
||||
// Add this mode
|
||||
GfxMode mode;
|
||||
mode.Width = w;
|
||||
mode.Height = h;
|
||||
mode.Depth = bpp;
|
||||
|
||||
// Frequency stays at 0 because on mac cocoa, display resolution
|
||||
// is never really changed. if rendering res < display res,
|
||||
// cocoa interpolates and keeps the display at it's original res.
|
||||
mode.Frequency = 0;
|
||||
modes.push_back (mode);
|
||||
|
||||
// nldebug(" Display 0x%x: Mode %dx%d, %d BPP", dspy, w, h, bpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -1722,7 +1955,30 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::getCurrentScreenMode(_win, mode);
|
||||
// the sceen with the menu bar
|
||||
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
|
||||
|
||||
mode.OffScreen = false;
|
||||
mode.Frequency = 0;
|
||||
mode.Depth = NSBitsPerPixelFromDepth([screen depth]);
|
||||
|
||||
// in fullscreen mode
|
||||
if([containerView() isInFullScreenMode])
|
||||
{
|
||||
// return the size of the back buffer (like having switched monitor mode)
|
||||
mode.Windowed = false;
|
||||
mode.Width = _backBufferWidth;
|
||||
mode.Height = _backBufferHeight;
|
||||
}
|
||||
|
||||
// in windowed mode
|
||||
else
|
||||
{
|
||||
// return the size of the screen with menu bar
|
||||
mode.Windowed = true;
|
||||
mode.Width = (uint16)[screen frame].size.width;
|
||||
mode.Height = (uint16)[screen frame].size.height;
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
|
@ -1830,7 +2086,8 @@ void CDriverGL::setWindowTitle(const ucstring &title)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::setWindowTitle(_win, title);
|
||||
[[containerView() window] setTitle:
|
||||
[NSString stringWithUTF8String:title.toUtf8().c_str()]];
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -1862,7 +2119,19 @@ void CDriverGL::setWindowPos(sint32 x, sint32 y)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::setWindowPos(_win, x, y);
|
||||
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];
|
||||
|
||||
// get the rect (position, size) of the window
|
||||
NSRect windowRect = [[containerView() window] frame];
|
||||
|
||||
// convert y from NeL coordinates to cocoa coordinates
|
||||
y = screenRect.size.height - y;
|
||||
|
||||
// tell cocoa to move the window
|
||||
[[containerView() window] setFrameTopLeftPoint:NSMakePoint(x, y)];
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -1895,7 +2164,7 @@ void CDriverGL::showWindow(bool show)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
MAC::showWindow(show);
|
||||
// TODO implement me
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -1940,11 +2209,8 @@ bool CDriverGL::activate()
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
if(!MAC::activate(_win))
|
||||
{
|
||||
nlwarning("cannot activate");
|
||||
return false;
|
||||
}
|
||||
if([NSOpenGLContext currentContext] != _ctx)
|
||||
[_ctx makeCurrentContext];
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2024,7 +2290,28 @@ void CDriverGL::showCursor(bool b)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::showCursor(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 show / hide cursor");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2077,7 +2364,30 @@ void CDriverGL::setMousePos(float x, float y)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::setMousePos(_win, x, y);
|
||||
// CG wants absolute coordinates related to first screen's top left
|
||||
|
||||
// get the first screen's (conaints menubar) rect (this is not mainScreen)
|
||||
NSRect firstScreenRect = [[[NSScreen screens] objectAtIndex:0] frame];
|
||||
|
||||
// get the rect (position, size) of the window
|
||||
NSRect windowRect;
|
||||
if([containerView() isInFullScreenMode])
|
||||
windowRect = [[[containerView() window] screen] frame];
|
||||
else
|
||||
windowRect = [[containerView() window] frame];
|
||||
|
||||
// get the view's rect for height and width
|
||||
NSRect viewRect = [containerView() frame];
|
||||
|
||||
// set the cursor position
|
||||
CGDisplayErr error = CGDisplayMoveCursorToPoint(
|
||||
kCGDirectMainDisplay, CGPointMake(
|
||||
windowRect.origin.x + (viewRect.size.width * x),
|
||||
firstScreenRect.size.height - windowRect.origin.y -
|
||||
viewRect.size.height + ((1.0 - y) * viewRect.size.height)));
|
||||
|
||||
if(error != kCGErrorSuccess)
|
||||
nlerror("cannot set mouse position");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2092,7 +2402,32 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
|
|||
|
||||
#ifdef NL_OS_MAC
|
||||
|
||||
NL3D::MAC::getWindowSize(_win, width, height);
|
||||
// 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
|
||||
|
||||
|
@ -2146,7 +2481,43 @@ void CDriverGL::setWindowSize(uint32 width, uint32 height)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::setWindowSize(_win, width, height);
|
||||
// for fullscreen mode, adjust the back buffer size to the 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(
|
||||
(CGLContextObj)[_ctx CGLContextObj],
|
||||
kCGLCPSurfaceBackingSize, dim);
|
||||
|
||||
if(error != kCGLNoError)
|
||||
nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)",
|
||||
CGLErrorString(error));
|
||||
|
||||
_backBufferWidth = width;
|
||||
_backBufferHeight = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
// only change the window size if the driver created the window itself
|
||||
if(_DestroyWindow)
|
||||
{
|
||||
// get the windows current frame
|
||||
NSRect rect = [[containerView() window] frame];
|
||||
|
||||
// convert the desired content size to window size
|
||||
rect = [[containerView() window] frameRectForContentRect:
|
||||
NSMakeRect(rect.origin.x, rect.origin.y, width, height)];
|
||||
|
||||
// update window dimensions
|
||||
[[containerView() window] setFrame:rect display:YES];
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
|
@ -2182,8 +2553,19 @@ 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
|
||||
|
||||
NL3D::MAC::getWindowPos(_win, x, y);
|
||||
// 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
|
||||
|
||||
|
@ -2219,9 +2601,7 @@ bool CDriverGL::isActive()
|
|||
res = (IsWindow(_win) != FALSE);
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
// nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
||||
# warning "OpenGL Driver: Missing Mac Implementation for isActive"
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
|
@ -2264,7 +2644,7 @@ void CDriverGL::setCapture (bool b)
|
|||
|
||||
#elif defined(NL_OS_MAC)
|
||||
|
||||
NL3D::MAC::setCapture(b);
|
||||
// no need to capture
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2316,11 +2696,7 @@ NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive
|
|||
}
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#endif
|
||||
|
||||
return res;
|
||||
|
@ -2358,11 +2734,7 @@ NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable)
|
|||
}
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#endif
|
||||
|
||||
return res;
|
||||
|
@ -2381,11 +2753,7 @@ NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager()
|
|||
res = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#endif
|
||||
|
||||
return res;
|
||||
|
@ -2429,8 +2797,8 @@ uint CDriverGL::getDoubleClickDelay(bool hardwareMouse)
|
|||
}
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
# warning "OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
|
@ -2492,11 +2860,10 @@ bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &proper
|
|||
}
|
||||
|
||||
#elif defined(NL_OS_MAC)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
// TODO for Mac: implement CDriverGL::setMonitorColorProperties
|
||||
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
// TODO for Linux: implement CDriverGL::setMonitorColorProperties
|
||||
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
|
||||
|
||||
|
@ -2505,4 +2872,64 @@ bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &proper
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef NL_OS_MAC
|
||||
void CDriverGL::setupApplicationMenu()
|
||||
{
|
||||
NSMenu* menu;
|
||||
NSMenuItem* menuItem;
|
||||
NSString* title;
|
||||
NSString* appName;
|
||||
|
||||
// get the applications name from it's process info
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
// create an empty menu object
|
||||
menu = [[NSMenu alloc] initWithTitle:@""];
|
||||
|
||||
// add the about menu item
|
||||
title = [@"About " stringByAppendingString:appName];
|
||||
[menu addItemWithTitle:title
|
||||
action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
|
||||
|
||||
// separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
// add the hide application menu item
|
||||
title = [@"Hide " stringByAppendingString:appName];
|
||||
[menu addItemWithTitle:title
|
||||
action:@selector(hide:) keyEquivalent:@"h"];
|
||||
|
||||
// add the hide others menu item
|
||||
menuItem = [menu addItemWithTitle:@"Hide Others"
|
||||
action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
|
||||
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
|
||||
|
||||
// add the show all menu item
|
||||
[menu addItemWithTitle:@"Show All"
|
||||
action:@selector(unhideAllApplications:) keyEquivalent:@""];
|
||||
|
||||
// separator
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
/*
|
||||
TODO on quit send EventDestroyWindowId
|
||||
*/
|
||||
// add the quit menu item
|
||||
title = [@"Quit " stringByAppendingString:appName];
|
||||
[menu addItemWithTitle:title
|
||||
action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
|
||||
// create an empty menu item and put the new menu into it as a subitem
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@""
|
||||
action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:menu];
|
||||
|
||||
// create a menu for the application
|
||||
[NSApp setMainMenu:[[NSMenu alloc] initWithTitle:@""]];
|
||||
|
||||
// attach the new menu to the applications menu
|
||||
[[NSApp mainMenu] addItem:menuItem];
|
||||
}
|
||||
#endif
|
||||
|
||||
} // NL3D
|
||||
|
|
|
@ -16,103 +16,4 @@
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NL_DRIVER_OPENGL_MAC_COCOA_ADAPTER_H
|
||||
#define NL_DRIVER_OPENGL_MAC_COCOA_ADAPTER_H
|
||||
|
||||
#include "nel/misc/types_nl.h"
|
||||
#include "nel/misc/event_server.h"
|
||||
#include "nel/3d/driver.h"
|
||||
|
||||
#include "cocoa_event_emitter.h"
|
||||
|
||||
/*
|
||||
* this cocoa adapter is a helper to call functions executing obj-c code
|
||||
* from driver_opengl.cpp
|
||||
*
|
||||
* please see this as a temporary solution... there is some stuff concerning
|
||||
* driver refactoring going on anyway as far as i know
|
||||
*
|
||||
* this can as well be seen as a preparation to pull platform specific code
|
||||
* out of driver_opengl.cpp ;)
|
||||
*
|
||||
* btw: we cannot simply use a c++ class here, because then NSWindow* and friends
|
||||
* would be members, but then we would need to add obj-c code here using an
|
||||
* include or a forward declaration. this again would break compiling cpp files
|
||||
* including this one (eg. driver_opengl.cpp)
|
||||
*/
|
||||
|
||||
namespace NL3D { namespace MAC {
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::CDriverGL()
|
||||
void ctor();
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::~CDriverGL()
|
||||
void dtor();
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::init()
|
||||
bool init(uint windowIcon = 0, emptyProc exitFunc = 0);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::unInit()
|
||||
bool unInit();
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::createWindow()
|
||||
nlWindow createWindow(const GfxMode& mode);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::destroyWindow()
|
||||
bool destroyWindow(nlWindow wnd);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setDisplay()
|
||||
nlWindow setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setWindowStyle()
|
||||
bool setWindowStyle(nlWindow wnd, bool fullscreen);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::getCurrentScreenMode()
|
||||
void getCurrentScreenMode(nlWindow wnd, GfxMode& mode);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::getModes()
|
||||
bool getModes(std::vector<GfxMode> &modes);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::getWindowSize()
|
||||
void getWindowSize(nlWindow wnd, uint32 &width, uint32 &height);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setWindowSize()
|
||||
void setWindowSize(nlWindow wnd, uint32 width, uint32 height);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::getWindowPos()
|
||||
void getWindowPos(nlWindow wnd, sint32 &x, sint32 &y);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setWindowPos()
|
||||
void setWindowPos(nlWindow wnd, sint32 x, sint32 y);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setWindowTitle()
|
||||
void setWindowTitle(nlWindow wnd, const ucstring& title);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::showWindow()
|
||||
void showWindow(bool show);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::activate()
|
||||
bool activate(nlWindow wnd);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::swapBuffers()
|
||||
void swapBuffers(nlWindow wnd);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setCapture()
|
||||
void setCapture(bool capture);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::showCursor()
|
||||
void showCursor(bool show);
|
||||
|
||||
/// mac specific stuff while calling CDriverGL::setMousePos()
|
||||
void setMousePos(nlWindow wnd, float x, float y);
|
||||
|
||||
/// mac specific stuff while calling CCocoaEventEmitter::submitEvents()
|
||||
void submitEvents(NLMISC::CEventServer& server,
|
||||
bool allWindows, NLMISC::CCocoaEventEmitter* eventEmitter);
|
||||
|
||||
/// mac specific stuff while calling CCocoaEventEmitter::emulateMouseRawMode()
|
||||
void emulateMouseRawMode(bool enable);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
/* TODO remove this file */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,21 +16,397 @@
|
|||
|
||||
#include "cocoa_event_emitter.h"
|
||||
|
||||
#include "cocoa_adapter.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
|
||||
{
|
||||
|
||||
void CCocoaEventEmitter::submitEvents(CEventServer & server, bool allWindows)
|
||||
/// map from virtual key code to nel internal key code
|
||||
static NLMISC::TKey virtualKeycodeToNelKey(unsigned short keycode)
|
||||
{
|
||||
// just forwarding to our cocoa adapter
|
||||
NL3D::MAC::submitEvents(server, allWindows, this);
|
||||
switch(keycode)
|
||||
{
|
||||
case kVK_ANSI_0: return NLMISC::Key0;
|
||||
case kVK_ANSI_1: return NLMISC::Key1;
|
||||
case kVK_ANSI_2: return NLMISC::Key2;
|
||||
case kVK_ANSI_3: return NLMISC::Key3;
|
||||
case kVK_ANSI_4: return NLMISC::Key4;
|
||||
case kVK_ANSI_5: return NLMISC::Key5;
|
||||
case kVK_ANSI_6: return NLMISC::Key6;
|
||||
case kVK_ANSI_7: return NLMISC::Key7;
|
||||
case kVK_ANSI_8: return NLMISC::Key8;
|
||||
case kVK_ANSI_9: return NLMISC::Key9;
|
||||
case kVK_ANSI_A: return NLMISC::KeyA;
|
||||
case kVK_ANSI_B: return NLMISC::KeyB;
|
||||
case kVK_ANSI_C: return NLMISC::KeyC;
|
||||
case kVK_ANSI_D: return NLMISC::KeyD;
|
||||
case kVK_ANSI_E: return NLMISC::KeyE;
|
||||
case kVK_ANSI_F: return NLMISC::KeyF;
|
||||
case kVK_ANSI_G: return NLMISC::KeyG;
|
||||
case kVK_ANSI_H: return NLMISC::KeyH;
|
||||
case kVK_ANSI_I: return NLMISC::KeyI;
|
||||
case kVK_ANSI_J: return NLMISC::KeyJ;
|
||||
case kVK_ANSI_K: return NLMISC::KeyK;
|
||||
case kVK_ANSI_L: return NLMISC::KeyL;
|
||||
case kVK_ANSI_M: return NLMISC::KeyM;
|
||||
case kVK_ANSI_N: return NLMISC::KeyN;
|
||||
case kVK_ANSI_O: return NLMISC::KeyO;
|
||||
case kVK_ANSI_P: return NLMISC::KeyP;
|
||||
case kVK_ANSI_Q: return NLMISC::KeyQ;
|
||||
case kVK_ANSI_R: return NLMISC::KeyR;
|
||||
case kVK_ANSI_S: return NLMISC::KeyS;
|
||||
case kVK_ANSI_T: return NLMISC::KeyT;
|
||||
case kVK_ANSI_U: return NLMISC::KeyU;
|
||||
case kVK_ANSI_V: return NLMISC::KeyV;
|
||||
case kVK_ANSI_W: return NLMISC::KeyW;
|
||||
case kVK_ANSI_X: return NLMISC::KeyX;
|
||||
case kVK_ANSI_Y: return NLMISC::KeyY;
|
||||
case kVK_ANSI_Z: return NLMISC::KeyZ;
|
||||
case kVK_ANSI_Equal: return NLMISC::KeyEQUALS;
|
||||
case kVK_ANSI_Minus: return NLMISC::KeySUBTRACT;
|
||||
case kVK_ANSI_RightBracket: return NLMISC::KeyRBRACKET;
|
||||
case kVK_ANSI_LeftBracket: return NLMISC::KeyLBRACKET;
|
||||
case kVK_ANSI_Quote: return NLMISC::KeyAPOSTROPHE;
|
||||
case kVK_ANSI_Grave: return NLMISC::KeyPARAGRAPH;
|
||||
case kVK_ANSI_Slash: return NLMISC::KeySLASH;
|
||||
case kVK_ANSI_Backslash: return NLMISC::KeyBACKSLASH;
|
||||
case kVK_ANSI_Comma: return NLMISC::KeyCOMMA;
|
||||
case kVK_ANSI_Period: return NLMISC::KeyPERIOD;
|
||||
case kVK_ANSI_Semicolon: return NLMISC::KeySEMICOLON;
|
||||
case kVK_ANSI_KeypadDecimal: return NLMISC::KeyDECIMAL;
|
||||
case kVK_ANSI_KeypadMultiply: return NLMISC::KeyMULTIPLY;
|
||||
case kVK_ANSI_KeypadPlus: return NLMISC::KeyADD;
|
||||
case kVK_ANSI_KeypadClear: return NLMISC::KeyDELETE;
|
||||
case kVK_ANSI_KeypadDivide: return NLMISC::KeyDIVIDE;
|
||||
case kVK_ANSI_KeypadEnter: return NLMISC::KeyRETURN;
|
||||
case kVK_ANSI_KeypadMinus: return NLMISC::KeySUBTRACT;
|
||||
case kVK_ANSI_KeypadEquals: return NLMISC::KeySEPARATOR;
|
||||
case kVK_ANSI_Keypad0: return NLMISC::KeyNUMPAD0;
|
||||
case kVK_ANSI_Keypad1: return NLMISC::KeyNUMPAD1;
|
||||
case kVK_ANSI_Keypad2: return NLMISC::KeyNUMPAD2;
|
||||
case kVK_ANSI_Keypad3: return NLMISC::KeyNUMPAD3;
|
||||
case kVK_ANSI_Keypad4: return NLMISC::KeyNUMPAD4;
|
||||
case kVK_ANSI_Keypad5: return NLMISC::KeyNUMPAD5;
|
||||
case kVK_ANSI_Keypad6: return NLMISC::KeyNUMPAD6;
|
||||
case kVK_ANSI_Keypad7: return NLMISC::KeyNUMPAD7;
|
||||
case kVK_ANSI_Keypad8: return NLMISC::KeyNUMPAD8;
|
||||
case kVK_ANSI_Keypad9: return NLMISC::KeyNUMPAD9;
|
||||
case kVK_Return: return NLMISC::KeyRETURN;
|
||||
case kVK_Tab: return NLMISC::KeyTAB;
|
||||
case kVK_Space: return NLMISC::KeySPACE;
|
||||
case kVK_Delete: return NLMISC::KeyBACK;
|
||||
case kVK_ForwardDelete: return NLMISC::KeyDELETE;
|
||||
case kVK_Escape: return NLMISC::KeyESCAPE;
|
||||
case kVK_Shift: return NLMISC::KeySHIFT;
|
||||
case kVK_RightShift: return NLMISC::KeyRSHIFT;
|
||||
case kVK_CapsLock: return NLMISC::KeyCAPITAL;
|
||||
case kVK_Control: return NLMISC::KeyCONTROL;
|
||||
case kVK_RightControl: return NLMISC::KeyRCONTROL;
|
||||
case kVK_F1: return NLMISC::KeyF1;
|
||||
case kVK_F2: return NLMISC::KeyF2;
|
||||
case kVK_F3: return NLMISC::KeyF3;
|
||||
case kVK_F4: return NLMISC::KeyF4;
|
||||
case kVK_F5: return NLMISC::KeyF5;
|
||||
case kVK_F6: return NLMISC::KeyF6;
|
||||
case kVK_F7: return NLMISC::KeyF7;
|
||||
case kVK_F8: return NLMISC::KeyF8;
|
||||
case kVK_F9: return NLMISC::KeyF9;
|
||||
case kVK_F11: return NLMISC::KeyF11;
|
||||
case kVK_F13: return NLMISC::KeyF13;
|
||||
case kVK_F16: return NLMISC::KeyF16;
|
||||
case kVK_F14: return NLMISC::KeyF14;
|
||||
case kVK_F10: return NLMISC::KeyF10;
|
||||
case kVK_F12: return NLMISC::KeyF12;
|
||||
case kVK_F15: return NLMISC::KeyF15;
|
||||
case kVK_F17: return NLMISC::KeyF17;
|
||||
case kVK_F18: return NLMISC::KeyF18;
|
||||
case kVK_F19: return NLMISC::KeyF19;
|
||||
case kVK_F20: return NLMISC::KeyF20;
|
||||
case kVK_Home: return NLMISC::KeyHOME;
|
||||
case kVK_End: return NLMISC::KeyEND;
|
||||
case kVK_PageUp: return NLMISC::KeyPRIOR;
|
||||
case kVK_PageDown: return NLMISC::KeyNEXT;
|
||||
case kVK_LeftArrow: return NLMISC::KeyLEFT;
|
||||
case kVK_RightArrow: return NLMISC::KeyRIGHT;
|
||||
case kVK_DownArrow: return NLMISC::KeyDOWN;
|
||||
case kVK_UpArrow: return NLMISC::KeyUP;
|
||||
case kVK_Command:break;
|
||||
case kVK_Option:break;
|
||||
case kVK_RightOption:break;
|
||||
case kVK_Function:break;
|
||||
case kVK_VolumeUp:break;
|
||||
case kVK_VolumeDown:break;
|
||||
case kVK_Mute:break;
|
||||
case kVK_Help:break;
|
||||
case kVK_ISO_Section:break;
|
||||
case kVK_JIS_Yen:break;
|
||||
case kVK_JIS_Underscore:break;
|
||||
case kVK_JIS_KeypadComma:break;
|
||||
case kVK_JIS_Eisu:break;
|
||||
case kVK_JIS_Kana:break;
|
||||
default:break;
|
||||
}
|
||||
return NLMISC::KeyNOKEY;
|
||||
}
|
||||
|
||||
/// convert modifier key state to nel internal modifier key state
|
||||
static NLMISC::TKeyButton modifierFlagsToNelKeyButton(unsigned int modifierFlags)
|
||||
{
|
||||
unsigned int buttons = 0;
|
||||
if (modifierFlags & NSControlKeyMask) buttons |= NLMISC::ctrlKeyButton;
|
||||
if (modifierFlags & NSShiftKeyMask) buttons |= NLMISC::shiftKeyButton;
|
||||
if (modifierFlags & NSAlternateKeyMask) buttons |= NLMISC::altKeyButton;
|
||||
return (NLMISC::TKeyButton)buttons;
|
||||
}
|
||||
|
||||
/// check whether a given event represents input text
|
||||
static bool isTextKeyEvent(NSEvent* event)
|
||||
{
|
||||
// if there are no characters provided with this event, it is not a text event
|
||||
if([[event characters] length] == 0)
|
||||
return false;
|
||||
|
||||
NLMISC::TKey nelKey = virtualKeycodeToNelKey([event keyCode]);
|
||||
|
||||
// ryzom ui wants to have "escape key string" to leave text box
|
||||
if(nelKey == NLMISC::KeyESCAPE)
|
||||
return true;
|
||||
|
||||
// ryzom ui wants to have "return key string" to submit text box (send chat)
|
||||
if(nelKey == NLMISC::KeyRETURN)
|
||||
return true;
|
||||
|
||||
// get the character reported by cocoa
|
||||
unsigned int character = [[event characters] characterAtIndex:0];
|
||||
|
||||
// printable ascii characters
|
||||
if(isprint(character))
|
||||
return true;
|
||||
|
||||
/*
|
||||
TODO check why iswprint(character) does not solve it.
|
||||
it always returns false, even for π, é, ...
|
||||
*/
|
||||
// characters > 127 but not printable
|
||||
if( nelKey == NLMISC::KeyF1 || nelKey == NLMISC::KeyF2 ||
|
||||
nelKey == NLMISC::KeyF3 || nelKey == NLMISC::KeyF4 ||
|
||||
nelKey == NLMISC::KeyF5 || nelKey == NLMISC::KeyF6 ||
|
||||
nelKey == NLMISC::KeyF7 || nelKey == NLMISC::KeyF8 ||
|
||||
nelKey == NLMISC::KeyF9 || nelKey == NLMISC::KeyF10 ||
|
||||
nelKey == NLMISC::KeyF11 || nelKey == NLMISC::KeyF12 ||
|
||||
nelKey == NLMISC::KeyF13 || nelKey == NLMISC::KeyF14 ||
|
||||
nelKey == NLMISC::KeyF15 || nelKey == NLMISC::KeyF16 ||
|
||||
nelKey == NLMISC::KeyF17 || nelKey == NLMISC::KeyF18 ||
|
||||
nelKey == NLMISC::KeyF19 || nelKey == NLMISC::KeyF20 ||
|
||||
nelKey == NLMISC::KeyUP || nelKey == NLMISC::KeyDOWN ||
|
||||
nelKey == NLMISC::KeyLEFT || nelKey == NLMISC::KeyRIGHT ||
|
||||
nelKey == NLMISC::KeyHOME || nelKey == NLMISC::KeyEND ||
|
||||
nelKey == NLMISC::KeyPRIOR || nelKey == NLMISC::KeyNEXT ||
|
||||
nelKey == NLMISC::KeyDELETE)
|
||||
return false;
|
||||
|
||||
// all the fancy wide characters
|
||||
if(character > 127)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */)
|
||||
{
|
||||
// break if there was no event to handle
|
||||
while(true)
|
||||
{
|
||||
// get the next event to handle
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:nil /*[NSDate distantFuture]*/
|
||||
inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
|
||||
// stop, if there was no event
|
||||
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)
|
||||
{
|
||||
[NSApp sendEvent:event];
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
|
||||
void CCocoaEventEmitter::emulateMouseRawMode(bool enable)
|
||||
{
|
||||
// just forwarding to our cocoa adapter
|
||||
NL3D::MAC::emulateMouseRawMode(enable);
|
||||
_emulateRawMode = enable;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,11 @@ namespace NLMISC
|
|||
|
||||
class CCocoaEventEmitter : public IEventEmitter
|
||||
{
|
||||
bool _emulateRawMode;
|
||||
|
||||
public:
|
||||
CCocoaEventEmitter() : _emulateRawMode(false) { }
|
||||
|
||||
virtual void submitEvents(CEventServer & server, bool allWindows);
|
||||
virtual void emulateMouseRawMode(bool enable);
|
||||
};
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/**
|
||||
* derived to configure the NSOpenGLView
|
||||
*/
|
||||
@interface CocoaOpenGLView : NSOpenGLView<NSTextInputClient>
|
||||
{
|
||||
NSMutableAttributedString* characterStorage;
|
||||
|
|
|
@ -18,15 +18,11 @@
|
|||
|
||||
#import "cocoa_opengl_view.h"
|
||||
|
||||
#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
||||
#define NL_USE_MAC_10_6_API 1
|
||||
#endif
|
||||
|
||||
@implementation CocoaOpenGLView
|
||||
|
||||
-(id)initWithFrame:(NSRect)frame
|
||||
{
|
||||
if(self = [super initWithFrame:frame])
|
||||
if((self = [super initWithFrame:frame]))
|
||||
{
|
||||
characterStorage = [[NSMutableAttributedString alloc] initWithString:@""];
|
||||
return self;
|
||||
|
@ -42,9 +38,9 @@
|
|||
|
||||
-(void)keyDown:(NSEvent*)event
|
||||
{
|
||||
#ifdef NL_USE_MAC_10_6_API
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
[[self inputContext] handleEvent:event];
|
||||
#endif // NL_USE_MAC_10_6_API
|
||||
#endif // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -80,7 +76,8 @@
|
|||
else
|
||||
{
|
||||
markedRange = NSMakeRange(replacementRange.location, [aString length]);
|
||||
[characterStorage replaceCharactersInRange:replacementRange withString:aString];
|
||||
[characterStorage replaceCharactersInRange:replacementRange
|
||||
withString:aString];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +105,8 @@
|
|||
if(replacementRange.location == NSNotFound)
|
||||
replacementRange = markedRange;
|
||||
|
||||
[characterStorage replaceCharactersInRange:replacementRange withString:aString];
|
||||
[characterStorage replaceCharactersInRange:replacementRange
|
||||
withString:aString];
|
||||
}
|
||||
|
||||
-(NSUInteger)characterIndexForPoint:(NSPoint)aPoint
|
||||
|
|
Loading…
Reference in a new issue