diff options
-rw-r--r-- | chrome/browser/cocoa/rwhvm_editcommand_helper.h | 4 | ||||
-rw-r--r-- | chrome/browser/cocoa/rwhvm_editcommand_helper.mm | 62 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 71 |
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 |