Mac: Change shutdown-related code to match Chromium (issue #1203)
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1648 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
6344555de7
commit
8b67278279
|
@ -42,6 +42,25 @@ char szWorkingDir[512]; // The current working directory
|
||||||
const int kWindowWidth = 800;
|
const int kWindowWidth = 800;
|
||||||
const int kWindowHeight = 600;
|
const int kWindowHeight = 600;
|
||||||
|
|
||||||
|
// Receives notifications from the application. Will delete itself when done.
|
||||||
|
@interface ClientAppDelegate : NSObject
|
||||||
|
- (void)createApplication:(id)object;
|
||||||
|
- (void)tryToTerminateApplication:(NSApplication*)app;
|
||||||
|
|
||||||
|
- (IBAction)testGetSource:(id)sender;
|
||||||
|
- (IBAction)testGetText:(id)sender;
|
||||||
|
- (IBAction)testPopupWindow:(id)sender;
|
||||||
|
- (IBAction)testRequest:(id)sender;
|
||||||
|
- (IBAction)testPluginInfo:(id)sender;
|
||||||
|
- (IBAction)testZoomIn:(id)sender;
|
||||||
|
- (IBAction)testZoomOut:(id)sender;
|
||||||
|
- (IBAction)testZoomReset:(id)sender;
|
||||||
|
- (IBAction)testBeginTracing:(id)sender;
|
||||||
|
- (IBAction)testEndTracing:(id)sender;
|
||||||
|
- (IBAction)testPrint:(id)sender;
|
||||||
|
- (IBAction)testOtherTests:(id)sender;
|
||||||
|
@end
|
||||||
|
|
||||||
// Provide the CefAppProtocol implementation required by CEF.
|
// Provide the CefAppProtocol implementation required by CEF.
|
||||||
@interface ClientApplication : NSApplication<CefAppProtocol> {
|
@interface ClientApplication : NSApplication<CefAppProtocol> {
|
||||||
@private
|
@private
|
||||||
|
@ -62,6 +81,50 @@ const int kWindowHeight = 600;
|
||||||
CefScopedSendingEvent sendingEventScoper;
|
CefScopedSendingEvent sendingEventScoper;
|
||||||
[super sendEvent:event];
|
[super sendEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// |-terminate:| is the entry point for orderly "quit" operations in Cocoa. This
|
||||||
|
// includes the application menu's quit menu item and keyboard equivalent, the
|
||||||
|
// application's dock icon menu's quit menu item, "quit" (not "force quit") in
|
||||||
|
// the Activity Monitor, and quits triggered by user logout and system restart
|
||||||
|
// and shutdown.
|
||||||
|
//
|
||||||
|
// The default |-terminate:| implementation ends the process by calling exit(),
|
||||||
|
// and thus never leaves the main run loop. This is unsuitable for Chromium
|
||||||
|
// since Chromium depends on leaving the main run loop to perform an orderly
|
||||||
|
// shutdown. We support the normal |-terminate:| interface by overriding the
|
||||||
|
// default implementation. Our implementation, which is very specific to the
|
||||||
|
// needs of Chromium, works by asking the application delegate to terminate
|
||||||
|
// using its |-tryToTerminateApplication:| method.
|
||||||
|
//
|
||||||
|
// |-tryToTerminateApplication:| differs from the standard
|
||||||
|
// |-applicationShouldTerminate:| in that no special event loop is run in the
|
||||||
|
// case that immediate termination is not possible (e.g., if dialog boxes
|
||||||
|
// allowing the user to cancel have to be shown). Instead, this method tries to
|
||||||
|
// close all browsers by calling CloseBrowser(false) via
|
||||||
|
// ClientHandler::CloseAllBrowsers. Calling CloseBrowser will result in a call
|
||||||
|
// to ClientHandler::DoClose and execution of |-performClose:| on the NSWindow.
|
||||||
|
// DoClose sets a flag that is used to differentiate between new close events
|
||||||
|
// (e.g., user clicked the window close button) and in-progress close events
|
||||||
|
// (e.g., user approved the close window dialog). The NSWindowDelegate
|
||||||
|
// |-windowShouldClose:| method checks this flag and either calls
|
||||||
|
// CloseBrowser(false) in the case of a new close event or destructs the
|
||||||
|
// NSWindow in the case of an in-progress close event.
|
||||||
|
// ClientHandler::OnBeforeClose will be called after the CEF NSView hosted in
|
||||||
|
// the NSWindow is dealloc'ed.
|
||||||
|
//
|
||||||
|
// After the final browser window has closed ClientHandler::OnBeforeClose will
|
||||||
|
// begin actual tear-down of the application by calling CefQuitMessageLoop.
|
||||||
|
// This ends the NSApplication event loop and execution then returns to the
|
||||||
|
// main() function for cleanup before application termination.
|
||||||
|
//
|
||||||
|
// The standard |-applicationShouldTerminate:| is not supported, and code paths
|
||||||
|
// leading to it must be redirected.
|
||||||
|
- (void)terminate:(id)sender {
|
||||||
|
ClientAppDelegate* delegate =
|
||||||
|
static_cast<ClientAppDelegate*>([NSApp delegate]);
|
||||||
|
[delegate tryToTerminateApplication:self];
|
||||||
|
// Return, don't exit. The application is responsible for exiting on its own.
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,27 +267,10 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receives notifications from the application. Will delete itself when done.
|
|
||||||
@interface ClientAppDelegate : NSObject
|
|
||||||
- (void)createApp:(id)object;
|
|
||||||
- (IBAction)testGetSource:(id)sender;
|
|
||||||
- (IBAction)testGetText:(id)sender;
|
|
||||||
- (IBAction)testPopupWindow:(id)sender;
|
|
||||||
- (IBAction)testRequest:(id)sender;
|
|
||||||
- (IBAction)testPluginInfo:(id)sender;
|
|
||||||
- (IBAction)testZoomIn:(id)sender;
|
|
||||||
- (IBAction)testZoomOut:(id)sender;
|
|
||||||
- (IBAction)testZoomReset:(id)sender;
|
|
||||||
- (IBAction)testBeginTracing:(id)sender;
|
|
||||||
- (IBAction)testEndTracing:(id)sender;
|
|
||||||
- (IBAction)testPrint:(id)sender;
|
|
||||||
- (IBAction)testOtherTests:(id)sender;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ClientAppDelegate
|
@implementation ClientAppDelegate
|
||||||
|
|
||||||
// Create the application on the UI thread.
|
// Create the application on the UI thread.
|
||||||
- (void)createApp:(id)object {
|
- (void)createApplication:(id)object {
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
|
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
|
||||||
|
|
||||||
|
@ -375,6 +421,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||||
[mainWnd setFrame:[mainWnd frameRectForContentRect:r] display:YES];
|
[mainWnd setFrame:[mainWnd frameRectForContentRect:r] display:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)tryToTerminateApplication:(NSApplication*)app {
|
||||||
|
if (g_handler.get() && !g_handler->IsClosing())
|
||||||
|
g_handler->CloseAllBrowsers(false);
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)testGetSource:(id)sender {
|
- (IBAction)testGetSource:(id)sender {
|
||||||
if (g_handler.get() && g_handler->GetBrowserId())
|
if (g_handler.get() && g_handler->GetBrowserId())
|
||||||
RunGetSourceTest(g_handler->GetBrowser());
|
RunGetSourceTest(g_handler->GetBrowser());
|
||||||
|
@ -441,22 +492,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||||
RunOtherTests(g_handler->GetBrowser());
|
RunOtherTests(g_handler->GetBrowser());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the application's Quit menu item is selected.
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:
|
- (NSApplicationTerminateReply)applicationShouldTerminate:
|
||||||
(NSApplication *)sender {
|
(NSApplication *)sender {
|
||||||
// Request that all browser windows close.
|
return NSTerminateNow;
|
||||||
if (g_handler.get())
|
|
||||||
g_handler->CloseAllBrowsers(false);
|
|
||||||
|
|
||||||
// Cancel the termination. The application will exit after all windows have
|
|
||||||
// closed.
|
|
||||||
return NSTerminateCancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sent immediately before the application terminates. This signal should not
|
|
||||||
// be called because we cancel the termination.
|
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
|
||||||
ASSERT(false); // Not reached.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -496,7 +534,8 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// Create the application delegate and window.
|
// Create the application delegate and window.
|
||||||
NSObject* delegate = [[ClientAppDelegate alloc] init];
|
NSObject* delegate = [[ClientAppDelegate alloc] init];
|
||||||
[delegate performSelectorOnMainThread:@selector(createApp:) withObject:nil
|
[delegate performSelectorOnMainThread:@selector(createApplication:)
|
||||||
|
withObject:nil
|
||||||
waitUntilDone:NO];
|
waitUntilDone:NO];
|
||||||
|
|
||||||
// Run the application message loop.
|
// Run the application message loop.
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
#include "cefsimple/util.h"
|
#include "cefsimple/util.h"
|
||||||
#include "include/cef_application_mac.h"
|
#include "include/cef_application_mac.h"
|
||||||
|
|
||||||
|
// Receives notifications from the application.
|
||||||
|
@interface SimpleAppDelegate : NSObject
|
||||||
|
- (void)createApplication:(id)object;
|
||||||
|
- (void)tryToTerminateApplication:(NSApplication*)app;
|
||||||
|
@end
|
||||||
|
|
||||||
// Provide the CefAppProtocol implementation required by CEF.
|
// Provide the CefAppProtocol implementation required by CEF.
|
||||||
@interface SimpleApplication : NSApplication<CefAppProtocol> {
|
@interface SimpleApplication : NSApplication<CefAppProtocol> {
|
||||||
@private
|
@private
|
||||||
|
@ -30,18 +36,56 @@
|
||||||
CefScopedSendingEvent sendingEventScoper;
|
CefScopedSendingEvent sendingEventScoper;
|
||||||
[super sendEvent:event];
|
[super sendEvent:event];
|
||||||
}
|
}
|
||||||
@end
|
|
||||||
|
|
||||||
|
// |-terminate:| is the entry point for orderly "quit" operations in Cocoa. This
|
||||||
// Receives notifications from the application.
|
// includes the application menu's quit menu item and keyboard equivalent, the
|
||||||
@interface SimpleAppDelegate : NSObject
|
// application's dock icon menu's quit menu item, "quit" (not "force quit") in
|
||||||
- (void)createApp:(id)object;
|
// the Activity Monitor, and quits triggered by user logout and system restart
|
||||||
|
// and shutdown.
|
||||||
|
//
|
||||||
|
// The default |-terminate:| implementation ends the process by calling exit(),
|
||||||
|
// and thus never leaves the main run loop. This is unsuitable for Chromium
|
||||||
|
// since Chromium depends on leaving the main run loop to perform an orderly
|
||||||
|
// shutdown. We support the normal |-terminate:| interface by overriding the
|
||||||
|
// default implementation. Our implementation, which is very specific to the
|
||||||
|
// needs of Chromium, works by asking the application delegate to terminate
|
||||||
|
// using its |-tryToTerminateApplication:| method.
|
||||||
|
//
|
||||||
|
// |-tryToTerminateApplication:| differs from the standard
|
||||||
|
// |-applicationShouldTerminate:| in that no special event loop is run in the
|
||||||
|
// case that immediate termination is not possible (e.g., if dialog boxes
|
||||||
|
// allowing the user to cancel have to be shown). Instead, this method tries to
|
||||||
|
// close all browsers by calling CloseBrowser(false) via
|
||||||
|
// ClientHandler::CloseAllBrowsers. Calling CloseBrowser will result in a call
|
||||||
|
// to ClientHandler::DoClose and execution of |-performClose:| on the NSWindow.
|
||||||
|
// DoClose sets a flag that is used to differentiate between new close events
|
||||||
|
// (e.g., user clicked the window close button) and in-progress close events
|
||||||
|
// (e.g., user approved the close window dialog). The NSWindowDelegate
|
||||||
|
// |-windowShouldClose:| method checks this flag and either calls
|
||||||
|
// CloseBrowser(false) in the case of a new close event or destructs the
|
||||||
|
// NSWindow in the case of an in-progress close event.
|
||||||
|
// ClientHandler::OnBeforeClose will be called after the CEF NSView hosted in
|
||||||
|
// the NSWindow is dealloc'ed.
|
||||||
|
//
|
||||||
|
// After the final browser window has closed ClientHandler::OnBeforeClose will
|
||||||
|
// begin actual tear-down of the application by calling CefQuitMessageLoop.
|
||||||
|
// This ends the NSApplication event loop and execution then returns to the
|
||||||
|
// main() function for cleanup before application termination.
|
||||||
|
//
|
||||||
|
// The standard |-applicationShouldTerminate:| is not supported, and code paths
|
||||||
|
// leading to it must be redirected.
|
||||||
|
- (void)terminate:(id)sender {
|
||||||
|
SimpleAppDelegate* delegate =
|
||||||
|
static_cast<SimpleAppDelegate*>([NSApp delegate]);
|
||||||
|
[delegate tryToTerminateApplication:self];
|
||||||
|
// Return, don't exit. The application is responsible for exiting on its own.
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SimpleAppDelegate
|
@implementation SimpleAppDelegate
|
||||||
|
|
||||||
// Create the application on the UI thread.
|
// Create the application on the UI thread.
|
||||||
- (void)createApp:(id)object {
|
- (void)createApplication:(id)object {
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
|
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
|
||||||
|
|
||||||
|
@ -49,24 +93,16 @@
|
||||||
[NSApp setDelegate:self];
|
[NSApp setDelegate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the application's Quit menu item is selected.
|
- (void)tryToTerminateApplication:(NSApplication*)app {
|
||||||
|
SimpleHandler* handler = SimpleHandler::GetInstance();
|
||||||
|
if (handler && !handler->IsClosing())
|
||||||
|
handler->CloseAllBrowsers(false);
|
||||||
|
}
|
||||||
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:
|
- (NSApplicationTerminateReply)applicationShouldTerminate:
|
||||||
(NSApplication *)sender {
|
(NSApplication *)sender {
|
||||||
// Request that all browser windows close.
|
return NSTerminateNow;
|
||||||
if (SimpleHandler* handler = SimpleHandler::GetInstance())
|
|
||||||
handler->CloseAllBrowsers(false);
|
|
||||||
|
|
||||||
// Cancel the termination. The application will exit after all windows have
|
|
||||||
// closed.
|
|
||||||
return NSTerminateCancel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sent immediately before the application terminates. This signal should not
|
|
||||||
// be called because we cancel the termination.
|
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
|
||||||
ASSERT(false); // Not reached.
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +129,8 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// Create the application delegate.
|
// Create the application delegate.
|
||||||
NSObject* delegate = [[SimpleAppDelegate alloc] init];
|
NSObject* delegate = [[SimpleAppDelegate alloc] init];
|
||||||
[delegate performSelectorOnMainThread:@selector(createApp:) withObject:nil
|
[delegate performSelectorOnMainThread:@selector(createApplication:)
|
||||||
|
withObject:nil
|
||||||
waitUntilDone:NO];
|
waitUntilDone:NO];
|
||||||
|
|
||||||
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
|
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
|
||||||
|
|
|
@ -17,7 +17,8 @@ SimpleHandler* g_instance = NULL;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SimpleHandler::SimpleHandler() {
|
SimpleHandler::SimpleHandler()
|
||||||
|
: is_closing_(false) {
|
||||||
ASSERT(!g_instance);
|
ASSERT(!g_instance);
|
||||||
g_instance = this;
|
g_instance = this;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +39,22 @@ void SimpleHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||||
browser_list_.push_back(browser);
|
browser_list_.push_back(browser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SimpleHandler::DoClose(CefRefPtr<CefBrowser> browser) {
|
||||||
|
REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
// Closing the main window requires special handling. See the DoClose()
|
||||||
|
// documentation in the CEF header for a detailed destription of this
|
||||||
|
// process.
|
||||||
|
if (browser_list_.size() == 1) {
|
||||||
|
// Set a flag to indicate that the window close should be allowed.
|
||||||
|
is_closing_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the close. For windowed browsers this will result in the OS close
|
||||||
|
// event being sent.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
void SimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||||
REQUIRE_UI_THREAD();
|
REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class SimpleHandler : public CefClient,
|
||||||
|
|
||||||
// CefLifeSpanHandler methods:
|
// CefLifeSpanHandler methods:
|
||||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||||
|
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||||
|
|
||||||
// CefLoadHandler methods:
|
// CefLoadHandler methods:
|
||||||
|
@ -49,11 +50,15 @@ class SimpleHandler : public CefClient,
|
||||||
// Request that all existing browser windows close.
|
// Request that all existing browser windows close.
|
||||||
void CloseAllBrowsers(bool force_close);
|
void CloseAllBrowsers(bool force_close);
|
||||||
|
|
||||||
|
bool IsClosing() const { return is_closing_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// List of existing browser windows. Only accessed on the CEF UI thread.
|
// List of existing browser windows. Only accessed on the CEF UI thread.
|
||||||
typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
|
typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
|
||||||
BrowserList browser_list_;
|
BrowserList browser_list_;
|
||||||
|
|
||||||
|
bool is_closing_;
|
||||||
|
|
||||||
// Include the default reference counting implementation.
|
// Include the default reference counting implementation.
|
||||||
IMPLEMENT_REFCOUNTING(SimpleHandler);
|
IMPLEMENT_REFCOUNTING(SimpleHandler);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue