Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Unified Diff: ui/views/cocoa/bridged_content_view.mm

Issue 2624093002: MacViews: Correctly handle character events when there's an active TextInputClient. (Closed)
Patch Set: Flip isKeyDownEventHandled_ -> hasUnhandledKeyDownEvent_ Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/cocoa/bridged_content_view.h ('k') | ui/views/controls/combobox/combobox_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/cocoa/bridged_content_view.mm
diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views/cocoa/bridged_content_view.mm
index 15ac3500bc7c36ed0e51d48931e75860ac9ef2ce..3afe6232465400c3d21d79f9f63eafc864ac65d9 100644
--- a/ui/views/cocoa/bridged_content_view.mm
+++ b/ui/views/cocoa/bridged_content_view.mm
@@ -200,19 +200,6 @@ bool IsTextRTL(const ui::TextInputClient* client) {
return substring;
}
-// Returns a character event corresponding to |event|. |event| must be a
-// character event itself.
-ui::KeyEvent GetCharacterEventFromNSEvent(NSEvent* event) {
- DCHECK([event type] == NSKeyDown || [event type] == NSKeyUp);
- DCHECK_EQ(1u, [[event characters] length]);
-
- // [NSEvent characters] already considers the pressed key modifiers. Hence
- // send ui::EF_NONE as the key modifier to the KeyEvent constructor.
- // E.g. For Alt+S, [NSEvent characters] is 'ß' and not 'S'.
- return ui::KeyEvent([[event characters] characterAtIndex:0],
- ui::KeyboardCodeFromNSEvent(event), ui::EF_NONE);
-}
-
NSAttributedString* GetAttributedString(
const gfx::DecoratedText& decorated_text) {
base::scoped_nsobject<NSMutableAttributedString> str(
@@ -462,12 +449,12 @@ - (void)handleKeyEvent:(ui::KeyEvent*)event {
}
- (BOOL)handleUnhandledKeyDownAsKeyEvent {
- if (!keyDownEvent_)
+ if (!hasUnhandledKeyDownEvent_)
return NO;
ui::KeyEvent event(keyDownEvent_);
[self handleKeyEvent:&event];
- keyDownEvent_ = nil;
+ hasUnhandledKeyDownEvent_ = NO;
return event.handled();
}
@@ -506,6 +493,42 @@ - (void)insertTextInternal:(id)text {
text = [text string];
bool isCharacterEvent = keyDownEvent_ && [text length] == 1;
+ // Pass the character event to the View hierarchy. Cases this handles (non-
+ // exhaustive)-
+ // - Space key press on controls. Unlike Tab and newline which have
+ // corresponding action messages, an insertText: message is generated for
+ // the Space key (insertText:replacementRange: when there's an active
+ // input context).
+ // - Menu mnemonic selection.
+ // Note we create a custom character ui::KeyEvent (and not use the
+ // ui::KeyEvent(NSEvent*) constructor) since we can't just rely on the event
+ // key code to get the actual characters from the ui::KeyEvent. This for
+ // example is necessary for menu mnemonic selection of non-latin text.
+
+ // Don't generate a key event when there is active composition text. These key
+ // down events should be consumed by the IME and not reach the Views layer.
+ // For example, on pressing Return to commit composition text, if we passed a
+ // synthetic key event to the View hierarchy, it will have the effect of
+ // performing the default action on the current dialog. We do not want this.
+
+ // Also note that a single key down event can cause multiple
+ // insertText:replacementRange: action messages. Example, on pressing Alt+e,
+ // the accent (´) character is composed via setMarkedText:. Now on pressing
+ // the character 'r', two insertText:replacementRange: action messages are
+ // generated with the text value of accent (´) and 'r' respectively. The key
+ // down event will have characters field of length 2. The first of these
+ // insertText messages won't generate a KeyEvent since there'll be active
+ // marked text. However, a KeyEvent will be generated corresponding to 'r'.
+
+ // Currently there seems to be no use case to pass non-character events routed
+ // from insertText: handlers to the View hierarchy.
+ if (isCharacterEvent && ![self hasMarkedText]) {
+ ui::KeyEvent charEvent([text characterAtIndex:0],
+ ui::KeyboardCodeFromNSEvent(keyDownEvent_),
+ ui::EF_NONE);
+ [self handleKeyEvent:&charEvent];
+ hasUnhandledKeyDownEvent_ = NO;
+ }
// Forward the |text| to |textInputClient_| if no menu is active.
if (textInputClient_ && ![self activeMenuController]) {
@@ -518,34 +541,17 @@ - (void)insertTextInternal:(id)text {
// modifiers.
// Also, note we don't use |keyDownEvent_| to generate the synthetic
- // ui::KeyEvent since for text inserted using an IME, [keyDownEvent_
- // characters] might not be the same as |text|. This is because
- // |keyDownEvent_| will correspond to the event that caused the composition
- // text to be confirmed, say, Return key press.
+ // ui::KeyEvent since for composed text, [keyDownEvent_ characters] might
+ // not be the same as |text|. This is because |keyDownEvent_| will
+ // correspond to the event that caused the composition text to be confirmed,
+ // say, Return key press.
if (isCharacterEvent) {
textInputClient_->InsertChar(ui::KeyEvent([text characterAtIndex:0],
ui::VKEY_UNKNOWN, ui::EF_NONE));
} else {
textInputClient_->InsertText(base::SysNSStringToUTF16(text));
}
-
- keyDownEvent_ = nil; // Handled.
- return;
- }
-
- // Only handle the case where no. of characters is 1. Cases not handled (not
- // an exhaustive list):
- // - |text| contains a unicode surrogate pair, i.e. a single grapheme which
- // requires two 16 bit characters. Currently Views menu only supports
- // mnemonics using a single 16 bit character, so it is ok to ignore this
- // case.
- // - Programmatically created events.
- // - Input from IME. But this case should not occur since inputContext is
- // nil.
- if (isCharacterEvent) {
- ui::KeyEvent charEvent = GetCharacterEventFromNSEvent(keyDownEvent_);
- [self handleKeyEvent:&charEvent];
- keyDownEvent_ = nil; // Handled.
+ hasUnhandledKeyDownEvent_ = NO;
}
}
@@ -804,12 +810,14 @@ - (BOOL)_wantsKeyDownForEvent:(NSEvent*)event {
- (void)keyDown:(NSEvent*)theEvent {
// Convert the event into an action message, according to OSX key mappings.
keyDownEvent_ = theEvent;
+ hasUnhandledKeyDownEvent_ = YES;
[self interpretKeyEvents:@[ theEvent ]];
// If |keyDownEvent_| wasn't cleared during -interpretKeyEvents:, it wasn't
// handled. Give Widget accelerators a chance to handle it.
[self handleUnhandledKeyDownAsKeyEvent];
- DCHECK(!keyDownEvent_);
+ DCHECK(!hasUnhandledKeyDownEvent_);
+ keyDownEvent_ = nil;
}
- (void)keyUp:(NSEvent*)theEvent {
@@ -1333,7 +1341,7 @@ - (void)doCommandBySelector:(SEL)selector {
if ([self respondsToSelector:selector]) {
[self performSelector:selector withObject:nil];
- keyDownEvent_ = nil;
+ hasUnhandledKeyDownEvent_ = NO;
return;
}
@@ -1412,7 +1420,7 @@ - (void)setMarkedText:(id)text
composition.underlines.push_back(ui::CompositionUnderline(
0, [text length], SK_ColorBLACK, false, SK_ColorTRANSPARENT));
textInputClient_->SetCompositionText(composition);
- keyDownEvent_ = nil; // Handled.
+ hasUnhandledKeyDownEvent_ = NO;
}
- (void)unmarkText {
@@ -1420,7 +1428,7 @@ - (void)unmarkText {
return;
textInputClient_->ConfirmCompositionText();
- keyDownEvent_ = nil; // Handled.
+ hasUnhandledKeyDownEvent_ = NO;
}
- (NSArray*)validAttributesForMarkedText {
« no previous file with comments | « ui/views/cocoa/bridged_content_view.h ('k') | ui/views/controls/combobox/combobox_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698