Home | History | Annotate | Download | only in textfield
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/views/controls/textfield/native_textfield_views.h"
      6 
      7 #include <algorithm>
      8 #include <set>
      9 
     10 #include "base/bind.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/i18n/case_conversion.h"
     13 #include "base/logging.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "grit/ui_strings.h"
     17 #include "third_party/icu/source/common/unicode/uchar.h"
     18 #include "third_party/skia/include/core/SkColor.h"
     19 #include "ui/base/clipboard/clipboard.h"
     20 #include "ui/base/dragdrop/drag_drop_types.h"
     21 #include "ui/base/dragdrop/drag_utils.h"
     22 #include "ui/base/l10n/l10n_util.h"
     23 #include "ui/base/ui_base_switches_util.h"
     24 #include "ui/compositor/layer.h"
     25 #include "ui/events/event.h"
     26 #include "ui/gfx/canvas.h"
     27 #include "ui/gfx/insets.h"
     28 #include "ui/gfx/range/range.h"
     29 #include "ui/gfx/render_text.h"
     30 #include "ui/gfx/text_constants.h"
     31 #include "ui/native_theme/native_theme.h"
     32 #include "ui/views/background.h"
     33 #include "ui/views/border.h"
     34 #include "ui/views/controls/focusable_border.h"
     35 #include "ui/views/controls/menu/menu_item_view.h"
     36 #include "ui/views/controls/menu/menu_model_adapter.h"
     37 #include "ui/views/controls/menu/menu_runner.h"
     38 #include "ui/views/controls/textfield/textfield.h"
     39 #include "ui/views/controls/textfield/textfield_controller.h"
     40 #include "ui/views/controls/textfield/textfield_views_model.h"
     41 #include "ui/views/drag_utils.h"
     42 #include "ui/views/ime/input_method.h"
     43 #include "ui/views/metrics.h"
     44 #include "ui/views/widget/widget.h"
     45 
     46 #if defined(USE_AURA)
     47 #include "ui/base/cursor/cursor.h"
     48 #endif
     49 
     50 #if defined(OS_WIN) && defined(USE_AURA)
     51 #include "base/win/win_util.h"
     52 #endif
     53 
     54 namespace {
     55 
     56 void ConvertRectToScreen(const views::View* src, gfx::Rect* r) {
     57   DCHECK(src);
     58 
     59   gfx::Point new_origin = r->origin();
     60   views::View::ConvertPointToScreen(src, &new_origin);
     61   r->set_origin(new_origin);
     62 }
     63 
     64 }  // namespace
     65 
     66 namespace views {
     67 
     68 const char NativeTextfieldViews::kViewClassName[] =
     69     "views/NativeTextfieldViews";
     70 
     71 NativeTextfieldViews::NativeTextfieldViews(Textfield* parent)
     72     : textfield_(parent),
     73       model_(new TextfieldViewsModel(this)),
     74       text_border_(new FocusableBorder()),
     75       is_cursor_visible_(false),
     76       is_drop_cursor_visible_(false),
     77       skip_input_method_cancel_composition_(false),
     78       initiating_drag_(false),
     79       cursor_timer_(this),
     80       aggregated_clicks_(0) {
     81   set_border(text_border_);
     82   GetRenderText()->SetFontList(textfield_->font_list());
     83   UpdateColorsFromTheme(GetNativeTheme());
     84   set_context_menu_controller(this);
     85   parent->set_context_menu_controller(this);
     86   set_drag_controller(this);
     87 }
     88 
     89 NativeTextfieldViews::~NativeTextfieldViews() {
     90 }
     91 
     92 ////////////////////////////////////////////////////////////////////////////////
     93 // NativeTextfieldViews, View overrides:
     94 
     95 bool NativeTextfieldViews::OnMousePressed(const ui::MouseEvent& event) {
     96   OnBeforeUserAction();
     97   TrackMouseClicks(event);
     98 
     99   TextfieldController* controller = textfield_->GetController();
    100   if (!(controller && controller->HandleMouseEvent(textfield_, event)) &&
    101       !textfield_->OnMousePressed(event)) {
    102     HandleMousePressEvent(event);
    103   }
    104 
    105   OnAfterUserAction();
    106   touch_selection_controller_.reset();
    107   return true;
    108 }
    109 
    110 bool NativeTextfieldViews::ExceededDragThresholdFromLastClickLocation(
    111     const ui::MouseEvent& event) {
    112   return ExceededDragThreshold(event.location() - last_click_location_);
    113 }
    114 
    115 bool NativeTextfieldViews::OnMouseDragged(const ui::MouseEvent& event) {
    116   // Don't adjust the cursor on a potential drag and drop, or if the mouse
    117   // movement from the last mouse click does not exceed the drag threshold.
    118   if (initiating_drag_ || !ExceededDragThresholdFromLastClickLocation(event) ||
    119       !event.IsOnlyLeftMouseButton()) {
    120     return true;
    121   }
    122 
    123   OnBeforeUserAction();
    124   // TODO: Remove once NativeTextfield implementations are consolidated to
    125   // Textfield.
    126   if (!textfield_->OnMouseDragged(event)) {
    127     MoveCursorTo(event.location(), true);
    128     if (aggregated_clicks_ == 1) {
    129       model_->SelectWord();
    130       // Expand the selection so the initially selected word remains selected.
    131       gfx::Range selection = GetRenderText()->selection();
    132       const size_t min = std::min(selection.GetMin(),
    133                                   double_click_word_.GetMin());
    134       const size_t max = std::max(selection.GetMax(),
    135                                   double_click_word_.GetMax());
    136       const bool reversed = selection.is_reversed();
    137       selection.set_start(reversed ? max : min);
    138       selection.set_end(reversed ? min : max);
    139       model_->SelectRange(selection);
    140     }
    141     SchedulePaint();
    142   }
    143   OnAfterUserAction();
    144   return true;
    145 }
    146 
    147 void NativeTextfieldViews::OnMouseReleased(const ui::MouseEvent& event) {
    148   OnBeforeUserAction();
    149   // TODO: Remove once NativeTextfield implementations are consolidated to
    150   // Textfield.
    151   textfield_->OnMouseReleased(event);
    152   // Cancel suspected drag initiations, the user was clicking in the selection.
    153   if (initiating_drag_ && MoveCursorTo(event.location(), false))
    154     SchedulePaint();
    155   initiating_drag_ = false;
    156   OnAfterUserAction();
    157 }
    158 
    159 void NativeTextfieldViews::OnGestureEvent(ui::GestureEvent* event) {
    160   textfield_->OnGestureEvent(event);
    161   if (event->handled())
    162     return;
    163 
    164   switch (event->type()) {
    165     case ui::ET_GESTURE_TAP_DOWN:
    166       OnBeforeUserAction();
    167       textfield_->RequestFocus();
    168       // We don't deselect if the point is in the selection
    169       // because TAP_DOWN may turn into a LONG_PRESS.
    170       if (!GetRenderText()->IsPointInSelection(event->location()) &&
    171           MoveCursorTo(event->location(), false))
    172         SchedulePaint();
    173       OnAfterUserAction();
    174       event->SetHandled();
    175       break;
    176     case ui::ET_GESTURE_SCROLL_UPDATE:
    177       OnBeforeUserAction();
    178       if (MoveCursorTo(event->location(), true))
    179         SchedulePaint();
    180       OnAfterUserAction();
    181       event->SetHandled();
    182       break;
    183     case ui::ET_GESTURE_SCROLL_END:
    184     case ui::ET_SCROLL_FLING_START:
    185       CreateTouchSelectionControllerAndNotifyIt();
    186       event->SetHandled();
    187       break;
    188     case ui::ET_GESTURE_TAP:
    189       if (event->details().tap_count() == 1) {
    190         CreateTouchSelectionControllerAndNotifyIt();
    191       } else {
    192         OnBeforeUserAction();
    193         SelectAll(false);
    194         OnAfterUserAction();
    195         event->SetHandled();
    196       }
    197       break;
    198     case ui::ET_GESTURE_LONG_PRESS:
    199       // If long press happens outside selection, select word and show context
    200       // menu (If touch selection is enabled, context menu is shown by the
    201       // |touch_selection_controller_|, hence we mark the event handled.
    202       // Otherwise, the regular context menu will be shown by views).
    203       // If long press happens in selected text and touch drag drop is enabled,
    204       // we will turn off touch selection (if one exists) and let views do drag
    205       // drop.
    206       if (!GetRenderText()->IsPointInSelection(event->location())) {
    207         OnBeforeUserAction();
    208         model_->SelectWord();
    209         touch_selection_controller_.reset(
    210             ui::TouchSelectionController::create(this));
    211         OnCaretBoundsChanged();
    212         SchedulePaint();
    213         OnAfterUserAction();
    214         if (touch_selection_controller_.get())
    215           event->SetHandled();
    216       } else if (switches::IsTouchDragDropEnabled()) {
    217         initiating_drag_ = true;
    218         touch_selection_controller_.reset();
    219       } else {
    220         if (!touch_selection_controller_.get())
    221           CreateTouchSelectionControllerAndNotifyIt();
    222         if (touch_selection_controller_.get())
    223           event->SetHandled();
    224       }
    225       return;
    226     case ui::ET_GESTURE_LONG_TAP:
    227       if (!touch_selection_controller_.get())
    228         CreateTouchSelectionControllerAndNotifyIt();
    229 
    230       // If touch selection is enabled, the context menu on long tap will be
    231       // shown by the |touch_selection_controller_|, hence we mark the event
    232       // handled so views does not try to show context menu on it.
    233       if (touch_selection_controller_.get())
    234         event->SetHandled();
    235       break;
    236     default:
    237       View::OnGestureEvent(event);
    238       return;
    239   }
    240   PlatformGestureEventHandling(event);
    241 }
    242 
    243 bool NativeTextfieldViews::OnKeyPressed(const ui::KeyEvent& event) {
    244   // OnKeyPressed/OnKeyReleased/OnFocus/OnBlur will never be invoked on
    245   // NativeTextfieldViews as it will never gain focus.
    246   NOTREACHED();
    247   return false;
    248 }
    249 
    250 bool NativeTextfieldViews::OnKeyReleased(const ui::KeyEvent& event) {
    251   NOTREACHED();
    252   return false;
    253 }
    254 
    255 bool NativeTextfieldViews::GetDropFormats(
    256     int* formats,
    257     std::set<OSExchangeData::CustomFormat>* custom_formats) {
    258   if (!textfield_->enabled() || textfield_->read_only())
    259     return false;
    260   // TODO(msw): Can we support URL, FILENAME, etc.?
    261   *formats = ui::OSExchangeData::STRING;
    262   TextfieldController* controller = textfield_->GetController();
    263   if (controller)
    264     controller->AppendDropFormats(formats, custom_formats);
    265   return true;
    266 }
    267 
    268 bool NativeTextfieldViews::CanDrop(const OSExchangeData& data) {
    269   int formats;
    270   std::set<OSExchangeData::CustomFormat> custom_formats;
    271   GetDropFormats(&formats, &custom_formats);
    272   return textfield_->enabled() && !textfield_->read_only() &&
    273       data.HasAnyFormat(formats, custom_formats);
    274 }
    275 
    276 int NativeTextfieldViews::OnDragUpdated(const ui::DropTargetEvent& event) {
    277   DCHECK(CanDrop(event.data()));
    278 
    279   const gfx::Range& selection = GetRenderText()->selection();
    280   drop_cursor_position_ = GetRenderText()->FindCursorPosition(event.location());
    281   bool in_selection = !selection.is_empty() &&
    282       selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
    283   is_drop_cursor_visible_ = !in_selection;
    284   // TODO(msw): Pan over text when the user drags to the visible text edge.
    285   OnCaretBoundsChanged();
    286   SchedulePaint();
    287 
    288   if (initiating_drag_) {
    289     if (in_selection)
    290       return ui::DragDropTypes::DRAG_NONE;
    291     return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
    292                                    ui::DragDropTypes::DRAG_MOVE;
    293   }
    294   return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
    295 }
    296 
    297 void NativeTextfieldViews::OnDragExited() {
    298   is_drop_cursor_visible_ = false;
    299   SchedulePaint();
    300 }
    301 
    302 int NativeTextfieldViews::OnPerformDrop(const ui::DropTargetEvent& event) {
    303   DCHECK(CanDrop(event.data()));
    304 
    305   is_drop_cursor_visible_ = false;
    306 
    307   TextfieldController* controller = textfield_->GetController();
    308   if (controller) {
    309       int drag_operation = controller->OnDrop(event.data());
    310       if (drag_operation != ui::DragDropTypes::DRAG_NONE)
    311         return drag_operation;
    312   }
    313 
    314   DCHECK(!initiating_drag_ ||
    315          !GetRenderText()->IsPointInSelection(event.location()));
    316   OnBeforeUserAction();
    317   skip_input_method_cancel_composition_ = true;
    318 
    319   gfx::SelectionModel drop_destination_model =
    320       GetRenderText()->FindCursorPosition(event.location());
    321   string16 text;
    322   event.data().GetString(&text);
    323   text = GetTextForDisplay(text);
    324 
    325   // Delete the current selection for a drag and drop within this view.
    326   const bool move = initiating_drag_ && !event.IsControlDown() &&
    327                     event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
    328   if (move) {
    329     // Adjust the drop destination if it is on or after the current selection.
    330     size_t drop = drop_destination_model.caret_pos();
    331     drop -= GetSelectedRange().Intersect(gfx::Range(0, drop)).length();
    332     model_->DeleteSelectionAndInsertTextAt(text, drop);
    333   } else {
    334     model_->MoveCursorTo(drop_destination_model);
    335     // Drop always inserts text even if the textfield is not in insert mode.
    336     model_->InsertText(text);
    337   }
    338   skip_input_method_cancel_composition_ = false;
    339   UpdateAfterChange(true, true);
    340   OnAfterUserAction();
    341   return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
    342 }
    343 
    344 void NativeTextfieldViews::OnDragDone() {
    345   initiating_drag_ = false;
    346   is_drop_cursor_visible_ = false;
    347 }
    348 
    349 void NativeTextfieldViews::OnPaint(gfx::Canvas* canvas) {
    350   OnPaintBackground(canvas);
    351   PaintTextAndCursor(canvas);
    352   if (textfield_->draw_border())
    353     OnPaintBorder(canvas);
    354 }
    355 
    356 void NativeTextfieldViews::OnFocus() {
    357   NOTREACHED();
    358 }
    359 
    360 void NativeTextfieldViews::OnBlur() {
    361   NOTREACHED();
    362 }
    363 
    364 void NativeTextfieldViews::OnNativeThemeChanged(const ui::NativeTheme* theme) {
    365   UpdateColorsFromTheme(theme);
    366 }
    367 
    368 void NativeTextfieldViews::SelectRect(const gfx::Point& start,
    369                                       const gfx::Point& end) {
    370   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
    371     return;
    372 
    373   gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
    374   gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
    375   gfx::SelectionModel selection(
    376       gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
    377       end_caret.caret_affinity());
    378 
    379   OnBeforeUserAction();
    380   model_->SelectSelectionModel(selection);
    381   OnCaretBoundsChanged();
    382   SchedulePaint();
    383   OnAfterUserAction();
    384 }
    385 
    386 void NativeTextfieldViews::MoveCaretTo(const gfx::Point& point) {
    387   SelectRect(point, point);
    388 }
    389 
    390 void NativeTextfieldViews::GetSelectionEndPoints(gfx::Rect* p1,
    391                                                  gfx::Rect* p2) {
    392   gfx::RenderText* render_text = GetRenderText();
    393   const gfx::SelectionModel& sel = render_text->selection_model();
    394   gfx::SelectionModel start_sel =
    395       render_text->GetSelectionModelForSelectionStart();
    396   *p1 = render_text->GetCursorBounds(start_sel, true);
    397   *p2 = render_text->GetCursorBounds(sel, true);
    398 }
    399 
    400 gfx::Rect NativeTextfieldViews::GetBounds() {
    401   return bounds();
    402 }
    403 
    404 gfx::NativeView NativeTextfieldViews::GetNativeView() {
    405   return GetWidget()->GetNativeView();
    406 }
    407 
    408 void NativeTextfieldViews::ConvertPointToScreen(gfx::Point* point) {
    409   View::ConvertPointToScreen(this, point);
    410 }
    411 
    412 void NativeTextfieldViews::ConvertPointFromScreen(gfx::Point* point) {
    413   View::ConvertPointFromScreen(this, point);
    414 }
    415 
    416 bool NativeTextfieldViews::DrawsHandles() {
    417   return false;
    418 }
    419 
    420 void NativeTextfieldViews::OpenContextMenu(const gfx::Point& anchor) {
    421   touch_selection_controller_.reset();
    422   ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
    423 }
    424 
    425 gfx::NativeCursor NativeTextfieldViews::GetCursor(const ui::MouseEvent& event) {
    426   bool in_selection = GetRenderText()->IsPointInSelection(event.location());
    427   bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
    428   bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
    429 #if defined(USE_AURA)
    430   return text_cursor ? ui::kCursorIBeam : ui::kCursorNull;
    431 #elif defined(OS_WIN)
    432   static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM);
    433   static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
    434   return text_cursor ? ibeam : arrow;
    435 #endif
    436 }
    437 
    438 /////////////////////////////////////////////////////////////////
    439 // NativeTextfieldViews, ContextMenuController overrides:
    440 void NativeTextfieldViews::ShowContextMenuForView(
    441     View* source,
    442     const gfx::Point& point,
    443     ui::MenuSourceType source_type) {
    444   UpdateContextMenu();
    445   if (context_menu_runner_->RunMenuAt(GetWidget(), NULL,
    446           gfx::Rect(point, gfx::Size()), views::MenuItemView::TOPLEFT,
    447           source_type,
    448           MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
    449       MenuRunner::MENU_DELETED)
    450     return;
    451 }
    452 
    453 /////////////////////////////////////////////////////////////////
    454 // NativeTextfieldViews, views::DragController overrides:
    455 void NativeTextfieldViews::WriteDragDataForView(views::View* sender,
    456                                                 const gfx::Point& press_pt,
    457                                                 OSExchangeData* data) {
    458   DCHECK_NE(ui::DragDropTypes::DRAG_NONE,
    459             GetDragOperationsForView(sender, press_pt));
    460   data->SetString(GetSelectedText());
    461   scoped_ptr<gfx::Canvas> canvas(
    462       views::GetCanvasForDragImage(textfield_->GetWidget(), size()));
    463   GetRenderText()->DrawSelectedTextForDrag(canvas.get());
    464   drag_utils::SetDragImageOnDataObject(*canvas, size(),
    465                                        press_pt.OffsetFromOrigin(),
    466                                        data);
    467   TextfieldController* controller = textfield_->GetController();
    468   if (controller)
    469     controller->OnWriteDragData(data);
    470 }
    471 
    472 int NativeTextfieldViews::GetDragOperationsForView(views::View* sender,
    473                                                    const gfx::Point& p) {
    474   int drag_operations = ui::DragDropTypes::DRAG_COPY;
    475   if (!textfield_->enabled() || textfield_->IsObscured() ||
    476       !GetRenderText()->IsPointInSelection(p))
    477     drag_operations = ui::DragDropTypes::DRAG_NONE;
    478   else if (sender == this && !textfield_->read_only())
    479     drag_operations =
    480         ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
    481   TextfieldController* controller = textfield_->GetController();
    482   if (controller)
    483     controller->OnGetDragOperationsForTextfield(&drag_operations);
    484   return drag_operations;
    485 }
    486 
    487 bool NativeTextfieldViews::CanStartDragForView(View* sender,
    488                                                const gfx::Point& press_pt,
    489                                                const gfx::Point& p) {
    490   return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
    491 }
    492 
    493 /////////////////////////////////////////////////////////////////
    494 // NativeTextfieldViews, NativeTextifieldWrapper overrides:
    495 
    496 string16 NativeTextfieldViews::GetText() const {
    497   return model_->GetText();
    498 }
    499 
    500 void NativeTextfieldViews::UpdateText() {
    501   model_->SetText(GetTextForDisplay(textfield_->text()));
    502   OnCaretBoundsChanged();
    503   SchedulePaint();
    504   textfield_->NotifyAccessibilityEvent(
    505       ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
    506 }
    507 
    508 void NativeTextfieldViews::AppendText(const string16& text) {
    509   if (text.empty())
    510     return;
    511   model_->Append(GetTextForDisplay(text));
    512   OnCaretBoundsChanged();
    513   SchedulePaint();
    514 }
    515 
    516 void NativeTextfieldViews::InsertOrReplaceText(const string16& text) {
    517   if (text.empty())
    518     return;
    519   model_->InsertText(text);
    520   OnCaretBoundsChanged();
    521   SchedulePaint();
    522 }
    523 
    524 base::i18n::TextDirection NativeTextfieldViews::GetTextDirection() const {
    525   return GetRenderText()->GetTextDirection();
    526 }
    527 
    528 string16 NativeTextfieldViews::GetSelectedText() const {
    529   return model_->GetSelectedText();
    530 }
    531 
    532 void NativeTextfieldViews::SelectAll(bool reversed) {
    533   model_->SelectAll(reversed);
    534   OnCaretBoundsChanged();
    535   SchedulePaint();
    536 }
    537 
    538 void NativeTextfieldViews::ClearSelection() {
    539   model_->ClearSelection();
    540   OnCaretBoundsChanged();
    541   SchedulePaint();
    542 }
    543 
    544 void NativeTextfieldViews::UpdateBorder() {
    545   // By default, if a caller calls Textfield::RemoveBorder() and does not set
    546   // any explicit margins, they should get zero margins.  But also call
    547   // UpdateXXXMargins() so we respect any explicitly-set margins.
    548   //
    549   // NOTE: If someday Textfield supports toggling |draw_border_| back on, we'll
    550   // need to update this conditional to set the insets to their default values.
    551   if (!textfield_->draw_border())
    552     text_border_->SetInsets(0, 0, 0, 0);
    553   UpdateHorizontalMargins();
    554   UpdateVerticalMargins();
    555 }
    556 
    557 void NativeTextfieldViews::UpdateTextColor() {
    558   SetColor(textfield_->GetTextColor());
    559 }
    560 
    561 void NativeTextfieldViews::UpdateBackgroundColor() {
    562   const SkColor color = textfield_->GetBackgroundColor();
    563   set_background(Background::CreateSolidBackground(color));
    564   GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
    565   SchedulePaint();
    566 }
    567 
    568 void NativeTextfieldViews::UpdateReadOnly() {
    569   OnTextInputTypeChanged();
    570 }
    571 
    572 void NativeTextfieldViews::UpdateFont() {
    573   GetRenderText()->SetFontList(textfield_->font_list());
    574   OnCaretBoundsChanged();
    575 }
    576 
    577 void NativeTextfieldViews::UpdateIsObscured() {
    578   GetRenderText()->SetObscured(textfield_->IsObscured());
    579   OnCaretBoundsChanged();
    580   SchedulePaint();
    581   OnTextInputTypeChanged();
    582 }
    583 
    584 void NativeTextfieldViews::UpdateEnabled() {
    585   SetEnabled(textfield_->enabled());
    586   SchedulePaint();
    587   OnTextInputTypeChanged();
    588 }
    589 
    590 gfx::Insets NativeTextfieldViews::CalculateInsets() {
    591   return GetInsets();
    592 }
    593 
    594 void NativeTextfieldViews::UpdateHorizontalMargins() {
    595   int left, right;
    596   if (!textfield_->GetHorizontalMargins(&left, &right))
    597     return;
    598   gfx::Insets inset = GetInsets();
    599   text_border_->SetInsets(inset.top(), left, inset.bottom(), right);
    600   OnBoundsChanged(GetBounds());
    601 }
    602 
    603 void NativeTextfieldViews::UpdateVerticalMargins() {
    604   int top, bottom;
    605   if (!textfield_->GetVerticalMargins(&top, &bottom))
    606     return;
    607   gfx::Insets inset = GetInsets();
    608   text_border_->SetInsets(top, inset.left(), bottom, inset.right());
    609   OnBoundsChanged(GetBounds());
    610 }
    611 
    612 bool NativeTextfieldViews::SetFocus() {
    613   return false;
    614 }
    615 
    616 View* NativeTextfieldViews::GetView() {
    617   return this;
    618 }
    619 
    620 gfx::NativeView NativeTextfieldViews::GetTestingHandle() const {
    621   NOTREACHED();
    622   return NULL;
    623 }
    624 
    625 bool NativeTextfieldViews::IsIMEComposing() const {
    626   return model_->HasCompositionText();
    627 }
    628 
    629 gfx::Range NativeTextfieldViews::GetSelectedRange() const {
    630   return GetRenderText()->selection();
    631 }
    632 
    633 void NativeTextfieldViews::SelectRange(const gfx::Range& range) {
    634   model_->SelectRange(range);
    635   OnCaretBoundsChanged();
    636   SchedulePaint();
    637   textfield_->NotifyAccessibilityEvent(
    638       ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
    639 }
    640 
    641 gfx::SelectionModel NativeTextfieldViews::GetSelectionModel() const {
    642   return GetRenderText()->selection_model();
    643 }
    644 
    645 void NativeTextfieldViews::SelectSelectionModel(
    646     const gfx::SelectionModel& sel) {
    647   model_->SelectSelectionModel(sel);
    648   OnCaretBoundsChanged();
    649   SchedulePaint();
    650 }
    651 
    652 size_t NativeTextfieldViews::GetCursorPosition() const {
    653   return model_->GetCursorPosition();
    654 }
    655 
    656 bool NativeTextfieldViews::GetCursorEnabled() const {
    657   return GetRenderText()->cursor_enabled();
    658 }
    659 
    660 void NativeTextfieldViews::SetCursorEnabled(bool enabled) {
    661   GetRenderText()->SetCursorEnabled(enabled);
    662 }
    663 
    664 bool NativeTextfieldViews::HandleKeyPressed(const ui::KeyEvent& e) {
    665   TextfieldController* controller = textfield_->GetController();
    666   bool handled = false;
    667   if (controller)
    668     handled = controller->HandleKeyEvent(textfield_, e);
    669   touch_selection_controller_.reset();
    670   return handled || HandleKeyEvent(e);
    671 }
    672 
    673 bool NativeTextfieldViews::HandleKeyReleased(const ui::KeyEvent& e) {
    674   return false;  // crbug.com/127520
    675 }
    676 
    677 void NativeTextfieldViews::HandleFocus() {
    678   GetRenderText()->set_focused(true);
    679   is_cursor_visible_ = true;
    680   SchedulePaint();
    681   GetInputMethod()->OnFocus();
    682   OnCaretBoundsChanged();
    683 
    684   const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
    685   if (caret_blink_ms != 0) {
    686     base::MessageLoop::current()->PostDelayedTask(
    687         FROM_HERE,
    688         base::Bind(&NativeTextfieldViews::UpdateCursor,
    689                    cursor_timer_.GetWeakPtr()),
    690         base::TimeDelta::FromMilliseconds(caret_blink_ms));
    691   }
    692 }
    693 
    694 void NativeTextfieldViews::HandleBlur() {
    695   GetRenderText()->set_focused(false);
    696   GetInputMethod()->OnBlur();
    697   // Stop blinking cursor.
    698   cursor_timer_.InvalidateWeakPtrs();
    699   if (is_cursor_visible_) {
    700     is_cursor_visible_ = false;
    701     RepaintCursor();
    702   }
    703 
    704   touch_selection_controller_.reset();
    705 }
    706 
    707 ui::TextInputClient* NativeTextfieldViews::GetTextInputClient() {
    708   return textfield_->read_only() ? NULL : this;
    709 }
    710 
    711 void NativeTextfieldViews::ClearEditHistory() {
    712   model_->ClearEditHistory();
    713 }
    714 
    715 int NativeTextfieldViews::GetFontHeight() {
    716   return GetRenderText()->font_list().GetHeight();
    717 }
    718 
    719 int NativeTextfieldViews::GetTextfieldBaseline() const {
    720   return GetRenderText()->GetBaseline();
    721 }
    722 
    723 int NativeTextfieldViews::GetWidthNeededForText() const {
    724   return GetRenderText()->GetContentWidth() + GetInsets().width();
    725 }
    726 
    727 void NativeTextfieldViews::ExecuteTextCommand(int command_id) {
    728   ExecuteCommand(command_id, 0);
    729 }
    730 
    731 bool NativeTextfieldViews::HasTextBeingDragged() {
    732   return initiating_drag_;
    733 }
    734 
    735 gfx::Point NativeTextfieldViews::GetContextMenuLocation() {
    736   return GetCaretBounds().bottom_right();
    737 }
    738 
    739 /////////////////////////////////////////////////////////////////
    740 // NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides:
    741 
    742 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const {
    743   return true;
    744 }
    745 
    746 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const {
    747   TextfieldController* controller = textfield_->GetController();
    748   if (controller && controller->HandlesCommand(command_id))
    749     return controller->IsCommandIdEnabled(command_id);
    750 
    751   bool editable = !textfield_->read_only();
    752   string16 result;
    753   switch (command_id) {
    754     case IDS_APP_UNDO:
    755       return editable && model_->CanUndo();
    756     case IDS_APP_CUT:
    757       return editable && model_->HasSelection() && !textfield_->IsObscured();
    758     case IDS_APP_COPY:
    759       return model_->HasSelection() && !textfield_->IsObscured();
    760     case IDS_APP_PASTE:
    761       ui::Clipboard::GetForCurrentThread()->ReadText(
    762           ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
    763       return editable && !result.empty();
    764     case IDS_APP_DELETE:
    765       return editable && model_->HasSelection();
    766     case IDS_APP_SELECT_ALL:
    767       return !model_->GetText().empty();
    768     default:
    769       return controller->IsCommandIdEnabled(command_id);
    770   }
    771 }
    772 
    773 bool NativeTextfieldViews::GetAcceleratorForCommandId(int command_id,
    774     ui::Accelerator* accelerator) {
    775   return false;
    776 }
    777 
    778 bool NativeTextfieldViews::IsItemForCommandIdDynamic(int command_id) const {
    779   const TextfieldController* controller = textfield_->GetController();
    780   return controller && controller->IsItemForCommandIdDynamic(command_id);
    781 }
    782 
    783 string16 NativeTextfieldViews::GetLabelForCommandId(int command_id) const {
    784   const TextfieldController* controller = textfield_->GetController();
    785   return controller ? controller->GetLabelForCommandId(command_id) : string16();
    786 }
    787 
    788 void NativeTextfieldViews::ExecuteCommand(int command_id, int event_flags) {
    789   touch_selection_controller_.reset();
    790   if (!IsCommandIdEnabled(command_id))
    791     return;
    792 
    793   TextfieldController* controller = textfield_->GetController();
    794   if (controller && controller->HandlesCommand(command_id)) {
    795     controller->ExecuteCommand(command_id, 0);
    796   } else {
    797     bool text_changed = false;
    798     switch (command_id) {
    799       case IDS_APP_UNDO:
    800         OnBeforeUserAction();
    801         text_changed = model_->Undo();
    802         UpdateAfterChange(text_changed, text_changed);
    803         OnAfterUserAction();
    804         break;
    805       case IDS_APP_CUT:
    806         OnBeforeUserAction();
    807         text_changed = Cut();
    808         UpdateAfterChange(text_changed, text_changed);
    809         OnAfterUserAction();
    810         break;
    811       case IDS_APP_COPY:
    812         OnBeforeUserAction();
    813         Copy();
    814         OnAfterUserAction();
    815         break;
    816       case IDS_APP_PASTE:
    817         OnBeforeUserAction();
    818         text_changed = Paste();
    819         UpdateAfterChange(text_changed, text_changed);
    820         OnAfterUserAction();
    821         break;
    822       case IDS_APP_DELETE:
    823         OnBeforeUserAction();
    824         text_changed = model_->Delete();
    825         UpdateAfterChange(text_changed, text_changed);
    826         OnAfterUserAction();
    827         break;
    828       case IDS_APP_SELECT_ALL:
    829         OnBeforeUserAction();
    830         SelectAll(false);
    831         UpdateAfterChange(false, true);
    832         OnAfterUserAction();
    833         break;
    834       default:
    835         controller->ExecuteCommand(command_id, 0);
    836         break;
    837     }
    838   }
    839 }
    840 
    841 void NativeTextfieldViews::SetColor(SkColor value) {
    842   GetRenderText()->SetColor(value);
    843   SchedulePaint();
    844 }
    845 
    846 void NativeTextfieldViews::ApplyColor(SkColor value, const gfx::Range& range) {
    847   GetRenderText()->ApplyColor(value, range);
    848   SchedulePaint();
    849 }
    850 
    851 void NativeTextfieldViews::SetStyle(gfx::TextStyle style, bool value) {
    852   GetRenderText()->SetStyle(style, value);
    853   SchedulePaint();
    854 }
    855 
    856 void NativeTextfieldViews::ApplyStyle(gfx::TextStyle style,
    857                                       bool value,
    858                                       const gfx::Range& range) {
    859   GetRenderText()->ApplyStyle(style, value, range);
    860   SchedulePaint();
    861 }
    862 
    863 void NativeTextfieldViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
    864   // Set the RenderText display area.
    865   gfx::Insets insets = GetInsets();
    866   gfx::Rect display_rect(insets.left(),
    867                          insets.top(),
    868                          width() - insets.width(),
    869                          height() - insets.height());
    870   GetRenderText()->SetDisplayRect(display_rect);
    871   OnCaretBoundsChanged();
    872 }
    873 
    874 ///////////////////////////////////////////////////////////////////////////////
    875 // NativeTextfieldViews, ui::TextInputClient implementation, private:
    876 
    877 void NativeTextfieldViews::SetCompositionText(
    878     const ui::CompositionText& composition) {
    879   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
    880     return;
    881 
    882   OnBeforeUserAction();
    883   skip_input_method_cancel_composition_ = true;
    884   model_->SetCompositionText(composition);
    885   skip_input_method_cancel_composition_ = false;
    886   UpdateAfterChange(true, true);
    887   OnAfterUserAction();
    888 }
    889 
    890 void NativeTextfieldViews::ConfirmCompositionText() {
    891   if (!model_->HasCompositionText())
    892     return;
    893 
    894   OnBeforeUserAction();
    895   skip_input_method_cancel_composition_ = true;
    896   model_->ConfirmCompositionText();
    897   skip_input_method_cancel_composition_ = false;
    898   UpdateAfterChange(true, true);
    899   OnAfterUserAction();
    900 }
    901 
    902 void NativeTextfieldViews::ClearCompositionText() {
    903   if (!model_->HasCompositionText())
    904     return;
    905 
    906   OnBeforeUserAction();
    907   skip_input_method_cancel_composition_ = true;
    908   model_->CancelCompositionText();
    909   skip_input_method_cancel_composition_ = false;
    910   UpdateAfterChange(true, true);
    911   OnAfterUserAction();
    912 }
    913 
    914 void NativeTextfieldViews::InsertText(const string16& text) {
    915   // TODO(suzhe): Filter invalid characters.
    916   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty())
    917     return;
    918 
    919   OnBeforeUserAction();
    920   skip_input_method_cancel_composition_ = true;
    921   if (GetRenderText()->insert_mode())
    922     model_->InsertText(GetTextForDisplay(text));
    923   else
    924     model_->ReplaceText(GetTextForDisplay(text));
    925   skip_input_method_cancel_composition_ = false;
    926   UpdateAfterChange(true, true);
    927   OnAfterUserAction();
    928 }
    929 
    930 void NativeTextfieldViews::InsertChar(char16 ch, int flags) {
    931   if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE ||
    932       !ShouldInsertChar(ch, flags)) {
    933     return;
    934   }
    935 
    936   OnBeforeUserAction();
    937   skip_input_method_cancel_composition_ = true;
    938   if (GetRenderText()->insert_mode())
    939     model_->InsertChar(ch);
    940   else
    941     model_->ReplaceChar(ch);
    942   skip_input_method_cancel_composition_ = false;
    943 
    944   model_->SetText(GetTextForDisplay(GetText()));
    945 
    946   UpdateAfterChange(true, true);
    947   OnAfterUserAction();
    948 
    949   if (textfield_->IsObscured()) {
    950     const base::TimeDelta& reveal_duration =
    951         textfield_->obscured_reveal_duration();
    952     if (reveal_duration != base::TimeDelta()) {
    953       const size_t change_offset = model_->GetCursorPosition();
    954       DCHECK_GT(change_offset, 0u);
    955       RevealObscuredChar(change_offset - 1, reveal_duration);
    956     }
    957   }
    958 }
    959 
    960 gfx::NativeWindow NativeTextfieldViews::GetAttachedWindow() const {
    961   // Imagine the following hierarchy.
    962   //   [NativeWidget A] - FocusManager
    963   //     [View]
    964   //     [NativeWidget B]
    965   //       [View]
    966   //         [View X]
    967   // An important thing is that [NativeWidget A] owns Win32 input focus even
    968   // when [View X] is logically focused by FocusManager. As a result, an Win32
    969   // IME may want to interact with the native view of [NativeWidget A] rather
    970   // than that of [NativeWidget B]. This is why we need to call
    971   // GetTopLevelWidget() here.
    972   return GetWidget()->GetTopLevelWidget()->GetNativeView();
    973 }
    974 
    975 ui::TextInputType NativeTextfieldViews::GetTextInputType() const {
    976   return textfield_->GetTextInputType();
    977 }
    978 
    979 ui::TextInputMode NativeTextfieldViews::GetTextInputMode() const {
    980   return ui::TEXT_INPUT_MODE_DEFAULT;
    981 }
    982 
    983 bool NativeTextfieldViews::CanComposeInline() const {
    984   return true;
    985 }
    986 
    987 gfx::Rect NativeTextfieldViews::GetCaretBounds() const {
    988   // TextInputClient::GetCaretBounds is expected to return a value in screen
    989   // coordinates.
    990   gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
    991   ConvertRectToScreen(this, &rect);
    992   return rect;
    993 }
    994 
    995 bool NativeTextfieldViews::GetCompositionCharacterBounds(
    996     uint32 index,
    997     gfx::Rect* rect) const {
    998   DCHECK(rect);
    999   if (!HasCompositionText())
   1000     return false;
   1001   const gfx::Range& composition_range = GetRenderText()->GetCompositionRange();
   1002   DCHECK(!composition_range.is_empty());
   1003 
   1004   size_t text_index = composition_range.start() + index;
   1005   if (composition_range.end() <= text_index)
   1006     return false;
   1007   if (!GetRenderText()->IsCursorablePosition(text_index)) {
   1008     text_index = GetRenderText()->IndexOfAdjacentGrapheme(
   1009         text_index, gfx::CURSOR_BACKWARD);
   1010   }
   1011   if (text_index < composition_range.start())
   1012     return false;
   1013   const gfx::SelectionModel caret(text_index, gfx::CURSOR_BACKWARD);
   1014   *rect = GetRenderText()->GetCursorBounds(caret, false);
   1015   ConvertRectToScreen(this, rect);
   1016 
   1017   return true;
   1018 }
   1019 
   1020 bool NativeTextfieldViews::HasCompositionText() const {
   1021   return model_->HasCompositionText();
   1022 }
   1023 
   1024 bool NativeTextfieldViews::GetTextRange(gfx::Range* range) const {
   1025   if (!ImeEditingAllowed())
   1026     return false;
   1027 
   1028   model_->GetTextRange(range);
   1029   return true;
   1030 }
   1031 
   1032 bool NativeTextfieldViews::GetCompositionTextRange(gfx::Range* range) const {
   1033   if (!ImeEditingAllowed())
   1034     return false;
   1035 
   1036   model_->GetCompositionTextRange(range);
   1037   return true;
   1038 }
   1039 
   1040 bool NativeTextfieldViews::GetSelectionRange(gfx::Range* range) const {
   1041   if (!ImeEditingAllowed())
   1042     return false;
   1043   *range = GetSelectedRange();
   1044   return true;
   1045 }
   1046 
   1047 bool NativeTextfieldViews::SetSelectionRange(const gfx::Range& range) {
   1048   if (!ImeEditingAllowed() || !range.IsValid())
   1049     return false;
   1050 
   1051   OnBeforeUserAction();
   1052   SelectRange(range);
   1053   OnAfterUserAction();
   1054   return true;
   1055 }
   1056 
   1057 bool NativeTextfieldViews::DeleteRange(const gfx::Range& range) {
   1058   if (!ImeEditingAllowed() || range.is_empty())
   1059     return false;
   1060 
   1061   OnBeforeUserAction();
   1062   model_->SelectRange(range);
   1063   if (model_->HasSelection()) {
   1064     model_->DeleteSelection();
   1065     UpdateAfterChange(true, true);
   1066   }
   1067   OnAfterUserAction();
   1068   return true;
   1069 }
   1070 
   1071 bool NativeTextfieldViews::GetTextFromRange(
   1072     const gfx::Range& range,
   1073     string16* text) const {
   1074   if (!ImeEditingAllowed() || !range.IsValid())
   1075     return false;
   1076 
   1077   gfx::Range text_range;
   1078   if (!GetTextRange(&text_range) || !text_range.Contains(range))
   1079     return false;
   1080 
   1081   *text = model_->GetTextFromRange(range);
   1082   return true;
   1083 }
   1084 
   1085 void NativeTextfieldViews::OnInputMethodChanged() {
   1086   // TODO(msw): NOTIMPLEMENTED(); see http://crbug.com/140402
   1087 }
   1088 
   1089 bool NativeTextfieldViews::ChangeTextDirectionAndLayoutAlignment(
   1090     base::i18n::TextDirection direction) {
   1091   // Restore text directionality mode when the indicated direction matches the
   1092   // current forced mode; otherwise, force the mode indicated. This helps users
   1093   // manage BiDi text layout without getting stuck in forced LTR or RTL modes.
   1094   const gfx::DirectionalityMode mode = direction == base::i18n::RIGHT_TO_LEFT ?
   1095       gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
   1096   if (mode == GetRenderText()->directionality_mode())
   1097     GetRenderText()->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
   1098   else
   1099     GetRenderText()->SetDirectionalityMode(mode);
   1100   SchedulePaint();
   1101   return true;
   1102 }
   1103 
   1104 void NativeTextfieldViews::ExtendSelectionAndDelete(
   1105     size_t before,
   1106     size_t after) {
   1107   gfx::Range range = GetSelectedRange();
   1108   DCHECK_GE(range.start(), before);
   1109 
   1110   range.set_start(range.start() - before);
   1111   range.set_end(range.end() + after);
   1112   gfx::Range text_range;
   1113   if (GetTextRange(&text_range) && text_range.Contains(range))
   1114     DeleteRange(range);
   1115 }
   1116 
   1117 void NativeTextfieldViews::EnsureCaretInRect(const gfx::Rect& rect) {
   1118 }
   1119 
   1120 void NativeTextfieldViews::OnCandidateWindowShown() {
   1121 }
   1122 
   1123 void NativeTextfieldViews::OnCandidateWindowUpdated() {
   1124 }
   1125 
   1126 void NativeTextfieldViews::OnCandidateWindowHidden() {
   1127 }
   1128 
   1129 void NativeTextfieldViews::OnCompositionTextConfirmedOrCleared() {
   1130   if (skip_input_method_cancel_composition_)
   1131     return;
   1132   DCHECK(textfield_->GetInputMethod());
   1133   textfield_->GetInputMethod()->CancelComposition(textfield_);
   1134 }
   1135 
   1136 gfx::RenderText* NativeTextfieldViews::GetRenderText() const {
   1137   return model_->render_text();
   1138 }
   1139 
   1140 string16 NativeTextfieldViews::GetTextForDisplay(const string16& text) {
   1141   return textfield_->style() & Textfield::STYLE_LOWERCASE ?
   1142       base::i18n::ToLower(text) : text;
   1143 }
   1144 
   1145 void NativeTextfieldViews::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
   1146   UpdateTextColor();
   1147   UpdateBackgroundColor();
   1148   gfx::RenderText* render_text = GetRenderText();
   1149   render_text->set_cursor_color(textfield_->GetTextColor());
   1150   render_text->set_selection_color(theme->GetSystemColor(
   1151       ui::NativeTheme::kColorId_TextfieldSelectionColor));
   1152   render_text->set_selection_background_focused_color(theme->GetSystemColor(
   1153       ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused));
   1154 }
   1155 
   1156 void NativeTextfieldViews::UpdateCursor() {
   1157   const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
   1158   is_cursor_visible_ = !is_cursor_visible_ || (caret_blink_ms == 0);
   1159   RepaintCursor();
   1160   if (caret_blink_ms != 0) {
   1161     base::MessageLoop::current()->PostDelayedTask(
   1162         FROM_HERE,
   1163         base::Bind(&NativeTextfieldViews::UpdateCursor,
   1164                    cursor_timer_.GetWeakPtr()),
   1165         base::TimeDelta::FromMilliseconds(caret_blink_ms));
   1166   }
   1167 }
   1168 
   1169 void NativeTextfieldViews::RepaintCursor() {
   1170   gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
   1171   r.Inset(-1, -1, -1, -1);
   1172   SchedulePaintInRect(r);
   1173 }
   1174 
   1175 void NativeTextfieldViews::PaintTextAndCursor(gfx::Canvas* canvas) {
   1176   TRACE_EVENT0("views", "NativeTextfieldViews::PaintTextAndCursor");
   1177   canvas->Save();
   1178   GetRenderText()->set_cursor_visible(!is_drop_cursor_visible_ &&
   1179       is_cursor_visible_ && !model_->HasSelection());
   1180   // Draw the text, cursor, and selection.
   1181   GetRenderText()->Draw(canvas);
   1182 
   1183   // Draw the detached drop cursor that marks where the text will be dropped.
   1184   if (is_drop_cursor_visible_)
   1185     GetRenderText()->DrawCursor(canvas, drop_cursor_position_);
   1186 
   1187   // Draw placeholder text if needed.
   1188   if (model_->GetText().empty() &&
   1189       !textfield_->GetPlaceholderText().empty()) {
   1190     canvas->DrawStringInt(
   1191         textfield_->GetPlaceholderText(),
   1192         GetRenderText()->GetPrimaryFont(),
   1193         textfield_->placeholder_text_color(),
   1194         GetRenderText()->display_rect());
   1195   }
   1196   canvas->Restore();
   1197 }
   1198 
   1199 bool NativeTextfieldViews::HandleKeyEvent(const ui::KeyEvent& key_event) {
   1200   // TODO(oshima): Refactor and consolidate with ExecuteCommand.
   1201   if (key_event.type() == ui::ET_KEY_PRESSED) {
   1202     ui::KeyboardCode key_code = key_event.key_code();
   1203     if (key_code == ui::VKEY_TAB || key_event.IsUnicodeKeyCode())
   1204       return false;
   1205 
   1206     OnBeforeUserAction();
   1207     const bool editable = !textfield_->read_only();
   1208     const bool readable = !textfield_->IsObscured();
   1209     const bool shift = key_event.IsShiftDown();
   1210     const bool control = key_event.IsControlDown();
   1211     const bool alt = key_event.IsAltDown() || key_event.IsAltGrDown();
   1212     bool text_changed = false;
   1213     bool cursor_changed = false;
   1214     switch (key_code) {
   1215       case ui::VKEY_Z:
   1216         if (control && !shift && !alt && editable)
   1217           cursor_changed = text_changed = model_->Undo();
   1218         else if (control && shift && !alt && editable)
   1219           cursor_changed = text_changed = model_->Redo();
   1220         break;
   1221       case ui::VKEY_Y:
   1222         if (control && !alt && editable)
   1223           cursor_changed = text_changed = model_->Redo();
   1224         break;
   1225       case ui::VKEY_A:
   1226         if (control && !alt) {
   1227           model_->SelectAll(false);
   1228           cursor_changed = true;
   1229         }
   1230         break;
   1231       case ui::VKEY_X:
   1232         if (control && !alt && editable && readable)
   1233           cursor_changed = text_changed = Cut();
   1234         break;
   1235       case ui::VKEY_C:
   1236         if (control && !alt && readable)
   1237           Copy();
   1238         break;
   1239       case ui::VKEY_V:
   1240         if (control && !alt && editable)
   1241           cursor_changed = text_changed = Paste();
   1242         break;
   1243       case ui::VKEY_RIGHT:
   1244       case ui::VKEY_LEFT: {
   1245         // We should ignore the alt-left/right keys because alt key doesn't make
   1246         // any special effects for them and they can be shortcut keys such like
   1247         // forward/back of the browser history.
   1248         if (alt)
   1249           break;
   1250         const gfx::Range selection_range = GetSelectedRange();
   1251         model_->MoveCursor(
   1252             control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
   1253             (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
   1254             shift);
   1255         cursor_changed = GetSelectedRange() != selection_range;
   1256         break;
   1257       }
   1258       case ui::VKEY_END:
   1259       case ui::VKEY_HOME:
   1260         if ((key_code == ui::VKEY_HOME) ==
   1261             (GetRenderText()->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
   1262           model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
   1263         else
   1264           model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
   1265         cursor_changed = true;
   1266         break;
   1267       case ui::VKEY_BACK:
   1268       case ui::VKEY_DELETE:
   1269         if (!editable)
   1270           break;
   1271         if (!model_->HasSelection()) {
   1272           gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
   1273               gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
   1274           if (shift && control) {
   1275             // If both shift and control are pressed, then erase up to the
   1276             // beginning/end of the buffer in ChromeOS. In windows, do nothing.
   1277 #if defined(OS_WIN)
   1278             break;
   1279 #else
   1280             model_->MoveCursor(gfx::LINE_BREAK, direction, true);
   1281 #endif
   1282           } else if (control) {
   1283             // If only control is pressed, then erase the previous/next word.
   1284             model_->MoveCursor(gfx::WORD_BREAK, direction, true);
   1285           }
   1286         }
   1287         if (key_code == ui::VKEY_BACK)
   1288           model_->Backspace();
   1289         else if (shift && model_->HasSelection() && readable)
   1290           Cut();
   1291         else
   1292           model_->Delete();
   1293 
   1294         // Consume backspace and delete keys even if the edit did nothing. This
   1295         // prevents potential unintended side-effects of further event handling.
   1296         text_changed = true;
   1297         break;
   1298       case ui::VKEY_INSERT:
   1299         if (control && !shift && readable)
   1300           Copy();
   1301         else if (shift && !control && editable)
   1302           cursor_changed = text_changed = Paste();
   1303         break;
   1304       default:
   1305         break;
   1306     }
   1307 
   1308     // We must have input method in order to support text input.
   1309     DCHECK(textfield_->GetInputMethod());
   1310 
   1311     UpdateAfterChange(text_changed, cursor_changed);
   1312     OnAfterUserAction();
   1313     return (text_changed || cursor_changed);
   1314   }
   1315   return false;
   1316 }
   1317 
   1318 bool NativeTextfieldViews::MoveCursorTo(const gfx::Point& point, bool select) {
   1319   if (!model_->MoveCursorTo(point, select))
   1320     return false;
   1321   OnCaretBoundsChanged();
   1322   return true;
   1323 }
   1324 
   1325 void NativeTextfieldViews::PropagateTextChange() {
   1326   textfield_->SyncText();
   1327 }
   1328 
   1329 void NativeTextfieldViews::UpdateAfterChange(bool text_changed,
   1330                                              bool cursor_changed) {
   1331   if (text_changed) {
   1332     PropagateTextChange();
   1333     textfield_->NotifyAccessibilityEvent(
   1334         ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
   1335   }
   1336   if (cursor_changed) {
   1337     is_cursor_visible_ = true;
   1338     RepaintCursor();
   1339     if (!text_changed) {
   1340       // TEXT_CHANGED implies SELECTION_CHANGED, so we only need to fire
   1341       // this if only the selection changed.
   1342       textfield_->NotifyAccessibilityEvent(
   1343           ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
   1344     }
   1345   }
   1346   if (text_changed || cursor_changed) {
   1347     OnCaretBoundsChanged();
   1348     SchedulePaint();
   1349   }
   1350 }
   1351 
   1352 void NativeTextfieldViews::UpdateContextMenu() {
   1353   if (!context_menu_contents_.get()) {
   1354     context_menu_contents_.reset(new ui::SimpleMenuModel(this));
   1355     context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
   1356     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   1357     context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
   1358     context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
   1359     context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
   1360     context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
   1361     context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   1362     context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
   1363                                                 IDS_APP_SELECT_ALL);
   1364     TextfieldController* controller = textfield_->GetController();
   1365     if (controller)
   1366       controller->UpdateContextMenu(context_menu_contents_.get());
   1367 
   1368     context_menu_delegate_.reset(
   1369         new views::MenuModelAdapter(context_menu_contents_.get()));
   1370     context_menu_runner_.reset(
   1371         new MenuRunner(new views::MenuItemView(context_menu_delegate_.get())));
   1372   }
   1373 
   1374   context_menu_delegate_->BuildMenu(context_menu_runner_->GetMenu());
   1375 }
   1376 
   1377 void NativeTextfieldViews::OnTextInputTypeChanged() {
   1378   // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
   1379   if (textfield_->GetInputMethod())
   1380     textfield_->GetInputMethod()->OnTextInputTypeChanged(textfield_);
   1381 }
   1382 
   1383 void NativeTextfieldViews::OnCaretBoundsChanged() {
   1384   // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
   1385   if (textfield_->GetInputMethod())
   1386     textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_);
   1387 
   1388   // Notify selection controller
   1389   if (touch_selection_controller_.get())
   1390     touch_selection_controller_->SelectionChanged();
   1391 }
   1392 
   1393 void NativeTextfieldViews::OnBeforeUserAction() {
   1394   TextfieldController* controller = textfield_->GetController();
   1395   if (controller)
   1396     controller->OnBeforeUserAction(textfield_);
   1397 }
   1398 
   1399 void NativeTextfieldViews::OnAfterUserAction() {
   1400   TextfieldController* controller = textfield_->GetController();
   1401   if (controller)
   1402     controller->OnAfterUserAction(textfield_);
   1403 }
   1404 
   1405 bool NativeTextfieldViews::Cut() {
   1406   if (!textfield_->read_only() && !textfield_->IsObscured() && model_->Cut()) {
   1407     TextfieldController* controller = textfield_->GetController();
   1408     if (controller)
   1409       controller->OnAfterCutOrCopy();
   1410     return true;
   1411   }
   1412   return false;
   1413 }
   1414 
   1415 bool NativeTextfieldViews::Copy() {
   1416   if (!textfield_->IsObscured() && model_->Copy()) {
   1417     TextfieldController* controller = textfield_->GetController();
   1418     if (controller)
   1419       controller->OnAfterCutOrCopy();
   1420     return true;
   1421   }
   1422   return false;
   1423 }
   1424 
   1425 bool NativeTextfieldViews::Paste() {
   1426   if (textfield_->read_only())
   1427     return false;
   1428 
   1429   const string16 original_text = GetText();
   1430   const bool success = model_->Paste();
   1431 
   1432   if (success) {
   1433     // As Paste is handled in model_->Paste(), the RenderText may contain
   1434     // upper case characters. This is not consistent with other places
   1435     // which keeps RenderText only containing lower case characters.
   1436     string16 new_text = GetTextForDisplay(GetText());
   1437     model_->SetText(new_text);
   1438 
   1439     TextfieldController* controller = textfield_->GetController();
   1440     if (controller)
   1441       controller->OnAfterPaste();
   1442   }
   1443   return success;
   1444 }
   1445 
   1446 void NativeTextfieldViews::TrackMouseClicks(const ui::MouseEvent& event) {
   1447   if (event.IsOnlyLeftMouseButton()) {
   1448     base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
   1449     if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
   1450         !ExceededDragThresholdFromLastClickLocation(event)) {
   1451       // Upon clicking after a triple click, the count should go back to double
   1452       // click and alternate between double and triple. This assignment maps
   1453       // 0 to 1, 1 to 2, 2 to 1.
   1454       aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
   1455     } else {
   1456       aggregated_clicks_ = 0;
   1457     }
   1458     last_click_time_ = event.time_stamp();
   1459     last_click_location_ = event.location();
   1460   }
   1461 }
   1462 
   1463 void NativeTextfieldViews::HandleMousePressEvent(const ui::MouseEvent& event) {
   1464   if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())
   1465     textfield_->RequestFocus();
   1466 
   1467   if (!event.IsOnlyLeftMouseButton())
   1468     return;
   1469 
   1470   initiating_drag_ = false;
   1471   bool can_drag = true;
   1472 
   1473   switch (aggregated_clicks_) {
   1474     case 0:
   1475       if (can_drag && GetRenderText()->IsPointInSelection(event.location()))
   1476         initiating_drag_ = true;
   1477       else
   1478         MoveCursorTo(event.location(), event.IsShiftDown());
   1479       break;
   1480     case 1:
   1481       MoveCursorTo(event.location(), false);
   1482       model_->SelectWord();
   1483       double_click_word_ = GetRenderText()->selection();
   1484       OnCaretBoundsChanged();
   1485       break;
   1486     case 2:
   1487       model_->SelectAll(false);
   1488       OnCaretBoundsChanged();
   1489       break;
   1490     default:
   1491       NOTREACHED();
   1492   }
   1493   SchedulePaint();
   1494 }
   1495 
   1496 bool NativeTextfieldViews::ImeEditingAllowed() const {
   1497   // We don't allow the input method to retrieve or delete content from a
   1498   // password field.
   1499   ui::TextInputType t = GetTextInputType();
   1500   return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
   1501 }
   1502 
   1503 // static
   1504 bool NativeTextfieldViews::ShouldInsertChar(char16 ch, int flags) {
   1505   // Filter out all control characters, including tab and new line characters,
   1506   // and all characters with Alt modifier. But we need to allow characters with
   1507   // AltGr modifier.
   1508   // On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a different
   1509   // flag that we don't care about.
   1510   return ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
   1511       (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN;
   1512 }
   1513 
   1514 void NativeTextfieldViews::CreateTouchSelectionControllerAndNotifyIt() {
   1515   if (!touch_selection_controller_) {
   1516     touch_selection_controller_.reset(
   1517         ui::TouchSelectionController::create(this));
   1518   }
   1519   if (touch_selection_controller_)
   1520     touch_selection_controller_->SelectionChanged();
   1521 }
   1522 
   1523 void NativeTextfieldViews::PlatformGestureEventHandling(
   1524     const ui::GestureEvent* event) {
   1525 #if defined(OS_WIN) && defined(USE_AURA)
   1526   if (event->type() == ui::ET_GESTURE_TAP && !textfield_->read_only())
   1527     base::win::DisplayVirtualKeyboard();
   1528 #endif
   1529 }
   1530 
   1531 void NativeTextfieldViews::RevealObscuredChar(int index,
   1532                                               const base::TimeDelta& duration) {
   1533   GetRenderText()->SetObscuredRevealIndex(index);
   1534   SchedulePaint();
   1535 
   1536   if (index != -1) {
   1537     obscured_reveal_timer_.Start(
   1538         FROM_HERE,
   1539         duration,
   1540         base::Bind(&NativeTextfieldViews::RevealObscuredChar,
   1541                    base::Unretained(this), -1, base::TimeDelta()));
   1542   }
   1543 }
   1544 
   1545 }  // namespace views
   1546