Changed: #947 mouse wheel, resizable flag

This commit is contained in:
rti 2010-06-11 16:21:27 +02:00
parent 0eda79d7b3
commit cb9217d8a3

View file

@ -52,7 +52,7 @@ void ctor()
{ {
// create a pool, cocoa code would leak memory otherwise // create a pool, cocoa code would leak memory otherwise
g_pool = [[NSAutoreleasePool alloc] init]; g_pool = [[NSAutoreleasePool alloc] init];
// init the application object // init the application object
g_app = [NSApplication sharedApplication]; g_app = [NSApplication sharedApplication];
} }
@ -62,7 +62,7 @@ void dtor()
/* /*
TODO there might be some more stuff to release ;) TODO there might be some more stuff to release ;)
*/ */
// release the pool // release the pool
[g_pool release]; [g_pool release];
} }
@ -78,20 +78,23 @@ bool init(uint windowIcon, emptyProc exitFunc)
bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
{ {
/* /*
TODO use show and resizable flags TODO use show
*/ */
/* /*
TODO add menu, on quit send EventDestroyWindowId TODO add menu, on quit send EventDestroyWindowId
*/ */
unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
if(resizeable)
styleMask |= NSResizableWindowMask;
// create a cocoa window with the size provided by the mode parameter // create a cocoa window with the size provided by the mode parameter
g_window = [[CocoaWindow alloc] g_window = [[CocoaWindow alloc]
initWithContentRect:NSMakeRect(0, 0, mode.Width, mode.Height) initWithContentRect:NSMakeRect(0, 0, mode.Width, mode.Height)
styleMask:NSTitledWindowMask | NSResizableWindowMask | styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
NSClosableWindowMask | NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
if(!g_window) if(!g_window)
nlerror("cannot create window"); nlerror("cannot create window");
@ -117,7 +120,7 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
// put the settings into a format object // put the settings into a format object
NSOpenGLPixelFormat* format = NSOpenGLPixelFormat* format =
[[NSOpenGLPixelFormat alloc] initWithAttributes:att]; [[NSOpenGLPixelFormat alloc] initWithAttributes:att];
if(!format) if(!format)
nlerror("cannot create NSOpenGLPixelFormat"); nlerror("cannot create NSOpenGLPixelFormat");
@ -160,7 +163,7 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
// free the pixel format object // free the pixel format object
[format release]; [format release];
// further mode setting, like switching to fullscreen and resolution setup // further mode setting, like switching to fullscreen and resolution setup
setMode(mode); setMode(mode);
@ -174,24 +177,24 @@ bool setMode(const GfxMode& mode)
{ {
// set the back buffer manually to match the desired rendering resolution // set the back buffer manually to match the desired rendering resolution
GLint dim[2] = { mode.Width, mode.Height }; GLint dim[2] = { mode.Width, mode.Height };
CGLError error = CGLSetParameter((CGLContextObj)[g_glctx CGLContextObj], CGLError error = CGLSetParameter((CGLContextObj)[g_glctx CGLContextObj],
kCGLCPSurfaceBackingSize, dim); kCGLCPSurfaceBackingSize, dim);
if(error != kCGLNoError) if(error != kCGLNoError)
nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)", nlerror("cannot set kCGLCPSurfaceBackingSize parameter (%s)",
CGLErrorString(error)); CGLErrorString(error));
} }
// leave fullscreen mode, enter windowed mode // leave fullscreen mode, enter windowed mode
if(mode.Windowed && [g_glview isInFullScreenMode]) if(mode.Windowed && [g_glview isInFullScreenMode])
{ {
// disable manual setting of back buffer size, cocoa handles this // disable manual setting of back buffer size, cocoa handles this
// automatically as soon as the view gets resized // automatically as soon as the view gets resized
CGLError error = CGLDisable((CGLContextObj)[g_glctx CGLContextObj], CGLError error = CGLDisable((CGLContextObj)[g_glctx CGLContextObj],
kCGLCESurfaceBackingSize); kCGLCESurfaceBackingSize);
if(error != kCGLNoError) if(error != kCGLNoError)
nlerror("cannot disable kCGLCESurfaceBackingSize (%s)", nlerror("cannot disable kCGLCESurfaceBackingSize (%s)",
CGLErrorString(error)); CGLErrorString(error));
// pull the view back from fullscreen restoring window options // pull the view back from fullscreen restoring window options
@ -202,20 +205,20 @@ bool setMode(const GfxMode& mode)
else if(!mode.Windowed && ![g_glview isInFullScreenMode]) else if(!mode.Windowed && ![g_glview isInFullScreenMode])
{ {
// enable manual back buffer size for mode setting in fullscreen // enable manual back buffer size for mode setting in fullscreen
CGLError error = CGLEnable((CGLContextObj)[g_glctx CGLContextObj], CGLError error = CGLEnable((CGLContextObj)[g_glctx CGLContextObj],
kCGLCESurfaceBackingSize); kCGLCESurfaceBackingSize);
if(error != kCGLNoError) if(error != kCGLNoError)
nlerror("cannot enable kCGLCESurfaceBackingSize (%s)", nlerror("cannot enable kCGLCESurfaceBackingSize (%s)",
CGLErrorString(error)); CGLErrorString(error));
// put the view in fullscreen mode, hiding the dock but enabling the menubar // put the view in fullscreen mode, hiding the dock but enabling the menubar
// to pop up if the mouse hits the top screen border. // to pop up if the mouse hits the top screen border.
// NOTE: withOptions:nil disables <CMD>+<Tab> application switching! // NOTE: withOptions:nil disables <CMD>+<Tab> application switching!
[g_glview enterFullScreenMode:[NSScreen mainScreen] withOptions: [g_glview enterFullScreenMode:[NSScreen mainScreen] withOptions:
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt: [NSNumber numberWithInt:
NSApplicationPresentationHideDock | NSApplicationPresentationHideDock |
NSApplicationPresentationAutoHideMenuBar], NSApplicationPresentationAutoHideMenuBar],
NSFullScreenModeApplicationPresentationOptions, nil]]; NSFullScreenModeApplicationPresentationOptions, nil]];
@ -223,8 +226,8 @@ bool setMode(const GfxMode& mode)
TODO check if simply using NSView enterFullScreenMode is a good idea. TODO check if simply using NSView enterFullScreenMode is a good idea.
the context can be set to full screen as well, performance differences? the context can be set to full screen as well, performance differences?
*/ */
} }
#ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND #ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND
// due to a back buffer size reading problem, just store the size // due to a back buffer size reading problem, just store the size
g_bufferSize[0] = mode.Width; g_bufferSize[0] = mode.Width;
@ -238,15 +241,15 @@ void getWindowSize(uint32 &width, uint32 &height)
{ {
if(!g_glctx) if(!g_glctx)
return; return;
// A cocoa fullscreen view stays at the native resolution of the display. // A cocoa fullscreen view stays at the native resolution of the display.
// When changing the rendering resolution, the size of the back buffer gets // 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 // 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 // the image from the rendered resolution to the view's resolution is done
// by cocoa automatically while flushing buffers. // by cocoa automatically while flushing buffers.
// That's why, in fullscreen mode, return the resolution of the back buffer, // That's why, in fullscreen mode, return the resolution of the back buffer,
// not the one from the window. // not the one from the window.
#ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND #ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND
// in fullscreen mode // in fullscreen mode
if([g_glview isInFullScreenMode]) if([g_glview isInFullScreenMode])
@ -270,13 +273,13 @@ void getWindowSize(uint32 &width, uint32 &height)
*/ */
// check if manual back buffer sizing is enabled (thats only in fullscreen) // check if manual back buffer sizing is enabled (thats only in fullscreen)
GLint surfaceBackingSizeSet = 0; GLint surfaceBackingSizeSet = 0;
CGLError error = CGLIsEnabled((CGLContextObj)[g_glctx CGLContextObj], CGLError error = CGLIsEnabled((CGLContextObj)[g_glctx CGLContextObj],
kCGLCESurfaceBackingSize, &surfaceBackingSizeSet); kCGLCESurfaceBackingSize, &surfaceBackingSizeSet);
if(error != kCGLNoError) if(error != kCGLNoError)
nlerror("cannot check kCGLCESurfaceBackingSize state (%s)", nlerror("cannot check kCGLCESurfaceBackingSize state (%s)",
CGLErrorString(error)); CGLErrorString(error));
// if in fullscreen mode (only in fullscreen back buffer sizing is used) // if in fullscreen mode (only in fullscreen back buffer sizing is used)
if(surfaceBackingSizeSet) if(surfaceBackingSizeSet)
{ {
@ -285,18 +288,18 @@ void getWindowSize(uint32 &width, uint32 &height)
*/ */
// get the back buffer size // get the back buffer size
GLint dim[2]; GLint dim[2];
CGLError error = CGLGetParameter((CGLContextObj)[g_glctx CGLContextObj], CGLError error = CGLGetParameter((CGLContextObj)[g_glctx CGLContextObj],
kCGLCPSurfaceBackingSize, dim); kCGLCPSurfaceBackingSize, dim);
if(error != kCGLNoError) if(error != kCGLNoError)
nlerror("cannot get kCGLCPSurfaceBackingSize value (%s)", nlerror("cannot get kCGLCPSurfaceBackingSize value (%s)",
CGLErrorString(error)); CGLErrorString(error));
// put size into ref params // put size into ref params
width = dim[0]; width = dim[0];
height = dim[1]; height = dim[1];
} }
// if in windowed mode // if in windowed mode
else else
{ {
@ -334,7 +337,7 @@ void setWindowPos(uint32 x, uint32 y)
NSRect windowRect = [g_window frame]; NSRect windowRect = [g_window frame];
// convert y from NeL coordinates to cocoa coordinates // convert y from NeL coordinates to cocoa coordinates
y = screenRect.size.height - y; y = screenRect.size.height - y;
// tell cocoa to move the window // tell cocoa to move the window
[g_window setFrameTopLeftPoint:NSMakePoint(x, y)]; [g_window setFrameTopLeftPoint:NSMakePoint(x, y)];
@ -365,9 +368,9 @@ void showCursor(bool b)
// by only calling hide if the cursor is visible and only calling show if // by only calling hide if the cursor is visible and only calling show if
// the cursor was hidden. // the cursor was hidden.
CGDisplayErr error = kCGErrorSuccess; CGDisplayErr error = kCGErrorSuccess;
static bool visible = true; static bool visible = true;
if(b && !visible) if(b && !visible)
{ {
error = CGDisplayShowCursor(kCGDirectMainDisplay); error = CGDisplayShowCursor(kCGDirectMainDisplay);
@ -378,17 +381,17 @@ void showCursor(bool b)
error = CGDisplayHideCursor(kCGDirectMainDisplay); error = CGDisplayHideCursor(kCGDirectMainDisplay);
visible = false; visible = false;
} }
if(error != kCGErrorSuccess) if(error != kCGErrorSuccess)
nlerror("cannot capture / un-capture cursor"); nlerror("cannot capture / un-capture cursor");
} }
void setMousePos(float x, float y) void setMousePos(float x, float y)
{ {
/* /*
TODO FIXME for windows placed on non primary monitor TODO FIXME for windows placed on non primary monitor
*/ */
// CG wants absolute coordinates related to screen top left // CG wants absolute coordinates related to screen top left
CGFloat fromScreenLeft = 0.0; CGFloat fromScreenLeft = 0.0;
CGFloat fromScreenTop = 0.0; CGFloat fromScreenTop = 0.0;
@ -409,11 +412,11 @@ void setMousePos(float x, float y)
fromScreenLeft = windowRect.origin.x; fromScreenLeft = windowRect.origin.x;
// TODO this code assumes, that the view fills the window // TODO this code assumes, that the view fills the window
// map window bottom to view top // map window bottom to view top
fromScreenTop = screenRect.size.height - fromScreenTop = screenRect.size.height -
viewRect.size.height - windowRect.origin.y; viewRect.size.height - windowRect.origin.y;
} }
// position inside the view // position inside the view
fromScreenLeft += (viewRect.size.width * x); fromScreenLeft += (viewRect.size.width * x);
@ -547,8 +550,8 @@ NLMISC::TKey virtualKeycodeToNelKey(unsigned short keycode)
case kVK_RightArrow: return NLMISC::KeyRIGHT; case kVK_RightArrow: return NLMISC::KeyRIGHT;
case kVK_DownArrow: return NLMISC::KeyDOWN; case kVK_DownArrow: return NLMISC::KeyDOWN;
case kVK_UpArrow: return NLMISC::KeyUP; case kVK_UpArrow: return NLMISC::KeyUP;
case kVK_Command:break; case kVK_Command:break;
case kVK_Option:break; case kVK_Option:break;
case kVK_RightOption:break; case kVK_RightOption:break;
case kVK_Function:break; case kVK_Function:break;
case kVK_VolumeUp:break; case kVK_VolumeUp:break;
@ -597,33 +600,33 @@ bool isTextKeyEvent(NSEvent* event)
// get the character reported by cocoa // get the character reported by cocoa
unsigned int character = [[event characters] characterAtIndex:0]; unsigned int character = [[event characters] characterAtIndex:0];
// printable ascii characters // printable ascii characters
if(isprint(character)) if(isprint(character))
return true; return true;
/* /*
TODO check why iswprint(character) does not solve it. TODO check why iswprint(character) does not solve it.
it always returns false, even for π, é, ... it always returns false, even for π, é, ...
*/ */
// characters > 127 but not printable // characters > 127 but not printable
if( nelKey == NLMISC::KeyF1 || nelKey == NLMISC::KeyF2 || if( nelKey == NLMISC::KeyF1 || nelKey == NLMISC::KeyF2 ||
nelKey == NLMISC::KeyF3 || nelKey == NLMISC::KeyF4 || nelKey == NLMISC::KeyF3 || nelKey == NLMISC::KeyF4 ||
nelKey == NLMISC::KeyF5 || nelKey == NLMISC::KeyF6 || nelKey == NLMISC::KeyF5 || nelKey == NLMISC::KeyF6 ||
nelKey == NLMISC::KeyF7 || nelKey == NLMISC::KeyF8 || nelKey == NLMISC::KeyF7 || nelKey == NLMISC::KeyF8 ||
nelKey == NLMISC::KeyF9 || nelKey == NLMISC::KeyF10 || nelKey == NLMISC::KeyF9 || nelKey == NLMISC::KeyF10 ||
nelKey == NLMISC::KeyF11 || nelKey == NLMISC::KeyF12 || nelKey == NLMISC::KeyF11 || nelKey == NLMISC::KeyF12 ||
nelKey == NLMISC::KeyF13 || nelKey == NLMISC::KeyF14 || nelKey == NLMISC::KeyF13 || nelKey == NLMISC::KeyF14 ||
nelKey == NLMISC::KeyF15 || nelKey == NLMISC::KeyF16 || nelKey == NLMISC::KeyF15 || nelKey == NLMISC::KeyF16 ||
nelKey == NLMISC::KeyF17 || nelKey == NLMISC::KeyF18 || nelKey == NLMISC::KeyF17 || nelKey == NLMISC::KeyF18 ||
nelKey == NLMISC::KeyF19 || nelKey == NLMISC::KeyF20 || nelKey == NLMISC::KeyF19 || nelKey == NLMISC::KeyF20 ||
nelKey == NLMISC::KeyUP || nelKey == NLMISC::KeyDOWN || nelKey == NLMISC::KeyUP || nelKey == NLMISC::KeyDOWN ||
nelKey == NLMISC::KeyLEFT || nelKey == NLMISC::KeyRIGHT || nelKey == NLMISC::KeyLEFT || nelKey == NLMISC::KeyRIGHT ||
nelKey == NLMISC::KeyHOME || nelKey == NLMISC::KeyEND || nelKey == NLMISC::KeyHOME || nelKey == NLMISC::KeyEND ||
nelKey == NLMISC::KeyPRIOR || nelKey == NLMISC::KeyNEXT || nelKey == NLMISC::KeyPRIOR || nelKey == NLMISC::KeyNEXT ||
nelKey == NLMISC::KeyDELETE) nelKey == NLMISC::KeyDELETE)
return false; return false;
// all the fancy wide characters // all the fancy wide characters
if(character > 127) if(character > 127)
return true; return true;
@ -716,15 +719,15 @@ void submitEvents(NLMISC::CEventServer& server,
TODO modifiers with mouse events TODO modifiers with mouse events
*/ */
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
if(g_emulateRawMode) if(g_emulateRawMode)
nelEvent = new NLMISC::CGDMouseMove( nelEvent = new NLMISC::CGDMouseMove(
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY); eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
(NLMISC::TMouseButton)0 /* modifiers */, eventEmitter); (NLMISC::TMouseButton)0 /* modifiers */, eventEmitter);
@ -738,14 +741,14 @@ void submitEvents(NLMISC::CEventServer& server,
*/ */
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
if(g_emulateRawMode) if(g_emulateRawMode)
nelEvent = new NLMISC::CGDMouseMove( nelEvent = new NLMISC::CGDMouseMove(
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY); eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
NLMISC::leftButton /* modifiers */, eventEmitter); NLMISC::leftButton /* modifiers */, eventEmitter);
server.postEvent(nelEvent); server.postEvent(nelEvent);
@ -758,14 +761,14 @@ void submitEvents(NLMISC::CEventServer& server,
*/ */
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
if(g_emulateRawMode) if(g_emulateRawMode)
nelEvent = new NLMISC::CGDMouseMove( nelEvent = new NLMISC::CGDMouseMove(
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY); eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
NLMISC::rightButton /* modifiers */, eventEmitter); NLMISC::rightButton /* modifiers */, eventEmitter);
server.postEvent(nelEvent); server.postEvent(nelEvent);
@ -777,13 +780,13 @@ void submitEvents(NLMISC::CEventServer& server,
{ {
// push the key press event to the event server // push the key press event to the event server
server.postEvent(new NLMISC::CEventKeyDown( server.postEvent(new NLMISC::CEventKeyDown(
virtualKeycodeToNelKey([event keyCode]), virtualKeycodeToNelKey([event keyCode]),
modifierFlagsToNelKeyButton([event modifierFlags]), modifierFlagsToNelKeyButton([event modifierFlags]),
[event isARepeat] == NO, [event isARepeat] == NO,
eventEmitter)); eventEmitter));
// if this was a text event // if this was a text event
if(isTextKeyEvent(event)) if(isTextKeyEvent(event))
{ {
ucstring ucstr; ucstring ucstr;
@ -792,8 +795,8 @@ void submitEvents(NLMISC::CEventServer& server,
// push the text event to event server as well // push the text event to event server as well
server.postEvent(new NLMISC::CEventChar( server.postEvent(new NLMISC::CEventChar(
ucstr[0], ucstr[0],
NLMISC::noKeyButton, NLMISC::noKeyButton,
eventEmitter)); eventEmitter));
} }
break; break;
@ -802,8 +805,8 @@ void submitEvents(NLMISC::CEventServer& server,
{ {
// push the key release event to the event server // push the key release event to the event server
server.postEvent(new NLMISC::CEventKeyUp( server.postEvent(new NLMISC::CEventKeyUp(
virtualKeycodeToNelKey([event keyCode]), virtualKeycodeToNelKey([event keyCode]),
modifierFlagsToNelKeyButton([event modifierFlags]), modifierFlagsToNelKeyButton([event modifierFlags]),
eventEmitter)); eventEmitter));
break; break;
} }
@ -813,7 +816,16 @@ void submitEvents(NLMISC::CEventServer& server,
case NSApplicationDefined:break; case NSApplicationDefined:break;
case NSPeriodic:break; case NSPeriodic:break;
case NSCursorUpdate:break; case NSCursorUpdate:break;
case NSScrollWheel:break; case NSScrollWheel:
{
/*
TODO modifiers with mouse events
*/
server.postEvent(new NLMISC::CEventMouseWheel(
mouseX, mouseY, (NLMISC::TMouseButton)0 /* modifiers */,
(event.deltaY > 0), eventEmitter));
break;
}
case NSTabletPoint:break; case NSTabletPoint:break;
case NSTabletProximity:break; case NSTabletProximity:break;
case NSOtherMouseDown:break; case NSOtherMouseDown:break;