| 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 keyDownEvent_ = nil; // Handled. |
| 515 return; | 532 return; |
| 516 } | 533 } |
| 517 | 534 |
| 518 // Only handle the case where no. of characters is 1. Cases not handled (not | 535 // Only handle the case where no. of characters is 1. Cases not handled (not |
| 519 // an exhaustive list): | 536 // an exhaustive list): |
| 520 // - |text| contains a unicode surrogate pair, i.e. a single grapheme which | 537 // - |text| contains a unicode surrogate pair, i.e. a single grapheme which |
| 521 // requires two 16 bit characters. Currently Views menu only supports | 538 // 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 | 539 // mnemonics using a single 16 bit character, so it is ok to ignore this |
| 523 // case. | 540 // case. |
| 524 // - Programmatically created events. | 541 // - Programmatically created events. |
| 525 // - Input from IME. But this case should not occur since inputContext is | 542 // - Input from IME. But this case should not occur since inputContext is |
| 526 // nil. | 543 // nil. |
| 527 if (isCharacterEvent) { | 544 if (isCharacterEvent) { |
| 528 ui::KeyEvent charEvent = GetCharacterEventFromNSEvent(keyDownEvent_); | 545 ui::KeyEvent charEvent = GetCharacterEventFromNSEvent(keyDownEvent_); |
| 529 [self handleKeyEvent:&charEvent]; | 546 [self handleKeyEvent:&charEvent]; |
| 547 keyDownEvent_ = nil; // Handled. |
| 530 } | 548 } |
| 531 } | 549 } |
| 532 | 550 |
| 533 - (views::DragDropClientMac*)dragDropClient { | 551 - (views::DragDropClientMac*)dragDropClient { |
| 534 views::BridgedNativeWidget* bridge = | 552 views::BridgedNativeWidget* bridge = |
| 535 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]); | 553 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]); |
| 536 return bridge ? bridge->drag_drop_client() : nullptr; | 554 return bridge ? bridge->drag_drop_client() : nullptr; |
| 537 } | 555 } |
| 538 | 556 |
| 539 - (void)undo:(id)sender { | 557 - (void)undo:(id)sender { |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 case ui::TEXT_INPUT_TYPE_NONE: | 776 case ui::TEXT_INPUT_TYPE_NONE: |
| 759 case ui::TEXT_INPUT_TYPE_PASSWORD: | 777 case ui::TEXT_INPUT_TYPE_PASSWORD: |
| 760 return nil; | 778 return nil; |
| 761 default: | 779 default: |
| 762 return [super inputContext]; | 780 return [super inputContext]; |
| 763 } | 781 } |
| 764 } | 782 } |
| 765 | 783 |
| 766 // NSResponder implementation. | 784 // NSResponder implementation. |
| 767 | 785 |
| 786 - (BOOL)_wantsKeyDownForEvent:(NSEvent*)event { |
| 787 // This is a SPI that AppKit apparently calls after |performKeyEquivalent:| |
| 788 // returned NO. If this function returns |YES|, Cocoa sends the event to |
| 789 // |keyDown:| instead of doing other things with it. Ctrl-tab will be sent |
| 790 // to us instead of doing key view loop control, ctrl-left/right get handled |
| 791 // correctly, etc. |
| 792 // (However, there are still some keys that Cocoa swallows, e.g. the key |
| 793 // equivalent that Cocoa uses for toggling the input language. In this case, |
| 794 // that's actually a good thing, though -- see http://crbug.com/26115 .) |
| 795 return YES; |
| 796 } |
| 797 |
| 768 - (void)keyDown:(NSEvent*)theEvent { | 798 - (void)keyDown:(NSEvent*)theEvent { |
| 769 // Convert the event into an action message, according to OSX key mappings. | 799 // Convert the event into an action message, according to OSX key mappings. |
| 770 keyDownEvent_ = theEvent; | 800 keyDownEvent_ = theEvent; |
| 771 [self interpretKeyEvents:@[ theEvent ]]; | 801 [self interpretKeyEvents:@[ theEvent ]]; |
| 772 keyDownEvent_ = nil; | 802 |
| 803 // If |keyDownEvent_| wasn't cleared during -interpretKeyEvents:, it wasn't |
| 804 // handled. Give Widget accelerators a chance to handle it. |
| 805 [self handleUnhandledKeyDownAsKeyEvent]; |
| 806 DCHECK(!keyDownEvent_); |
| 773 } | 807 } |
| 774 | 808 |
| 775 - (void)keyUp:(NSEvent*)theEvent { | 809 - (void)keyUp:(NSEvent*)theEvent { |
| 776 ui::KeyEvent event(theEvent); | 810 ui::KeyEvent event(theEvent); |
| 777 [self handleKeyEvent:&event]; | 811 [self handleKeyEvent:&event]; |
| 778 } | 812 } |
| 779 | 813 |
| 780 - (void)scrollWheel:(NSEvent*)theEvent { | 814 - (void)scrollWheel:(NSEvent*)theEvent { |
| 781 if (!hostedView_) | 815 if (!hostedView_) |
| 782 return; | 816 return; |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 } | 1315 } |
| 1282 | 1316 |
| 1283 - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { | 1317 - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { |
| 1284 NOTIMPLEMENTED(); | 1318 NOTIMPLEMENTED(); |
| 1285 return 0; | 1319 return 0; |
| 1286 } | 1320 } |
| 1287 | 1321 |
| 1288 - (void)doCommandBySelector:(SEL)selector { | 1322 - (void)doCommandBySelector:(SEL)selector { |
| 1289 // Like the renderer, handle insert action messages as a regular key dispatch. | 1323 // Like the renderer, handle insert action messages as a regular key dispatch. |
| 1290 // This ensures, e.g., insertTab correctly changes focus between fields. | 1324 // This ensures, e.g., insertTab correctly changes focus between fields. |
| 1291 if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"]) { | 1325 if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"]) |
| 1292 ui::KeyEvent event(keyDownEvent_); | 1326 return; // Handle in -keyDown:. |
| 1293 [self handleKeyEvent:&event]; | 1327 |
| 1328 if ([self respondsToSelector:selector]) { |
| 1329 [self performSelector:selector withObject:nil]; |
| 1330 keyDownEvent_ = nil; |
| 1294 return; | 1331 return; |
| 1295 } | 1332 } |
| 1296 | 1333 |
| 1297 if ([self respondsToSelector:selector]) | 1334 // For events that AppKit sends via doCommandBySelector:, first attempt to |
| 1298 [self performSelector:selector withObject:nil]; | 1335 // handle as a Widget accelerator. Forward along the responder chain only if |
| 1299 else | 1336 // the Widget doesn't handle it. |
| 1337 if (![self handleUnhandledKeyDownAsKeyEvent]) |
| 1300 [[self nextResponder] doCommandBySelector:selector]; | 1338 [[self nextResponder] doCommandBySelector:selector]; |
| 1301 } | 1339 } |
| 1302 | 1340 |
| 1303 - (NSRect)firstRectForCharacterRange:(NSRange)range | 1341 - (NSRect)firstRectForCharacterRange:(NSRange)range |
| 1304 actualRange:(NSRangePointer)actualNSRange { | 1342 actualRange:(NSRangePointer)actualNSRange { |
| 1305 gfx::Range actualRange; | 1343 gfx::Range actualRange; |
| 1306 gfx::Rect rect = GetFirstRectForRangeHelper(textInputClient_, | 1344 gfx::Rect rect = GetFirstRectForRangeHelper(textInputClient_, |
| 1307 gfx::Range(range), &actualRange); | 1345 gfx::Range(range), &actualRange); |
| 1308 if (actualNSRange) | 1346 if (actualNSRange) |
| 1309 *actualNSRange = actualRange.ToNSRange(); | 1347 *actualNSRange = actualRange.ToNSRange(); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; | 1470 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; |
| 1433 } | 1471 } |
| 1434 | 1472 |
| 1435 - (id)accessibilityFocusedUIElement { | 1473 - (id)accessibilityFocusedUIElement { |
| 1436 if (!hostedView_) | 1474 if (!hostedView_) |
| 1437 return nil; | 1475 return nil; |
| 1438 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; | 1476 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; |
| 1439 } | 1477 } |
| 1440 | 1478 |
| 1441 @end | 1479 @end |
| OLD | NEW |