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

Side by Side Diff: ui/views/cocoa/bridged_content_view.mm

Issue 2007503002: Views: Replace resource ids with ui::TextEditCommand enum for text editing commands in Textfield. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added file deleted during rename. Created 4 years, 6 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 unified diff | Download patch
OLDNEW
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 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
11 #include "skia/ext/skia_utils_mac.h" 11 #include "skia/ext/skia_utils_mac.h"
12 #include "ui/base/cocoa/cocoa_base_utils.h" 12 #include "ui/base/cocoa/cocoa_base_utils.h"
13 #include "ui/base/ime/input_method.h" 13 #include "ui/base/ime/input_method.h"
14 #include "ui/base/ime/text_input_client.h" 14 #include "ui/base/ime/text_input_client.h"
15 #include "ui/compositor/canvas_painter.h" 15 #include "ui/compositor/canvas_painter.h"
16 #import "ui/events/cocoa/cocoa_event_utils.h" 16 #import "ui/events/cocoa/cocoa_event_utils.h"
17 #include "ui/events/keycodes/dom/dom_code.h" 17 #include "ui/events/keycodes/dom/dom_code.h"
18 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" 18 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
19 #include "ui/gfx/canvas_paint_mac.h" 19 #include "ui/gfx/canvas_paint_mac.h"
20 #include "ui/gfx/geometry/rect.h" 20 #include "ui/gfx/geometry/rect.h"
21 #import "ui/gfx/mac/coordinate_conversion.h" 21 #import "ui/gfx/mac/coordinate_conversion.h"
22 #include "ui/gfx/path.h" 22 #include "ui/gfx/path.h"
23 #import "ui/gfx/path_mac.h" 23 #import "ui/gfx/path_mac.h"
24 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 24 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
25 #include "ui/strings/grit/ui_strings.h"
26 #include "ui/views/controls/menu/menu_config.h" 25 #include "ui/views/controls/menu/menu_config.h"
27 #include "ui/views/controls/menu/menu_controller.h" 26 #include "ui/views/controls/menu/menu_controller.h"
28 #include "ui/views/view.h" 27 #include "ui/views/view.h"
29 #include "ui/views/widget/widget.h" 28 #include "ui/views/widget/widget.h"
30 29
31 using views::MenuController; 30 using views::MenuController;
32 31
33 namespace { 32 namespace {
34 33
35 NSString* const kFullKeyboardAccessChangedNotification = 34 NSString* const kFullKeyboardAccessChangedNotification =
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 197 }
199 198
200 } // namespace 199 } // namespace
201 200
202 @interface BridgedContentView () 201 @interface BridgedContentView ()
203 202
204 // Translates keycodes and modifiers on |theEvent| to ui::KeyEvents and passes 203 // Translates keycodes and modifiers on |theEvent| to ui::KeyEvents and passes
205 // the event to the InputMethod for dispatch. 204 // the event to the InputMethod for dispatch.
206 - (void)handleKeyEvent:(NSEvent*)theEvent; 205 - (void)handleKeyEvent:(NSEvent*)theEvent;
207 206
208 // Handles an NSResponder Action Message by mapping it to a corresponding text 207 // Handles an NSResponder Action Message by mapping it to a corresponding
209 // editing command from ui_strings.grd and, when not being sent to a 208 // ui::TextEditCommand and, when not being sent to a TextInputClient, the
210 // TextInputClient, the keyCode that toolkit-views expects internally. 209 // keyCode that toolkit-views expects internally.
211 // For example, moveToLeftEndOfLine: would pass ui::VKEY_HOME in non-RTL locales 210 // For example, moveToLeftEndOfLine: would pass ui::VKEY_HOME in non-RTL locales
212 // even though the Home key on Mac defaults to moveToBeginningOfDocument:. 211 // even though the Home key on Mac defaults to moveToBeginningOfDocument:.
213 // This approach also allows action messages a user 212 // This approach also allows action messages a user
214 // may have remapped in ~/Library/KeyBindings/DefaultKeyBinding.dict to be 213 // may have remapped in ~/Library/KeyBindings/DefaultKeyBinding.dict to be
215 // catered for. 214 // catered for.
216 // Note: default key bindings in Mac can be read from StandardKeyBinding.dict 215 // Note: default key bindings in Mac can be read from StandardKeyBinding.dict
217 // which lives in /System/Library/Frameworks/AppKit.framework/Resources. Do 216 // which lives in /System/Library/Frameworks/AppKit.framework/Resources. Do
218 // `plutil -convert xml1 -o StandardKeyBinding.xml StandardKeyBinding.dict` to 217 // `plutil -convert xml1 -o StandardKeyBinding.xml StandardKeyBinding.dict` to
219 // get something readable. 218 // get something readable.
220 - (void)handleAction:(int)commandId 219 - (void)handleAction:(ui::TextEditCommand)command
221 keyCode:(ui::KeyboardCode)keyCode 220 keyCode:(ui::KeyboardCode)keyCode
222 domCode:(ui::DomCode)domCode 221 domCode:(ui::DomCode)domCode
223 eventFlags:(int)eventFlags; 222 eventFlags:(int)eventFlags;
224 223
225 // Notification handler invoked when the Full Keyboard Access mode is changed. 224 // Notification handler invoked when the Full Keyboard Access mode is changed.
226 - (void)onFullKeyboardAccessModeChanged:(NSNotification*)notification; 225 - (void)onFullKeyboardAccessModeChanged:(NSNotification*)notification;
227 226
228 // Menu action handlers. 227 // Menu action handlers.
229 - (void)undo:(id)sender; 228 - (void)undo:(id)sender;
230 - (void)redo:(id)sender; 229 - (void)redo:(id)sender;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 return; 361 return;
363 362
364 DCHECK(theEvent); 363 DCHECK(theEvent);
365 ui::KeyEvent event(theEvent); 364 ui::KeyEvent event(theEvent);
366 if (DispatchEventToMenu(hostedView_->GetWidget(), event.key_code())) 365 if (DispatchEventToMenu(hostedView_->GetWidget(), event.key_code()))
367 return; 366 return;
368 367
369 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(&event); 368 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(&event);
370 } 369 }
371 370
372 - (void)handleAction:(int)commandId 371 - (void)handleAction:(ui::TextEditCommand)command
373 keyCode:(ui::KeyboardCode)keyCode 372 keyCode:(ui::KeyboardCode)keyCode
374 domCode:(ui::DomCode)domCode 373 domCode:(ui::DomCode)domCode
375 eventFlags:(int)eventFlags { 374 eventFlags:(int)eventFlags {
376 if (!hostedView_) 375 if (!hostedView_)
377 return; 376 return;
378 377
379 if (DispatchEventToMenu(hostedView_->GetWidget(), keyCode)) 378 if (DispatchEventToMenu(hostedView_->GetWidget(), keyCode))
380 return; 379 return;
381 380
382 // If there's an active TextInputClient, schedule the editing command to be 381 // If there's an active TextInputClient, schedule the editing command to be
383 // performed. 382 // performed.
384 if (commandId && textInputClient_ && 383 if (textInputClient_ && textInputClient_->IsEditCommandEnabled(command))
385 textInputClient_->IsEditCommandEnabled(commandId)) 384 textInputClient_->SetEditCommandForNextKeyEvent(command);
386 textInputClient_->SetEditCommandForNextKeyEvent(commandId);
387 385
388 // Generate a synthetic event with the keycode toolkit-views expects. 386 // Generate a synthetic event with the keycode toolkit-views expects.
389 ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags); 387 ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags);
390 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(&event); 388 hostedView_->GetWidget()->GetInputMethod()->DispatchKeyEvent(&event);
391 } 389 }
392 390
393 - (void)onFullKeyboardAccessModeChanged:(NSNotification*)notification { 391 - (void)onFullKeyboardAccessModeChanged:(NSNotification*)notification {
394 DCHECK([[notification name] 392 DCHECK([[notification name]
395 isEqualToString:kFullKeyboardAccessChangedNotification]); 393 isEqualToString:kFullKeyboardAccessChangedNotification]);
396 [self updateFullKeyboardAccess]; 394 [self updateFullKeyboardAccess];
397 } 395 }
398 396
399 - (void)undo:(id)sender { 397 - (void)undo:(id)sender {
400 // This DCHECK is more strict than a similar check in handleAction:. It can be 398 // This DCHECK is more strict than a similar check in handleAction:. It can be
401 // done here because the actors sending these actions should be calling 399 // done here because the actors sending these actions should be calling
402 // validateUserInterfaceItem: before enabling UI that allows these messages to 400 // validateUserInterfaceItem: before enabling UI that allows these messages to
403 // be sent. Checking it here would be too late to provide correct UI feedback 401 // be sent. Checking it here would be too late to provide correct UI feedback
404 // (e.g. there will be no "beep"). 402 // (e.g. there will be no "beep").
405 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_UNDO)); 403 DCHECK(textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::UNDO));
406 [self handleAction:IDS_APP_UNDO 404 [self handleAction:ui::TextEditCommand::UNDO
407 keyCode:ui::VKEY_Z 405 keyCode:ui::VKEY_Z
408 domCode:ui::DomCode::US_Z 406 domCode:ui::DomCode::US_Z
409 eventFlags:ui::EF_CONTROL_DOWN]; 407 eventFlags:ui::EF_CONTROL_DOWN];
410 } 408 }
411 409
412 - (void)redo:(id)sender { 410 - (void)redo:(id)sender {
413 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_REDO)); 411 DCHECK(textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::REDO));
414 [self handleAction:IDS_APP_REDO 412 [self handleAction:ui::TextEditCommand::REDO
415 keyCode:ui::VKEY_Z 413 keyCode:ui::VKEY_Z
416 domCode:ui::DomCode::US_Z 414 domCode:ui::DomCode::US_Z
417 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 415 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
418 } 416 }
419 417
420 - (void)cut:(id)sender { 418 - (void)cut:(id)sender {
421 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_CUT)); 419 DCHECK(textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::CUT));
422 [self handleAction:IDS_APP_CUT 420 [self handleAction:ui::TextEditCommand::CUT
423 keyCode:ui::VKEY_X 421 keyCode:ui::VKEY_X
424 domCode:ui::DomCode::US_X 422 domCode:ui::DomCode::US_X
425 eventFlags:ui::EF_CONTROL_DOWN]; 423 eventFlags:ui::EF_CONTROL_DOWN];
426 } 424 }
427 425
428 - (void)copy:(id)sender { 426 - (void)copy:(id)sender {
429 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_COPY)); 427 DCHECK(textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::COPY));
430 [self handleAction:IDS_APP_COPY 428 [self handleAction:ui::TextEditCommand::COPY
431 keyCode:ui::VKEY_C 429 keyCode:ui::VKEY_C
432 domCode:ui::DomCode::US_C 430 domCode:ui::DomCode::US_C
433 eventFlags:ui::EF_CONTROL_DOWN]; 431 eventFlags:ui::EF_CONTROL_DOWN];
434 } 432 }
435 433
436 - (void)paste:(id)sender { 434 - (void)paste:(id)sender {
437 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_PASTE)); 435 DCHECK(textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::PASTE));
438 [self handleAction:IDS_APP_PASTE 436 [self handleAction:ui::TextEditCommand::PASTE
439 keyCode:ui::VKEY_V 437 keyCode:ui::VKEY_V
440 domCode:ui::DomCode::US_V 438 domCode:ui::DomCode::US_V
441 eventFlags:ui::EF_CONTROL_DOWN]; 439 eventFlags:ui::EF_CONTROL_DOWN];
442 } 440 }
443 441
444 - (void)selectAll:(id)sender { 442 - (void)selectAll:(id)sender {
445 DCHECK(textInputClient_->IsEditCommandEnabled(IDS_APP_SELECT_ALL)); 443 DCHECK(
446 [self handleAction:IDS_APP_SELECT_ALL 444 textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::SELECT_ALL));
445 [self handleAction:ui::TextEditCommand::SELECT_ALL
447 keyCode:ui::VKEY_A 446 keyCode:ui::VKEY_A
448 domCode:ui::DomCode::US_A 447 domCode:ui::DomCode::US_A
449 eventFlags:ui::EF_CONTROL_DOWN]; 448 eventFlags:ui::EF_CONTROL_DOWN];
450 } 449 }
451 450
452 // BaseView implementation. 451 // BaseView implementation.
453 452
454 // Don't use tracking areas from BaseView. BridgedContentView's tracks 453 // Don't use tracking areas from BaseView. BridgedContentView's tracks
455 // NSTrackingCursorUpdate and Apple's documentation suggests it's incompatible. 454 // NSTrackingCursorUpdate and Apple's documentation suggests it's incompatible.
456 - (void)enableTracking { 455 - (void)enableTracking {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 } 628 }
630 629
631 //////////////////////////////////////////////////////////////////////////////// 630 ////////////////////////////////////////////////////////////////////////////////
632 // NSResponder Action Messages. Keep sorted according NSResponder.h (from the 631 // NSResponder Action Messages. Keep sorted according NSResponder.h (from the
633 // 10.9 SDK). The list should eventually be complete. Anything not defined will 632 // 10.9 SDK). The list should eventually be complete. Anything not defined will
634 // beep when interpretKeyEvents: would otherwise call it. 633 // beep when interpretKeyEvents: would otherwise call it.
635 // TODO(tapted): Make this list complete, except for insert* methods which are 634 // TODO(tapted): Make this list complete, except for insert* methods which are
636 // dispatched as regular key events in doCommandBySelector:. 635 // dispatched as regular key events in doCommandBySelector:.
637 636
638 // views::Textfields are single-line only, map Paragraph and Document commands 637 // views::Textfields are single-line only, map Paragraph and Document commands
639 // to Line. Also, Up/Down commands correspond to beginning/end of line. 638 // to Line. Also, some up/down commands are mapped to beginning/end of line
639 // commands.
640 640
641 // The insertText action message forwards to the TextInputClient unless a menu 641 // The insertText action message forwards to the TextInputClient unless a menu
642 // is active. Note that NSResponder's interpretKeyEvents: implementation doesn't 642 // is active. Note that NSResponder's interpretKeyEvents: implementation doesn't
643 // direct insertText: through doCommandBySelector:, so this is still needed to 643 // direct insertText: through doCommandBySelector:, so this is still needed to
644 // handle the case when inputContext: is nil. When inputContext: returns non-nil 644 // handle the case when inputContext: is nil. When inputContext: returns non-nil
645 // text goes directly to insertText:replacementRange:. 645 // text goes directly to insertText:replacementRange:.
646 - (void)insertText:(id)text { 646 - (void)insertText:(id)text {
647 [self insertText:text replacementRange:NSMakeRange(NSNotFound, 0)]; 647 [self insertText:text replacementRange:NSMakeRange(NSNotFound, 0)];
648 } 648 }
649 649
650 // Selection movement and scrolling. 650 // Selection movement and scrolling.
651 651
652 - (void)moveForward:(id)sender { 652 - (void)moveForward:(id)sender {
653 IsTextRTL(textInputClient_) ? [self moveLeft:sender] 653 IsTextRTL(textInputClient_) ? [self moveLeft:sender]
654 : [self moveRight:sender]; 654 : [self moveRight:sender];
655 } 655 }
656 656
657 - (void)moveRight:(id)sender { 657 - (void)moveRight:(id)sender {
658 [self handleAction:IDS_MOVE_RIGHT 658 [self handleAction:ui::TextEditCommand::MOVE_RIGHT
659 keyCode:ui::VKEY_RIGHT 659 keyCode:ui::VKEY_RIGHT
660 domCode:ui::DomCode::ARROW_RIGHT 660 domCode:ui::DomCode::ARROW_RIGHT
661 eventFlags:0]; 661 eventFlags:0];
662 } 662 }
663 663
664 - (void)moveBackward:(id)sender { 664 - (void)moveBackward:(id)sender {
665 IsTextRTL(textInputClient_) ? [self moveRight:sender] 665 IsTextRTL(textInputClient_) ? [self moveRight:sender]
666 : [self moveLeft:sender]; 666 : [self moveLeft:sender];
667 } 667 }
668 668
669 - (void)moveLeft:(id)sender { 669 - (void)moveLeft:(id)sender {
670 [self handleAction:IDS_MOVE_LEFT 670 [self handleAction:ui::TextEditCommand::MOVE_LEFT
671 keyCode:ui::VKEY_LEFT 671 keyCode:ui::VKEY_LEFT
672 domCode:ui::DomCode::ARROW_LEFT 672 domCode:ui::DomCode::ARROW_LEFT
673 eventFlags:0]; 673 eventFlags:0];
674 } 674 }
675 675
676 - (void)moveUp:(id)sender { 676 - (void)moveUp:(id)sender {
677 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE 677 [self handleAction:ui::TextEditCommand::MOVE_UP
678 keyCode:ui::VKEY_UP 678 keyCode:ui::VKEY_UP
679 domCode:ui::DomCode::ARROW_UP 679 domCode:ui::DomCode::ARROW_UP
680 eventFlags:0]; 680 eventFlags:0];
681 } 681 }
682 682
683 - (void)moveDown:(id)sender { 683 - (void)moveDown:(id)sender {
684 [self handleAction:IDS_MOVE_TO_END_OF_LINE 684 [self handleAction:ui::TextEditCommand::MOVE_DOWN
685 keyCode:ui::VKEY_DOWN 685 keyCode:ui::VKEY_DOWN
686 domCode:ui::DomCode::ARROW_DOWN 686 domCode:ui::DomCode::ARROW_DOWN
687 eventFlags:0]; 687 eventFlags:0];
688 } 688 }
689 689
690 - (void)moveWordForward:(id)sender { 690 - (void)moveWordForward:(id)sender {
691 IsTextRTL(textInputClient_) ? [self moveWordLeft:sender] 691 IsTextRTL(textInputClient_) ? [self moveWordLeft:sender]
692 : [self moveWordRight:sender]; 692 : [self moveWordRight:sender];
693 } 693 }
694 694
695 - (void)moveWordBackward:(id)sender { 695 - (void)moveWordBackward:(id)sender {
696 IsTextRTL(textInputClient_) ? [self moveWordRight:sender] 696 IsTextRTL(textInputClient_) ? [self moveWordRight:sender]
697 : [self moveWordLeft:sender]; 697 : [self moveWordLeft:sender];
698 } 698 }
699 699
700 - (void)moveToBeginningOfLine:(id)sender { 700 - (void)moveToBeginningOfLine:(id)sender {
701 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE 701 [self handleAction:ui::TextEditCommand::MOVE_TO_BEGINNING_OF_LINE
702 keyCode:ui::VKEY_HOME 702 keyCode:ui::VKEY_HOME
703 domCode:ui::DomCode::HOME 703 domCode:ui::DomCode::HOME
704 eventFlags:0]; 704 eventFlags:0];
705 } 705 }
706 706
707 - (void)moveToEndOfLine:(id)sender { 707 - (void)moveToEndOfLine:(id)sender {
708 [self handleAction:IDS_MOVE_TO_END_OF_LINE 708 [self handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE
709 keyCode:ui::VKEY_END 709 keyCode:ui::VKEY_END
710 domCode:ui::DomCode::END 710 domCode:ui::DomCode::END
711 eventFlags:0]; 711 eventFlags:0];
712 } 712 }
713 713
714 - (void)moveToBeginningOfParagraph:(id)sender { 714 - (void)moveToBeginningOfParagraph:(id)sender {
715 [self moveToBeginningOfLine:sender]; 715 [self moveToBeginningOfLine:sender];
716 } 716 }
717 717
718 - (void)moveToEndOfParagraph:(id)sender { 718 - (void)moveToEndOfParagraph:(id)sender {
719 [self moveToEndOfLine:sender]; 719 [self moveToEndOfLine:sender];
720 } 720 }
721 721
722 - (void)moveToEndOfDocument:(id)sender { 722 - (void)moveToEndOfDocument:(id)sender {
723 [self handleAction:IDS_MOVE_TO_END_OF_LINE 723 [self handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE
724 keyCode:ui::VKEY_END 724 keyCode:ui::VKEY_END
725 domCode:ui::DomCode::END 725 domCode:ui::DomCode::END
726 eventFlags:ui::EF_CONTROL_DOWN]; 726 eventFlags:ui::EF_CONTROL_DOWN];
727 } 727 }
728 728
729 - (void)moveToBeginningOfDocument:(id)sender { 729 - (void)moveToBeginningOfDocument:(id)sender {
730 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE 730 [self handleAction:ui::TextEditCommand::MOVE_TO_BEGINNING_OF_LINE
731 keyCode:ui::VKEY_HOME 731 keyCode:ui::VKEY_HOME
732 domCode:ui::DomCode::HOME 732 domCode:ui::DomCode::HOME
733 eventFlags:ui::EF_CONTROL_DOWN]; 733 eventFlags:ui::EF_CONTROL_DOWN];
734 } 734 }
735 735
736 - (void)pageDown:(id)sender { 736 - (void)pageDown:(id)sender {
737 [self handleAction:IDS_MOVE_TO_END_OF_LINE 737 [self handleAction:ui::TextEditCommand::MOVE_PAGE_DOWN
738 keyCode:ui::VKEY_NEXT 738 keyCode:ui::VKEY_NEXT
739 domCode:ui::DomCode::PAGE_DOWN 739 domCode:ui::DomCode::PAGE_DOWN
740 eventFlags:0]; 740 eventFlags:0];
741 } 741 }
742 742
743 - (void)pageUp:(id)sender { 743 - (void)pageUp:(id)sender {
744 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE 744 [self handleAction:ui::TextEditCommand::MOVE_PAGE_UP
745 keyCode:ui::VKEY_PRIOR 745 keyCode:ui::VKEY_PRIOR
746 domCode:ui::DomCode::PAGE_UP 746 domCode:ui::DomCode::PAGE_UP
747 eventFlags:0]; 747 eventFlags:0];
748 } 748 }
749 749
750 - (void)moveBackwardAndModifySelection:(id)sender { 750 - (void)moveBackwardAndModifySelection:(id)sender {
751 IsTextRTL(textInputClient_) ? [self moveRightAndModifySelection:sender] 751 IsTextRTL(textInputClient_) ? [self moveRightAndModifySelection:sender]
752 : [self moveLeftAndModifySelection:sender]; 752 : [self moveLeftAndModifySelection:sender];
753 } 753 }
754 754
755 - (void)moveForwardAndModifySelection:(id)sender { 755 - (void)moveForwardAndModifySelection:(id)sender {
756 IsTextRTL(textInputClient_) ? [self moveLeftAndModifySelection:sender] 756 IsTextRTL(textInputClient_) ? [self moveLeftAndModifySelection:sender]
757 : [self moveRightAndModifySelection:sender]; 757 : [self moveRightAndModifySelection:sender];
758 } 758 }
759 759
760 - (void)moveWordForwardAndModifySelection:(id)sender { 760 - (void)moveWordForwardAndModifySelection:(id)sender {
761 IsTextRTL(textInputClient_) ? [self moveWordLeftAndModifySelection:sender] 761 IsTextRTL(textInputClient_) ? [self moveWordLeftAndModifySelection:sender]
762 : [self moveWordRightAndModifySelection:sender]; 762 : [self moveWordRightAndModifySelection:sender];
763 } 763 }
764 764
765 - (void)moveWordBackwardAndModifySelection:(id)sender { 765 - (void)moveWordBackwardAndModifySelection:(id)sender {
766 IsTextRTL(textInputClient_) ? [self moveWordRightAndModifySelection:sender] 766 IsTextRTL(textInputClient_) ? [self moveWordRightAndModifySelection:sender]
767 : [self moveWordLeftAndModifySelection:sender]; 767 : [self moveWordLeftAndModifySelection:sender];
768 } 768 }
769 769
770 - (void)moveUpAndModifySelection:(id)sender { 770 - (void)moveUpAndModifySelection:(id)sender {
771 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION 771 [self handleAction:ui::TextEditCommand::
772 MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
772 keyCode:ui::VKEY_UP 773 keyCode:ui::VKEY_UP
773 domCode:ui::DomCode::ARROW_UP 774 domCode:ui::DomCode::ARROW_UP
774 eventFlags:ui::EF_SHIFT_DOWN]; 775 eventFlags:ui::EF_SHIFT_DOWN];
775 } 776 }
776 777
777 - (void)moveDownAndModifySelection:(id)sender { 778 - (void)moveDownAndModifySelection:(id)sender {
778 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION 779 [self
779 keyCode:ui::VKEY_DOWN 780 handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
780 domCode:ui::DomCode::ARROW_DOWN 781 keyCode:ui::VKEY_DOWN
781 eventFlags:ui::EF_SHIFT_DOWN]; 782 domCode:ui::DomCode::ARROW_DOWN
783 eventFlags:ui::EF_SHIFT_DOWN];
782 } 784 }
783 785
784 - (void)moveToBeginningOfLineAndModifySelection:(id)sender { 786 - (void)moveToBeginningOfLineAndModifySelection:(id)sender {
785 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION 787 [self handleAction:ui::TextEditCommand::
788 MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
786 keyCode:ui::VKEY_HOME 789 keyCode:ui::VKEY_HOME
787 domCode:ui::DomCode::HOME 790 domCode:ui::DomCode::HOME
788 eventFlags:ui::EF_SHIFT_DOWN]; 791 eventFlags:ui::EF_SHIFT_DOWN];
789 } 792 }
790 793
791 - (void)moveToEndOfLineAndModifySelection:(id)sender { 794 - (void)moveToEndOfLineAndModifySelection:(id)sender {
792 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION 795 [self
793 keyCode:ui::VKEY_END 796 handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
794 domCode:ui::DomCode::END 797 keyCode:ui::VKEY_END
795 eventFlags:ui::EF_SHIFT_DOWN]; 798 domCode:ui::DomCode::END
799 eventFlags:ui::EF_SHIFT_DOWN];
796 } 800 }
797 801
798 - (void)moveToBeginningOfParagraphAndModifySelection:(id)sender { 802 - (void)moveToBeginningOfParagraphAndModifySelection:(id)sender {
799 [self moveToBeginningOfLineAndModifySelection:sender]; 803 [self moveToBeginningOfLineAndModifySelection:sender];
800 } 804 }
801 805
802 - (void)moveToEndOfParagraphAndModifySelection:(id)sender { 806 - (void)moveToEndOfParagraphAndModifySelection:(id)sender {
803 [self moveToEndOfLineAndModifySelection:sender]; 807 [self moveToEndOfLineAndModifySelection:sender];
804 } 808 }
805 809
806 - (void)moveToEndOfDocumentAndModifySelection:(id)sender { 810 - (void)moveToEndOfDocumentAndModifySelection:(id)sender {
807 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION 811 [self
808 keyCode:ui::VKEY_END 812 handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
809 domCode:ui::DomCode::END 813 keyCode:ui::VKEY_END
810 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 814 domCode:ui::DomCode::END
815 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
811 } 816 }
812 817
813 - (void)moveToBeginningOfDocumentAndModifySelection:(id)sender { 818 - (void)moveToBeginningOfDocumentAndModifySelection:(id)sender {
814 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION 819 [self handleAction:ui::TextEditCommand::
820 MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
815 keyCode:ui::VKEY_HOME 821 keyCode:ui::VKEY_HOME
816 domCode:ui::DomCode::HOME 822 domCode:ui::DomCode::HOME
817 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 823 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
818 } 824 }
819 825
820 - (void)pageDownAndModifySelection:(id)sender { 826 - (void)pageDownAndModifySelection:(id)sender {
821 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION 827 [self
822 keyCode:ui::VKEY_NEXT 828 handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
823 domCode:ui::DomCode::PAGE_DOWN 829 keyCode:ui::VKEY_NEXT
824 eventFlags:ui::EF_SHIFT_DOWN]; 830 domCode:ui::DomCode::PAGE_DOWN
831 eventFlags:ui::EF_SHIFT_DOWN];
825 } 832 }
826 833
827 - (void)pageUpAndModifySelection:(id)sender { 834 - (void)pageUpAndModifySelection:(id)sender {
828 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION 835 [self handleAction:ui::TextEditCommand::
836 MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
829 keyCode:ui::VKEY_PRIOR 837 keyCode:ui::VKEY_PRIOR
830 domCode:ui::DomCode::PAGE_UP 838 domCode:ui::DomCode::PAGE_UP
831 eventFlags:ui::EF_SHIFT_DOWN]; 839 eventFlags:ui::EF_SHIFT_DOWN];
832 } 840 }
833 841
834 - (void)moveParagraphForwardAndModifySelection:(id)sender { 842 - (void)moveParagraphForwardAndModifySelection:(id)sender {
835 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION 843 [self
836 keyCode:ui::VKEY_DOWN 844 handleAction:ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
837 domCode:ui::DomCode::ARROW_DOWN 845 keyCode:ui::VKEY_DOWN
838 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 846 domCode:ui::DomCode::ARROW_DOWN
847 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
839 } 848 }
840 849
841 - (void)moveParagraphBackwardAndModifySelection:(id)sender { 850 - (void)moveParagraphBackwardAndModifySelection:(id)sender {
842 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION 851 [self handleAction:ui::TextEditCommand::
852 MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
843 keyCode:ui::VKEY_UP 853 keyCode:ui::VKEY_UP
844 domCode:ui::DomCode::ARROW_UP 854 domCode:ui::DomCode::ARROW_UP
845 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 855 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
846 } 856 }
847 857
848 - (void)moveWordRight:(id)sender { 858 - (void)moveWordRight:(id)sender {
849 [self handleAction:IDS_MOVE_WORD_RIGHT 859 [self handleAction:ui::TextEditCommand::MOVE_WORD_RIGHT
850 keyCode:ui::VKEY_RIGHT 860 keyCode:ui::VKEY_RIGHT
851 domCode:ui::DomCode::ARROW_RIGHT 861 domCode:ui::DomCode::ARROW_RIGHT
852 eventFlags:ui::EF_CONTROL_DOWN]; 862 eventFlags:ui::EF_CONTROL_DOWN];
853 } 863 }
854 864
855 - (void)moveWordLeft:(id)sender { 865 - (void)moveWordLeft:(id)sender {
856 [self handleAction:IDS_MOVE_WORD_LEFT 866 [self handleAction:ui::TextEditCommand::MOVE_WORD_LEFT
857 keyCode:ui::VKEY_LEFT 867 keyCode:ui::VKEY_LEFT
858 domCode:ui::DomCode::ARROW_LEFT 868 domCode:ui::DomCode::ARROW_LEFT
859 eventFlags:ui::EF_CONTROL_DOWN]; 869 eventFlags:ui::EF_CONTROL_DOWN];
860 } 870 }
861 871
862 - (void)moveRightAndModifySelection:(id)sender { 872 - (void)moveRightAndModifySelection:(id)sender {
863 [self handleAction:IDS_MOVE_RIGHT_AND_MODIFY_SELECTION 873 [self handleAction:ui::TextEditCommand::MOVE_RIGHT_AND_MODIFY_SELECTION
864 keyCode:ui::VKEY_RIGHT 874 keyCode:ui::VKEY_RIGHT
865 domCode:ui::DomCode::ARROW_RIGHT 875 domCode:ui::DomCode::ARROW_RIGHT
866 eventFlags:ui::EF_SHIFT_DOWN]; 876 eventFlags:ui::EF_SHIFT_DOWN];
867 } 877 }
868 878
869 - (void)moveLeftAndModifySelection:(id)sender { 879 - (void)moveLeftAndModifySelection:(id)sender {
870 [self handleAction:IDS_MOVE_LEFT_AND_MODIFY_SELECTION 880 [self handleAction:ui::TextEditCommand::MOVE_LEFT_AND_MODIFY_SELECTION
871 keyCode:ui::VKEY_LEFT 881 keyCode:ui::VKEY_LEFT
872 domCode:ui::DomCode::ARROW_LEFT 882 domCode:ui::DomCode::ARROW_LEFT
873 eventFlags:ui::EF_SHIFT_DOWN]; 883 eventFlags:ui::EF_SHIFT_DOWN];
874 } 884 }
875 885
876 - (void)moveWordRightAndModifySelection:(id)sender { 886 - (void)moveWordRightAndModifySelection:(id)sender {
877 [self handleAction:IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION 887 [self handleAction:ui::TextEditCommand::MOVE_WORD_RIGHT_AND_MODIFY_SELECTION
878 keyCode:ui::VKEY_RIGHT 888 keyCode:ui::VKEY_RIGHT
879 domCode:ui::DomCode::ARROW_RIGHT 889 domCode:ui::DomCode::ARROW_RIGHT
880 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 890 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
881 } 891 }
882 892
883 - (void)moveWordLeftAndModifySelection:(id)sender { 893 - (void)moveWordLeftAndModifySelection:(id)sender {
884 [self handleAction:IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION 894 [self handleAction:ui::TextEditCommand::MOVE_WORD_LEFT_AND_MODIFY_SELECTION
885 keyCode:ui::VKEY_LEFT 895 keyCode:ui::VKEY_LEFT
886 domCode:ui::DomCode::ARROW_LEFT 896 domCode:ui::DomCode::ARROW_LEFT
887 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 897 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
888 } 898 }
889 899
890 - (void)moveToLeftEndOfLine:(id)sender { 900 - (void)moveToLeftEndOfLine:(id)sender {
891 IsTextRTL(textInputClient_) ? [self moveToEndOfLine:sender] 901 IsTextRTL(textInputClient_) ? [self moveToEndOfLine:sender]
892 : [self moveToBeginningOfLine:sender]; 902 : [self moveToBeginningOfLine:sender];
893 } 903 }
894 904
(...skipping 10 matching lines...) Expand all
905 915
906 - (void)moveToRightEndOfLineAndModifySelection:(id)sender { 916 - (void)moveToRightEndOfLineAndModifySelection:(id)sender {
907 IsTextRTL(textInputClient_) 917 IsTextRTL(textInputClient_)
908 ? [self moveToBeginningOfLineAndModifySelection:sender] 918 ? [self moveToBeginningOfLineAndModifySelection:sender]
909 : [self moveToEndOfLineAndModifySelection:sender]; 919 : [self moveToEndOfLineAndModifySelection:sender];
910 } 920 }
911 921
912 // Deletions. 922 // Deletions.
913 923
914 - (void)deleteForward:(id)sender { 924 - (void)deleteForward:(id)sender {
915 [self handleAction:IDS_DELETE_FORWARD 925 [self handleAction:ui::TextEditCommand::DELETE_FORWARD
916 keyCode:ui::VKEY_DELETE 926 keyCode:ui::VKEY_DELETE
917 domCode:ui::DomCode::DEL 927 domCode:ui::DomCode::DEL
918 eventFlags:0]; 928 eventFlags:0];
919 } 929 }
920 930
921 - (void)deleteBackward:(id)sender { 931 - (void)deleteBackward:(id)sender {
922 [self handleAction:IDS_DELETE_BACKWARD 932 [self handleAction:ui::TextEditCommand::DELETE_BACKWARD
923 keyCode:ui::VKEY_BACK 933 keyCode:ui::VKEY_BACK
924 domCode:ui::DomCode::BACKSPACE 934 domCode:ui::DomCode::BACKSPACE
925 eventFlags:0]; 935 eventFlags:0];
926 } 936 }
927 937
928 - (void)deleteWordForward:(id)sender { 938 - (void)deleteWordForward:(id)sender {
929 [self handleAction:IDS_DELETE_WORD_FORWARD 939 [self handleAction:ui::TextEditCommand::DELETE_WORD_FORWARD
930 keyCode:ui::VKEY_DELETE 940 keyCode:ui::VKEY_DELETE
931 domCode:ui::DomCode::DEL 941 domCode:ui::DomCode::DEL
932 eventFlags:ui::EF_CONTROL_DOWN]; 942 eventFlags:ui::EF_CONTROL_DOWN];
933 } 943 }
934 944
935 - (void)deleteWordBackward:(id)sender { 945 - (void)deleteWordBackward:(id)sender {
936 [self handleAction:IDS_DELETE_WORD_BACKWARD 946 [self handleAction:ui::TextEditCommand::DELETE_WORD_BACKWARD
937 keyCode:ui::VKEY_BACK 947 keyCode:ui::VKEY_BACK
938 domCode:ui::DomCode::BACKSPACE 948 domCode:ui::DomCode::BACKSPACE
939 eventFlags:ui::EF_CONTROL_DOWN]; 949 eventFlags:ui::EF_CONTROL_DOWN];
940 } 950 }
941 951
942 - (void)deleteToBeginningOfLine:(id)sender { 952 - (void)deleteToBeginningOfLine:(id)sender {
943 [self handleAction:IDS_DELETE_TO_BEGINNING_OF_LINE 953 [self handleAction:ui::TextEditCommand::DELETE_TO_BEGINNING_OF_LINE
944 keyCode:ui::VKEY_BACK 954 keyCode:ui::VKEY_BACK
945 domCode:ui::DomCode::BACKSPACE 955 domCode:ui::DomCode::BACKSPACE
946 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 956 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
947 } 957 }
948 958
949 - (void)deleteToEndOfLine:(id)sender { 959 - (void)deleteToEndOfLine:(id)sender {
950 [self handleAction:IDS_DELETE_TO_END_OF_LINE 960 [self handleAction:ui::TextEditCommand::DELETE_TO_END_OF_LINE
951 keyCode:ui::VKEY_DELETE 961 keyCode:ui::VKEY_DELETE
952 domCode:ui::DomCode::DEL 962 domCode:ui::DomCode::DEL
953 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 963 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
954 } 964 }
955 965
956 - (void)deleteToBeginningOfParagraph:(id)sender { 966 - (void)deleteToBeginningOfParagraph:(id)sender {
957 [self deleteToBeginningOfLine:sender]; 967 [self deleteToBeginningOfLine:sender];
958 } 968 }
959 969
960 - (void)deleteToEndOfParagraph:(id)sender { 970 - (void)deleteToEndOfParagraph:(id)sender {
961 [self deleteToEndOfLine:sender]; 971 [self deleteToEndOfLine:sender];
962 } 972 }
963 973
964 // Cancellation. 974 // Cancellation.
965 975
966 - (void)cancelOperation:(id)sender { 976 - (void)cancelOperation:(id)sender {
967 [self handleAction:0 977 [self handleAction:ui::TextEditCommand::INVALID_COMMAND
968 keyCode:ui::VKEY_ESCAPE 978 keyCode:ui::VKEY_ESCAPE
969 domCode:ui::DomCode::ESCAPE 979 domCode:ui::DomCode::ESCAPE
970 eventFlags:0]; 980 eventFlags:0];
971 } 981 }
972 982
973 // Support for Services in context menus. 983 // Support for Services in context menus.
974 // Currently we only support reading and writing plain strings. 984 // Currently we only support reading and writing plain strings.
975 - (id)validRequestorForSendType:(NSString*)sendType 985 - (id)validRequestorForSendType:(NSString*)sendType
976 returnType:(NSString*)returnType { 986 returnType:(NSString*)returnType {
977 BOOL canWrite = [sendType isEqualToString:NSStringPboardType] && 987 BOOL canWrite = [sendType isEqualToString:NSStringPboardType] &&
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 1165
1156 // NSUserInterfaceValidations protocol implementation. 1166 // NSUserInterfaceValidations protocol implementation.
1157 1167
1158 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { 1168 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
1159 if (!textInputClient_) 1169 if (!textInputClient_)
1160 return NO; 1170 return NO;
1161 1171
1162 SEL action = [item action]; 1172 SEL action = [item action];
1163 1173
1164 if (action == @selector(undo:)) 1174 if (action == @selector(undo:))
1165 return textInputClient_->IsEditCommandEnabled(IDS_APP_UNDO); 1175 return textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::UNDO);
1166 if (action == @selector(redo:)) 1176 if (action == @selector(redo:))
1167 return textInputClient_->IsEditCommandEnabled(IDS_APP_REDO); 1177 return textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::REDO);
1168 if (action == @selector(cut:)) 1178 if (action == @selector(cut:))
1169 return textInputClient_->IsEditCommandEnabled(IDS_APP_CUT); 1179 return textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::CUT);
1170 if (action == @selector(copy:)) 1180 if (action == @selector(copy:))
1171 return textInputClient_->IsEditCommandEnabled(IDS_APP_COPY); 1181 return textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::COPY);
1172 if (action == @selector(paste:)) 1182 if (action == @selector(paste:))
1173 return textInputClient_->IsEditCommandEnabled(IDS_APP_PASTE); 1183 return textInputClient_->IsEditCommandEnabled(ui::TextEditCommand::PASTE);
1174 if (action == @selector(selectAll:)) 1184 if (action == @selector(selectAll:))
1175 return textInputClient_->IsEditCommandEnabled(IDS_APP_SELECT_ALL); 1185 return textInputClient_->IsEditCommandEnabled(
1186 ui::TextEditCommand::SELECT_ALL);
1176 1187
1177 return NO; 1188 return NO;
1178 } 1189 }
1179 1190
1180 // NSAccessibility informal protocol implementation. 1191 // NSAccessibility informal protocol implementation.
1181 1192
1182 - (id)accessibilityAttributeValue:(NSString*)attribute { 1193 - (id)accessibilityAttributeValue:(NSString*)attribute {
1183 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { 1194 if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
1184 return @[ hostedView_->GetNativeViewAccessible() ]; 1195 return @[ hostedView_->GetNativeViewAccessible() ];
1185 } 1196 }
1186 1197
1187 return [super accessibilityAttributeValue:attribute]; 1198 return [super accessibilityAttributeValue:attribute];
1188 } 1199 }
1189 1200
1190 - (id)accessibilityHitTest:(NSPoint)point { 1201 - (id)accessibilityHitTest:(NSPoint)point {
1191 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; 1202 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point];
1192 } 1203 }
1193 1204
1194 @end 1205 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698