OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ui/views/cocoa/bridged_content_view.h" | 5 #import "ui/views/cocoa/bridged_content_view.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #import "base/mac/mac_util.h" | 8 #import "base/mac/mac_util.h" |
9 #import "base/mac/scoped_nsobject.h" | 9 #import "base/mac/scoped_nsobject.h" |
10 #import "base/mac/sdk_forward_declarations.h" | 10 #import "base/mac/sdk_forward_declarations.h" |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 | 268 |
269 @interface BridgedContentView () | 269 @interface BridgedContentView () |
270 | 270 |
271 // Returns the active menu controller corresponding to |hostedView_|, | 271 // Returns the active menu controller corresponding to |hostedView_|, |
272 // nil otherwise. | 272 // nil otherwise. |
273 - (MenuController*)activeMenuController; | 273 - (MenuController*)activeMenuController; |
274 | 274 |
275 // Passes |event| to the InputMethod for dispatch. | 275 // Passes |event| to the InputMethod for dispatch. |
276 - (void)handleKeyEvent:(ui::KeyEvent*)event; | 276 - (void)handleKeyEvent:(ui::KeyEvent*)event; |
277 | 277 |
278 // Allows accelerators to be handled at different points in AppKit key event | |
279 // dispatch. Checks for an unhandled event passed in to -keyDown: and passes it | |
280 // to the Widget for processing. Returns YES if the Widget handles it. | |
281 - (BOOL)handleUnhandledKeyDownAsKeyEvent; | |
282 | |
278 // Handles an NSResponder Action Message by mapping it to a corresponding text | 283 // Handles an NSResponder Action Message by mapping it to a corresponding text |
279 // editing command from ui_strings.grd and, when not being sent to a | 284 // editing command from ui_strings.grd and, when not being sent to a |
280 // TextInputClient, the keyCode that toolkit-views expects internally. | 285 // TextInputClient, the keyCode that toolkit-views expects internally. |
281 // For example, moveToLeftEndOfLine: would pass ui::VKEY_HOME in non-RTL locales | 286 // For example, moveToLeftEndOfLine: would pass ui::VKEY_HOME in non-RTL locales |
282 // even though the Home key on Mac defaults to moveToBeginningOfDocument:. | 287 // even though the Home key on Mac defaults to moveToBeginningOfDocument:. |
283 // This approach also allows action messages a user | 288 // This approach also allows action messages a user |
284 // may have remapped in ~/Library/KeyBindings/DefaultKeyBinding.dict to be | 289 // may have remapped in ~/Library/KeyBindings/DefaultKeyBinding.dict to be |
285 // catered for. | 290 // catered for. |
286 // Note: default key bindings in Mac can be read from StandardKeyBinding.dict | 291 // Note: default key bindings in Mac can be read from StandardKeyBinding.dict |
287 // which lives in /System/Library/Frameworks/AppKit.framework/Resources. Do | 292 // which lives in /System/Library/Frameworks/AppKit.framework/Resources. Do |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 if (!hostedView_) | 453 if (!hostedView_) |
449 return; | 454 return; |
450 | 455 |
451 DCHECK(event); | 456 DCHECK(event); |
452 if (DispatchEventToMenu([self activeMenuController], event)) | 457 if (DispatchEventToMenu([self activeMenuController], event)) |
453 return; | 458 return; |
454 | 459 |
455 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event); | 460 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event); |
456 } | 461 } |
457 | 462 |
463 - (BOOL)handleUnhandledKeyDownAsKeyEvent { | |
464 if (!keyDownEvent_) | |
465 return NO; | |
466 | |
467 ui::KeyEvent event(keyDownEvent_); | |
468 [self handleKeyEvent:&event]; | |
469 keyDownEvent_ = nil; | |
470 return event.handled(); | |
471 } | |
472 | |
458 - (void)handleAction:(ui::TextEditCommand)command | 473 - (void)handleAction:(ui::TextEditCommand)command |
459 keyCode:(ui::KeyboardCode)keyCode | 474 keyCode:(ui::KeyboardCode)keyCode |
460 domCode:(ui::DomCode)domCode | 475 domCode:(ui::DomCode)domCode |
461 eventFlags:(int)eventFlags { | 476 eventFlags:(int)eventFlags { |
462 if (!hostedView_) | 477 if (!hostedView_) |
463 return; | 478 return; |
464 | 479 |
465 // Generate a synthetic event with the keycode toolkit-views expects. | 480 // Generate a synthetic event with the keycode toolkit-views expects. |
466 ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags); | 481 ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags); |
467 | 482 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 // ui::KeyEvent since for text inserted using an IME, [keyDownEvent_ | 520 // ui::KeyEvent since for text inserted using an IME, [keyDownEvent_ |
506 // characters] might not be the same as |text|. This is because | 521 // characters] might not be the same as |text|. This is because |
507 // |keyDownEvent_| will correspond to the event that caused the composition | 522 // |keyDownEvent_| will correspond to the event that caused the composition |
508 // text to be confirmed, say, Return key press. | 523 // text to be confirmed, say, Return key press. |
509 if (isCharacterEvent) { | 524 if (isCharacterEvent) { |
510 textInputClient_->InsertChar(ui::KeyEvent([text characterAtIndex:0], | 525 textInputClient_->InsertChar(ui::KeyEvent([text characterAtIndex:0], |
511 ui::VKEY_UNKNOWN, ui::EF_NONE)); | 526 ui::VKEY_UNKNOWN, ui::EF_NONE)); |
512 } else { | 527 } else { |
513 textInputClient_->InsertText(base::SysNSStringToUTF16(text)); | 528 textInputClient_->InsertText(base::SysNSStringToUTF16(text)); |
514 } | 529 } |
530 | |
531 // If -insertTextInternal: was invoked from -keyDown:, we don't want | |
532 // to do -handleUnhandledKeyDownAsKeyEvent. | |
533 keyDownEvent_ = nil; | |
themblsha
2016/11/22 14:33:48
Fixex TextfieldTest.TextInputType_InsertionTest (a
tapted
2016/11/23 02:09:30
Acknowledged. The comment could be more terse, too
themblsha
2016/11/23 15:16:39
Done.
| |
515 return; | 534 return; |
516 } | 535 } |
517 | 536 |
518 // Only handle the case where no. of characters is 1. Cases not handled (not | 537 // Only handle the case where no. of characters is 1. Cases not handled (not |
519 // an exhaustive list): | 538 // an exhaustive list): |
520 // - |text| contains a unicode surrogate pair, i.e. a single grapheme which | 539 // - |text| contains a unicode surrogate pair, i.e. a single grapheme which |
521 // requires two 16 bit characters. Currently Views menu only supports | 540 // requires two 16 bit characters. Currently Views menu only supports |
522 // mnemonics using a single 16 bit character, so it is ok to ignore this | 541 // mnemonics using a single 16 bit character, so it is ok to ignore this |
523 // case. | 542 // case. |
524 // - Programmatically created events. | 543 // - Programmatically created events. |
525 // - Input from IME. But this case should not occur since inputContext is | 544 // - Input from IME. But this case should not occur since inputContext is |
526 // nil. | 545 // nil. |
527 if (isCharacterEvent) { | 546 if (isCharacterEvent) { |
528 ui::KeyEvent charEvent = GetCharacterEventFromNSEvent(keyDownEvent_); | 547 ui::KeyEvent charEvent = GetCharacterEventFromNSEvent(keyDownEvent_); |
529 [self handleKeyEvent:&charEvent]; | 548 [self handleKeyEvent:&charEvent]; |
549 // Currently it doesn't seem that this code path could be reached from | |
550 // -keyDown:. If it does, it needs an additional test case, and to clear the | |
551 // keyDownEvent_ to avoid duplicate text processing. | |
552 DCHECK(!keyDownEvent_); | |
themblsha
2016/11/22 14:33:48
This didn't cause any problems with the tests I've
tapted
2016/11/23 02:09:30
It's easy to hit this DCHECK - just focus somethin
themblsha
2016/11/23 15:16:39
Ah. Duplicated "keyDownEvent_ = nil; // Handled."
| |
530 } | 553 } |
531 } | 554 } |
532 | 555 |
533 - (views::DragDropClientMac*)dragDropClient { | 556 - (views::DragDropClientMac*)dragDropClient { |
534 views::BridgedNativeWidget* bridge = | 557 views::BridgedNativeWidget* bridge = |
535 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]); | 558 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]); |
536 return bridge ? bridge->drag_drop_client() : nullptr; | 559 return bridge ? bridge->drag_drop_client() : nullptr; |
537 } | 560 } |
538 | 561 |
539 - (void)undo:(id)sender { | 562 - (void)undo:(id)sender { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
758 case ui::TEXT_INPUT_TYPE_NONE: | 781 case ui::TEXT_INPUT_TYPE_NONE: |
759 case ui::TEXT_INPUT_TYPE_PASSWORD: | 782 case ui::TEXT_INPUT_TYPE_PASSWORD: |
760 return nil; | 783 return nil; |
761 default: | 784 default: |
762 return [super inputContext]; | 785 return [super inputContext]; |
763 } | 786 } |
764 } | 787 } |
765 | 788 |
766 // NSResponder implementation. | 789 // NSResponder implementation. |
767 | 790 |
791 - (BOOL)_wantsKeyDownForEvent:(NSEvent*)event { | |
792 // This is a SPI that AppKit apparently calls after |performKeyEquivalent:| | |
793 // returned NO. If this function returns |YES|, Cocoa sends the event to | |
794 // |keyDown:| instead of doing other things with it. Ctrl-tab will be sent | |
795 // to us instead of doing key view loop control, ctrl-left/right get handled | |
796 // correctly, etc. | |
797 // (However, there are still some keys that Cocoa swallows, e.g. the key | |
798 // equivalent that Cocoa uses for toggling the input language. In this case, | |
799 // that's actually a good thing, though -- see http://crbug.com/26115 .) | |
800 return YES; | |
801 } | |
802 | |
768 - (void)keyDown:(NSEvent*)theEvent { | 803 - (void)keyDown:(NSEvent*)theEvent { |
769 // Convert the event into an action message, according to OSX key mappings. | 804 // Convert the event into an action message, according to OSX key mappings. |
770 keyDownEvent_ = theEvent; | 805 keyDownEvent_ = theEvent; |
771 [self interpretKeyEvents:@[ theEvent ]]; | 806 [self interpretKeyEvents:@[ theEvent ]]; |
772 keyDownEvent_ = nil; | 807 |
808 // If |keyDownEvent_| wasn't cleared during -interpretKeyEvents:, it wasn't | |
809 // handled. Give Widget accelerators a chance to handle it. | |
810 [self handleUnhandledKeyDownAsKeyEvent]; | |
811 DCHECK(!keyDownEvent_); | |
773 } | 812 } |
774 | 813 |
775 - (void)keyUp:(NSEvent*)theEvent { | 814 - (void)keyUp:(NSEvent*)theEvent { |
776 ui::KeyEvent event(theEvent); | 815 ui::KeyEvent event(theEvent); |
777 [self handleKeyEvent:&event]; | 816 [self handleKeyEvent:&event]; |
778 } | 817 } |
779 | 818 |
780 - (void)scrollWheel:(NSEvent*)theEvent { | 819 - (void)scrollWheel:(NSEvent*)theEvent { |
781 if (!hostedView_) | 820 if (!hostedView_) |
782 return; | 821 return; |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1281 } | 1320 } |
1282 | 1321 |
1283 - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { | 1322 - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { |
1284 NOTIMPLEMENTED(); | 1323 NOTIMPLEMENTED(); |
1285 return 0; | 1324 return 0; |
1286 } | 1325 } |
1287 | 1326 |
1288 - (void)doCommandBySelector:(SEL)selector { | 1327 - (void)doCommandBySelector:(SEL)selector { |
1289 // Like the renderer, handle insert action messages as a regular key dispatch. | 1328 // Like the renderer, handle insert action messages as a regular key dispatch. |
1290 // This ensures, e.g., insertTab correctly changes focus between fields. | 1329 // This ensures, e.g., insertTab correctly changes focus between fields. |
1291 if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"]) { | 1330 if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"]) |
1292 ui::KeyEvent event(keyDownEvent_); | 1331 return; // Handle in -keyDown:. |
1293 [self handleKeyEvent:&event]; | 1332 |
1333 if ([self respondsToSelector:selector]) { | |
1334 [self performSelector:selector withObject:nil]; | |
1335 keyDownEvent_ = nil; | |
1294 return; | 1336 return; |
1295 } | 1337 } |
1296 | 1338 |
1297 if ([self respondsToSelector:selector]) | 1339 // For events that AppKit sends via doCommandBySelector:, first attempt to |
1298 [self performSelector:selector withObject:nil]; | 1340 // handle as a Widget accelerator. Forward along the responder chain only if |
1299 else | 1341 // the Widget doesn't handle it. |
1342 if (![self handleUnhandledKeyDownAsKeyEvent]) | |
1300 [[self nextResponder] doCommandBySelector:selector]; | 1343 [[self nextResponder] doCommandBySelector:selector]; |
1301 } | 1344 } |
1302 | 1345 |
1303 - (NSRect)firstRectForCharacterRange:(NSRange)range | 1346 - (NSRect)firstRectForCharacterRange:(NSRange)range |
1304 actualRange:(NSRangePointer)actualNSRange { | 1347 actualRange:(NSRangePointer)actualNSRange { |
1305 gfx::Range actualRange; | 1348 gfx::Range actualRange; |
1306 gfx::Rect rect = GetFirstRectForRangeHelper(textInputClient_, | 1349 gfx::Rect rect = GetFirstRectForRangeHelper(textInputClient_, |
1307 gfx::Range(range), &actualRange); | 1350 gfx::Range(range), &actualRange); |
1308 if (actualNSRange) | 1351 if (actualNSRange) |
1309 *actualNSRange = actualRange.ToNSRange(); | 1352 *actualNSRange = actualRange.ToNSRange(); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1432 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; | 1475 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; |
1433 } | 1476 } |
1434 | 1477 |
1435 - (id)accessibilityFocusedUIElement { | 1478 - (id)accessibilityFocusedUIElement { |
1436 if (!hostedView_) | 1479 if (!hostedView_) |
1437 return nil; | 1480 return nil; |
1438 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; | 1481 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; |
1439 } | 1482 } |
1440 | 1483 |
1441 @end | 1484 @end |
OLD | NEW |