| Index: chrome/browser/chrome_application_mac.mm
|
| diff --git a/chrome/browser/chrome_application_mac.mm b/chrome/browser/chrome_application_mac.mm
|
| index 94c975bd64b661b12a3641a2dea6239d59058b82..9453bc0f32334fc287a73575b606ed9815eb1655 100644
|
| --- a/chrome/browser/chrome_application_mac.mm
|
| +++ b/chrome/browser/chrome_application_mac.mm
|
| @@ -4,8 +4,9 @@
|
|
|
| #import "chrome/browser/chrome_application_mac.h"
|
|
|
| -#import "base/histogram.h"
|
| -#import "base/logging.h"
|
| +#include "base/histogram.h"
|
| +#include "base/logging.h"
|
| +#include "base/message_loop.h"
|
| #import "base/scoped_nsobject.h"
|
| #import "base/sys_string_conversions.h"
|
| #import "chrome/app/breakpad_mac.h"
|
| @@ -13,6 +14,15 @@
|
| #import "chrome/browser/cocoa/objc_method_swizzle.h"
|
| #import "chrome/browser/renderer_host/render_widget_host_view_mac.h"
|
|
|
| +// When C++ exceptions are disabled, the C++ library defines |try| and
|
| +// |catch| so as to allow exception-expecting C++ code to build properly when
|
| +// language support for exceptions is not present. These macros interfere
|
| +// with the use of |@try| and |@catch| in Objective-C files such as this one.
|
| +// Undefine these macros here, after everything has been #included, since
|
| +// there will be no C++ uses and only Objective-C uses from this point on.
|
| +#undef try
|
| +#undef catch
|
| +
|
| // The implementation of NSExceptions break various assumptions in the
|
| // Chrome code. This category defines a replacement for
|
| // -initWithName:reason:userInfo: for purposes of forcing a break in
|
| @@ -244,18 +254,34 @@ BOOL SwizzleNSExceptionInit() {
|
| }
|
|
|
| - (void)sendEvent:(NSEvent*)event {
|
| - // The superclass's |sendEvent:| sends keyboard events to the menu and the key
|
| - // view loop before dispatching them to |keyDown:|. Since we want to send keys
|
| - // to the renderer before sending them to the menu, and we never want them to
|
| - // the kev view loop when the web is focussed, we change this behavior.
|
| - if ([[self keyWindow]
|
| - isKindOfClass:[ChromeEventProcessingWindow class]]) {
|
| - if ([static_cast<ChromeEventProcessingWindow*>([self keyWindow])
|
| - shortcircuitEvent:event])
|
| - return;
|
| + // Messages from renderers and plug-ins can cause unfortunate
|
| + // interactions with modal event loops (consider a control which
|
| + // talks to a tab which is closed while you're click-dragging the
|
| + // mouse). This turns off handling of nested events for the
|
| + // duration of -sendEvent: handling, then restores the prior. Any
|
| + // event-handling code which needs nested events to work in a modal
|
| + // loop should explicitly turn handling back on using similar code.
|
| + bool wasEnabled = MessageLoop::current()->NestableTasksAllowed();
|
| + MessageLoop::current()->SetNestableTasksAllowed(false);
|
| +
|
| + @try {
|
| + // The superclass's |sendEvent:| sends keyboard events to the menu
|
| + // and the key view loop before dispatching them to
|
| + // |keyDown:|. Since we want to send keys to the renderer before
|
| + // sending them to the menu, and we never want them to go to the
|
| + // key view loop when the web is focussed, we change this
|
| + // behavior.
|
| + ChromeEventProcessingWindow* keyWindow =
|
| + static_cast<ChromeEventProcessingWindow*>([self keyWindow]);
|
| + if (![keyWindow isKindOfClass:[ChromeEventProcessingWindow class]] ||
|
| + ![keyWindow shortcircuitEvent:event]) {
|
| + [super sendEvent:event];
|
| + }
|
| + } @finally {
|
| + // ALWAYS set things back the way we found them, no matter what.
|
| + // Leaving nested tasks turned off breaks about a million things.
|
| + MessageLoop::current()->SetNestableTasksAllowed(wasEnabled);
|
| }
|
| -
|
| - [super sendEvent:event];
|
| }
|
|
|
| // NSExceptions which are caught by the event loop are logged here.
|
|
|