summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/cocoa/rwhvm_editcommand_helper.h4
-rw-r--r--chrome/browser/cocoa/rwhvm_editcommand_helper.mm62
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm71
3 files changed, 103 insertions, 34 deletions
diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper.h b/chrome/browser/cocoa/rwhvm_editcommand_helper.h
index 25a8a73..458b58c 100644
--- a/chrome/browser/cocoa/rwhvm_editcommand_helper.h
+++ b/chrome/browser/cocoa/rwhvm_editcommand_helper.h
@@ -51,6 +51,10 @@ class RWHVMEditCommandHelper {
bool IsMenuItemEnabled(SEL item_action,
id<RenderWidgetHostViewMacOwner> owner);
+ // Converts an editing selector into a command name that can be sent to
+ // webkit.
+ static NSString* CommandNameForSelector(SEL selector);
+
protected:
// Gets a list of all the selectors that AddEditingSelectorsToClass adds to
// the aforementioned class.
diff --git a/chrome/browser/cocoa/rwhvm_editcommand_helper.mm b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
index c4b1efd..fe02a88 100644
--- a/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
+++ b/chrome/browser/cocoa/rwhvm_editcommand_helper.mm
@@ -105,35 +105,6 @@ const char* kEditCommands[] = {
"yank",
"yankAndSelect"};
-// Maps an objc-selector to a core command name.
-//
-// Returns the core command name (which is the selector name with the trailing
-// ':' stripped in most cases).
-//
-// Adapted from a function by the same name in
-// WebKit/mac/WebView/WebHTMLView.mm .
-// Capitalized names are returned from this function, but that's simply
-// matching WebHTMLView.mm.
-NSString* CommandNameForSelector(SEL selector) {
- if (selector == @selector(insertParagraphSeparator:) ||
- selector == @selector(insertNewlineIgnoringFieldEditor:))
- return @"InsertNewline";
- if (selector == @selector(insertTabIgnoringFieldEditor:))
- return @"InsertTab";
- if (selector == @selector(pageDown:))
- return @"MovePageDown";
- if (selector == @selector(pageDownAndModifySelection:))
- return @"MovePageDownAndModifySelection";
- if (selector == @selector(pageUp:))
- return @"MovePageUp";
- if (selector == @selector(pageUpAndModifySelection:))
- return @"MovePageUpAndModifySelection";
-
- // Remove the trailing colon.
- NSString* selector_str = NSStringFromSelector(selector);
- int selector_len = [selector_str length];
- return [selector_str substringToIndex:selector_len - 1];
-}
// This function is installed via the objc runtime as the implementation of all
// the various editing selectors.
@@ -157,7 +128,8 @@ void EditCommandImp(id self, SEL _cmd, id sender) {
DCHECK([self conformsToProtocol:@protocol(RenderWidgetHostViewMacOwner)]);
// SEL -> command name string.
- NSString* command_name_ns = CommandNameForSelector(_cmd);
+ NSString* command_name_ns =
+ RWHVMEditCommandHelper::CommandNameForSelector(_cmd);
std::string edit_command([command_name_ns UTF8String]);
// Forward the edit command string down the pipeline.
@@ -171,6 +143,36 @@ void EditCommandImp(id self, SEL _cmd, id sender) {
} // namespace
+// Maps an objc-selector to a core command name.
+//
+// Returns the core command name (which is the selector name with the trailing
+// ':' stripped in most cases).
+//
+// Adapted from a function by the same name in
+// WebKit/mac/WebView/WebHTMLView.mm .
+// Capitalized names are returned from this function, but that's simply
+// matching WebHTMLView.mm.
+NSString* RWHVMEditCommandHelper::CommandNameForSelector(SEL selector) {
+ if (selector == @selector(insertParagraphSeparator:) ||
+ selector == @selector(insertNewlineIgnoringFieldEditor:))
+ return @"InsertNewline";
+ if (selector == @selector(insertTabIgnoringFieldEditor:))
+ return @"InsertTab";
+ if (selector == @selector(pageDown:))
+ return @"MovePageDown";
+ if (selector == @selector(pageDownAndModifySelection:))
+ return @"MovePageDownAndModifySelection";
+ if (selector == @selector(pageUp:))
+ return @"MovePageUp";
+ if (selector == @selector(pageUpAndModifySelection:))
+ return @"MovePageUpAndModifySelection";
+
+ // Remove the trailing colon.
+ NSString* selector_str = NSStringFromSelector(selector);
+ int selector_len = [selector_str length];
+ return [selector_str substringToIndex:selector_len - 1];
+}
+
RWHVMEditCommandHelper::RWHVMEditCommandHelper() {
for (size_t i = 0; i < arraysize(kEditCommands); ++i) {
edit_command_set_.insert(kEditCommands[i]);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 21fce5f..82145d0 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -5,6 +5,7 @@
#include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
#include "base/histogram.h"
+#include "base/scoped_nsobject.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "chrome/browser/browser_trial.h"
@@ -14,6 +15,7 @@
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/common/native_web_keyboard_event.h"
+#include "chrome/common/edit_command.h"
#include "chrome/common/render_messages.h"
#include "skia/ext/platform_canvas.h"
#include "webkit/api/public/mac/WebInputEventFactory.h"
@@ -430,6 +432,60 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
render_widget_host_->routing_id(), background));
}
+// EditCommandMatcher ---------------------------------------------------------
+
+// This class is used to capture the shortcuts that a given key event maps to.
+// We instantiate a vanilla NSResponder, call interpretKeyEvents on it, and
+// record all of the selectors passed into doCommandBySelector while
+// interpreting the key event. The selectors are converted into edit commands
+// which can be passed to the render process.
+//
+// Caveats:
+// - Shortcuts involving a sequence of key combinations (chords) don't work,
+// because we instantiate a new responder for each event.
+// - We ignore key combinations that don't include a modifier (ctrl, cmd, alt)
+// because this was causing strange behavior (e.g. tab always inserted a tab
+// rather than moving to the next field on the page).
+
+@interface EditCommandMatcher : NSResponder {
+ EditCommands* edit_commands_;
+}
+@end
+
+@implementation EditCommandMatcher
+
+- (id)initWithEditCommands:(EditCommands*)edit_commands {
+ if ((self = [super init]) != nil) {
+ edit_commands_ = edit_commands;
+ }
+ return self;
+}
+
+- (void)doCommandBySelector:(SEL)selector {
+ NSString* editCommand =
+ RWHVMEditCommandHelper::CommandNameForSelector(selector);
+ edit_commands_->push_back(
+ EditCommand(base::SysNSStringToUTF8(editCommand), ""));
+}
+
+- (void)insertText:(id)string {
+ // If we don't ignore this, then sometimes we get a bell.
+}
+
++ (void)matchEditCommands:(EditCommands*)edit_commands
+ forEvent:(NSEvent*)theEvent {
+ if ([theEvent type] != NSKeyDown) return;
+ // Don't interpret plain key presses. This screws up things like <Tab>.
+ NSUInteger flags = [theEvent modifierFlags];
+ flags &= (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask);
+ if (flags == 0) return;
+ scoped_nsobject<EditCommandMatcher> matcher(
+ [[EditCommandMatcher alloc] initWithEditCommands:edit_commands]);
+ [matcher.get() interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+}
+
+@end
+
// RenderWidgetHostViewCocoa ---------------------------------------------------
@implementation RenderWidgetHostViewCocoa
@@ -465,7 +521,7 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
closeOnDeactivate_ = b;
}
-- (void)mouseEvent:(NSEvent *)theEvent {
+- (void)mouseEvent:(NSEvent*)theEvent {
// Don't cancel child popups; killing them on a mouse click would prevent the
// user from positioning the insertion point in the text field spawning the
// popup. A click outside the text field would cause the text field to drop
@@ -478,7 +534,7 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event);
}
-- (void)keyEvent:(NSEvent *)theEvent {
+- (void)keyEvent:(NSEvent*)theEvent {
// TODO(avi): Possibly kill self? See RenderWidgetHostViewWin::OnKeyEvent and
// http://b/issue?id=1192881 .
@@ -499,8 +555,15 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
event.windowsKeyCode = 0xE5;
// Dispatch this keyboard event to the renderer.
- if (renderWidgetHostView_->render_widget_host_)
- renderWidgetHostView_->render_widget_host_->ForwardKeyboardEvent(event);
+ if (renderWidgetHostView_->render_widget_host_) {
+ RenderWidgetHost* widgetHost = renderWidgetHostView_->render_widget_host_;
+ // Look up shortcut, if any, for this key combination.
+ EditCommands editCommands;
+ [EditCommandMatcher matchEditCommands:&editCommands forEvent:theEvent];
+ if (!editCommands.empty())
+ widgetHost->ForwardEditCommandsForNextKeyEvent(editCommands);
+ widgetHost->ForwardKeyboardEvent(event);
+ }
// Dispatch a NSKeyDown event to an input method.
// To send an onkeydown() event before an onkeypress() event, we should