summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm6
-rw-r--r--chrome/browser/cocoa/chrome_event_processing_window.h7
-rw-r--r--chrome/browser/cocoa/chrome_event_processing_window.mm61
-rw-r--r--chrome/browser/cocoa/html_dialog_window_controller.mm4
4 files changed, 67 insertions, 11 deletions
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index d5ed7e3..47bdfac 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -484,8 +484,8 @@ bool BrowserWindowCocoa::HandleKeyboardEventInternal(NSEvent* event) {
// Send the event to the menu before sending it to the browser/window
// shortcut handling, so that if a user configures cmd-left to mean
// "previous tab", it takes precedence over the built-in "history back"
- // binding. Other than that, the |redispatchEvent| call would take care of
- // invoking the original menu item shortcut as well.
+ // binding. Other than that, the |-redispatchKeyEvent:| call would take care
+ // of invoking the original menu item shortcut as well.
if ([[NSApp mainMenu] performKeyEquivalent:event])
return true;
@@ -500,7 +500,7 @@ bool BrowserWindowCocoa::HandleKeyboardEventInternal(NSEvent* event) {
return true;
}
- return [event_window redispatchEvent:event];
+ return [event_window redispatchKeyEvent:event];
}
void BrowserWindowCocoa::ShowCreateShortcutsDialog(TabContents* tab_contents) {
diff --git a/chrome/browser/cocoa/chrome_event_processing_window.h b/chrome/browser/cocoa/chrome_event_processing_window.h
index 0d9cfbb..4159be7 100644
--- a/chrome/browser/cocoa/chrome_event_processing_window.h
+++ b/chrome/browser/cocoa/chrome_event_processing_window.h
@@ -18,12 +18,13 @@
BOOL eventHandled_;
}
-// Sends an event to |NSApp sendEvent:|, but also makes sure that it's not
+// Sends a key event to |NSApp sendEvent:|, but also makes sure that it's not
// short-circuited to the RWHV. This is used to send keyboard events to the menu
// and the cmd-` handler if a keyboard event comes back unhandled from the
-// renderer.
+// renderer. The event must be of type |NSKeyDown|, |NSKeyUp|, or
+// |NSFlagsChanged|.
// Returns |YES| if |event| has been handled.
-- (BOOL)redispatchEvent:(NSEvent*)event;
+- (BOOL)redispatchKeyEvent:(NSEvent*)event;
// See global_keyboard_shortcuts_mac.h for details on the next two functions.
diff --git a/chrome/browser/cocoa/chrome_event_processing_window.mm b/chrome/browser/cocoa/chrome_event_processing_window.mm
index 36fea38..c4bee5b 100644
--- a/chrome/browser/cocoa/chrome_event_processing_window.mm
+++ b/chrome/browser/cocoa/chrome_event_processing_window.mm
@@ -13,6 +13,11 @@
typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
+@interface ChromeEventProcessingWindow ()
+// Duplicate the given key event, but changing the associated window.
+- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event;
+@end
+
@implementation ChromeEventProcessingWindow
- (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event fromTable:
@@ -79,9 +84,26 @@ typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
return [self handleDelayedWindowKeyboardShortcut:event];
}
-- (BOOL)redispatchEvent:(NSEvent*)event {
+- (BOOL)redispatchKeyEvent:(NSEvent*)event {
DCHECK(event);
- DCHECK_EQ([event window], self);
+ NSEventType eventType = [event type];
+ if (eventType != NSKeyDown &&
+ eventType != NSKeyUp &&
+ eventType != NSFlagsChanged) {
+ NOTREACHED();
+ return YES; // Pretend it's been handled in an effort to limit damage.
+ }
+
+ // Ordinarily, the event's window should be this window. However, when
+ // switching between normal and fullscreen mode, we switch out the window, and
+ // the event's window might be the previous window (or even an earlier one if
+ // the renderer is running slowly and several mode switches occur). In this
+ // rare case, we synthesize a new key event so that its associate window
+ // (number) is our own.
+ if ([event window] != self)
+ event = [self keyEventForWindow:self fromKeyEvent:event];
+
+ // Redispatch the event.
eventHandled_ = YES;
redispatchingEvent_ = YES;
[NSApp sendEvent:event];
@@ -100,5 +122,38 @@ typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
eventHandled_ = NO;
}
-@end // ChromeEventProcessingWindow
+- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event {
+ NSEventType eventType = [event type];
+
+ // Convert the event's location from the original window's coordinates into
+ // our own.
+ NSPoint eventLoc = [event locationInWindow];
+ eventLoc = [[event window] convertBaseToScreen:eventLoc];
+ eventLoc = [self convertScreenToBase:eventLoc];
+
+ // Various things *only* apply to key down/up.
+ BOOL eventIsARepeat = NO;
+ NSString* eventCharacters = nil;
+ NSString* eventUnmodCharacters = nil;
+ if (eventType == NSKeyDown || eventType == NSKeyUp) {
+ eventIsARepeat = [event isARepeat];
+ eventCharacters = [event characters];
+ eventUnmodCharacters = [event charactersIgnoringModifiers];
+ }
+
+ // This synthesis may be slightly imperfect: we provide nil for the context,
+ // since I (viettrungluu) am sceptical that putting in the original context
+ // (if one is given) is valid.
+ return [NSEvent keyEventWithType:eventType
+ location:eventLoc
+ modifierFlags:[event modifierFlags]
+ timestamp:[event timestamp]
+ windowNumber:[window windowNumber]
+ context:nil
+ characters:eventCharacters
+ charactersIgnoringModifiers:eventUnmodCharacters
+ isARepeat:eventIsARepeat
+ keyCode:[event keyCode]];
+}
+@end // ChromeEventProcessingWindow
diff --git a/chrome/browser/cocoa/html_dialog_window_controller.mm b/chrome/browser/cocoa/html_dialog_window_controller.mm
index c07d0c0..9287a1a9 100644
--- a/chrome/browser/cocoa/html_dialog_window_controller.mm
+++ b/chrome/browser/cocoa/html_dialog_window_controller.mm
@@ -200,8 +200,8 @@ void HtmlDialogWindowDelegateBridge::HandleKeyboardEvent(
ChromeEventProcessingWindow* event_window =
static_cast<ChromeEventProcessingWindow*>([controller_ window]);
-
- [event_window redispatchEvent:event.os_event];
+ DCHECK([event_window isKindOfClass:[ChromeEventProcessingWindow class]]);
+ [event_window redispatchKeyEvent:event.os_event];
}
@implementation HtmlDialogWindowController (InternalAPI)