Fixed: #1156 Handle window close/application quit cleanly

This commit is contained in:
rti 2010-11-05 12:57:31 +01:00
parent 0c5854ecc8
commit b11c346e3b
7 changed files with 125 additions and 6 deletions

View file

@ -782,9 +782,10 @@ private:
#elif defined(NL_OS_MAC)
friend bool GlWndProc(CDriverGL*, const void*);
friend void windowDidMove(NSWindow*, CDriverGL*);
friend void viewDidResize(NSView*, CDriverGL*);
friend bool GlWndProc(CDriverGL*, const void*);
friend void windowDidMove(NSWindow*, CDriverGL*);
friend void viewDidResize(NSView*, CDriverGL*);
friend NSApplicationTerminateReply applicationShouldTerminate(CDriverGL*);
NLMISC::CCocoaEventEmitter _EventEmitter;
NSOpenGLContext* _ctx;

View file

@ -26,7 +26,8 @@
# include <windowsx.h>
#elif defined(NL_OS_MAC)
# import "mac/cocoa_window_delegate.h"
# import <OpenGL/OpenGL.h>
# import "mac/cocoa_application_delegate.h"
# import <OpenGL/OpenGL.h>
#elif defined (NL_OS_UNIX)
# include <GL/gl.h>
# include <GL/glx.h>
@ -1432,6 +1433,18 @@ bool CDriverGL::createWindow(const GfxMode &mode)
return false;
}
// create an application delegate
CocoaApplicationDelegate* appDelegate =
[[CocoaApplicationDelegate alloc] initWithDriver:this];
// set the application delegate, this will handle window/app close events
[NSApp setDelegate:appDelegate];
// bind the close button of the window to applicationShouldTerminate
id closeButton = [cocoa_window standardWindowButton:NSWindowCloseButton];
[closeButton setAction:@selector(applicationShouldTerminate:)];
[closeButton setTarget:appDelegate];
// set the delegate which will handle window move events
[cocoa_window setDelegate:[[CocoaWindowDelegate alloc] initWithDriver:this]];

View file

@ -0,0 +1,33 @@
// 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;
NSApplicationTerminateReply applicationShouldTerminate(CDriverGL*);
}
@interface CocoaApplicationDelegate : NSObject<NSApplicationDelegate>
{
NL3D::CDriverGL* _driver;
}
-(id)initWithDriver:(NL3D::CDriverGL*)driver;
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
@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"
#include "cocoa_application_delegate.h"
#include "cocoa_event_emitter.h"
namespace NL3D
{
NSApplicationTerminateReply applicationShouldTerminate(CDriverGL* driver)
{
// cancel if there is a driver and a custom exit handler set up
if(driver && driver->ExitFunc)
{
driver->ExitFunc();
return NSTerminateCancel;
}
NLMISC::CCocoaEventEmitter* eventEmitter =
NLMISC::safe_cast<NLMISC::CCocoaEventEmitter*>(&(driver->_EventEmitter));
// cancel if there is a driver and cocoa event emitter handles the quit
if(driver && eventEmitter && eventEmitter->handleQuitRequest())
return NSTerminateCancel;
// just let the app terminate if no custom quit handling worked
return NSTerminateNow;
}
}
@implementation CocoaApplicationDelegate
-(id)initWithDriver:(NL3D::CDriverGL*)driver
{
if((self = [super init]))
{
_driver = driver;
return self;
}
return nil;
}
-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender
{
return NL3D::applicationShouldTerminate(_driver);
}
@end

View file

@ -410,6 +410,17 @@ bool CCocoaEventEmitter::processMessage(NSEvent* event, CEventServer* server)
return true;
}
bool CCocoaEventEmitter::handleQuitRequest()
{
if(_server)
{
_server->postEvent(new CEventDestroyWindow(this));
return true;
}
return false;
}
typedef bool (*cocoaProc)(NL3D::IDriver*, const void* e);
void CCocoaEventEmitter::submitEvents(CEventServer& server, bool /* allWins */)

View file

@ -50,6 +50,7 @@ public:
bool processMessage(NSEvent* event, CEventServer* server = NULL);
virtual void submitEvents(CEventServer& server, bool allWindows);
virtual void emulateMouseRawMode(bool enable);
bool handleQuitRequest();
virtual bool copyTextToClipboard(const ucstring &text);
virtual bool pasteTextFromClipboard(ucstring &text);

View file

@ -18,8 +18,6 @@
#import "cocoa_opengl_view.h"
#include <stdio.h>
namespace NL3D
{
void viewDidResize(NSView* view, CDriverGL* driver)