OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "views/controls/textfield/native_textfield_views.h" | 5 #include "views/controls/textfield/native_textfield_views.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 } | 193 } |
194 | 194 |
195 int NativeTextfieldViews::OnPerformDrop(const DropTargetEvent& event) { | 195 int NativeTextfieldViews::OnPerformDrop(const DropTargetEvent& event) { |
196 DCHECK(CanDrop(event.data())); | 196 DCHECK(CanDrop(event.data())); |
197 DCHECK(!initiating_drag_ || | 197 DCHECK(!initiating_drag_ || |
198 !GetRenderText()->IsPointInSelection(event.location())); | 198 !GetRenderText()->IsPointInSelection(event.location())); |
199 OnBeforeUserAction(); | 199 OnBeforeUserAction(); |
200 skip_input_method_cancel_composition_ = true; | 200 skip_input_method_cancel_composition_ = true; |
201 | 201 |
202 // TODO(msw): Remove final reference to FindCursorPosition. | 202 // TODO(msw): Remove final reference to FindCursorPosition. |
203 size_t drop_destination = | 203 gfx::SelectionModel drop_destination = |
204 GetRenderText()->FindCursorPosition(event.location()); | 204 GetRenderText()->FindCursorPosition(event.location()); |
205 string16 text; | 205 string16 text; |
206 event.data().GetString(&text); | 206 event.data().GetString(&text); |
207 | 207 |
208 // We'll delete the current selection for a drag and drop within this view. | 208 // We'll delete the current selection for a drag and drop within this view. |
209 bool move = initiating_drag_ && !event.IsControlDown() && | 209 bool move = initiating_drag_ && !event.IsControlDown() && |
210 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; | 210 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; |
211 if (move) { | 211 if (move) { |
212 ui::Range selected_range; | 212 ui::Range selected_range; |
213 model_->GetSelectedRange(&selected_range); | 213 model_->GetSelectedRange(&selected_range); |
214 // Adjust the drop destination if it is on or after the current selection. | 214 // Adjust the drop destination if it is on or after the current selection. |
215 if (selected_range.GetMax() <= drop_destination) | 215 if (selected_range.GetMax() <= drop_destination.selection_end()) |
216 drop_destination -= selected_range.length(); | 216 drop_destination.set_selection_end( |
217 else if (selected_range.GetMin() <= drop_destination) | 217 drop_destination.selection_end() - selected_range.length()); |
218 drop_destination = selected_range.GetMin(); | 218 else if (selected_range.GetMin() <= drop_destination.selection_end()) |
219 model_->DeleteSelectionAndInsertTextAt(text, drop_destination); | 219 drop_destination.set_selection_end(selected_range.GetMin()); |
220 model_->DeleteSelectionAndInsertTextAt(text, | |
221 drop_destination.selection_end()); | |
220 } else { | 222 } else { |
221 model_->MoveCursorTo(drop_destination, false); | 223 drop_destination.set_selection_start(drop_destination.selection_end()); |
224 model_->MoveCursorTo(drop_destination); | |
222 // Drop always inserts text even if the textfield is not in insert mode. | 225 // Drop always inserts text even if the textfield is not in insert mode. |
223 model_->InsertText(text); | 226 model_->InsertText(text); |
224 } | 227 } |
225 skip_input_method_cancel_composition_ = false; | 228 skip_input_method_cancel_composition_ = false; |
226 UpdateAfterChange(true, true); | 229 UpdateAfterChange(true, true); |
227 OnAfterUserAction(); | 230 OnAfterUserAction(); |
228 return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY; | 231 return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY; |
229 } | 232 } |
230 | 233 |
231 void NativeTextfieldViews::OnDragDone() { | 234 void NativeTextfieldViews::OnDragDone() { |
(...skipping 12 matching lines...) Expand all Loading... | |
244 void NativeTextfieldViews::OnFocus() { | 247 void NativeTextfieldViews::OnFocus() { |
245 NOTREACHED(); | 248 NOTREACHED(); |
246 } | 249 } |
247 | 250 |
248 void NativeTextfieldViews::OnBlur() { | 251 void NativeTextfieldViews::OnBlur() { |
249 NOTREACHED(); | 252 NOTREACHED(); |
250 } | 253 } |
251 | 254 |
252 void NativeTextfieldViews::SelectRect(const gfx::Point& start, | 255 void NativeTextfieldViews::SelectRect(const gfx::Point& start, |
253 const gfx::Point& end) { | 256 const gfx::Point& end) { |
254 size_t start_pos = GetRenderText()->FindCursorPosition(start); | 257 gfx::SelectionModel start_pos = GetRenderText()->FindCursorPosition(start); |
255 size_t end_pos = GetRenderText()->FindCursorPosition(end); | 258 gfx::SelectionModel end_pos = GetRenderText()->FindCursorPosition(end); |
256 SetSelectionRange(ui::Range(start_pos, end_pos)); | 259 |
260 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) | |
msw
2011/08/03 23:44:38
Move this check above the start_pos and end_pos ca
xji
2011/08/04 06:26:50
Done.
| |
261 return; | |
262 if (start_pos.selection_end() == end_pos.selection_end() | |
msw
2011/08/03 23:44:38
OK, I think we can trust the results of FindCursor
xji
2011/08/04 06:26:50
Ah, you are right here.
I suspect that we will ne
| |
263 && start_pos.selection_end() == std::numeric_limits<size_t>::max()) | |
264 return; | |
265 | |
266 OnBeforeUserAction(); | |
267 // Merge selection models of "start_pos" and "end_pos" so that | |
268 // selection start is the value from "start_pos", while selection end, | |
269 // caret position, and caret placement are values from "end_pos". | |
270 gfx::SelectionModel sel(end_pos); | |
271 sel.set_selection_start(start_pos.selection_start()); | |
272 model_->SelectSelectionModel(sel); | |
273 | |
274 OnCaretBoundsChanged(); | |
275 SchedulePaint(); | |
276 OnAfterUserAction(); | |
257 } | 277 } |
258 | 278 |
259 gfx::NativeCursor NativeTextfieldViews::GetCursor(const MouseEvent& event) { | 279 gfx::NativeCursor NativeTextfieldViews::GetCursor(const MouseEvent& event) { |
260 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 280 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); |
261 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 281 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
262 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 282 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
263 #if defined(OS_WIN) | 283 #if defined(OS_WIN) |
264 static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM); | 284 static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM); |
265 static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW); | 285 static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW); |
266 return text_cursor ? ibeam : arrow; | 286 return text_cursor ? ibeam : arrow; |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 | 685 |
666 ui::TextInputType NativeTextfieldViews::GetTextInputType() { | 686 ui::TextInputType NativeTextfieldViews::GetTextInputType() { |
667 if (textfield_->read_only() || !textfield_->IsEnabled()) | 687 if (textfield_->read_only() || !textfield_->IsEnabled()) |
668 return ui::TEXT_INPUT_TYPE_NONE; | 688 return ui::TEXT_INPUT_TYPE_NONE; |
669 else if (textfield_->IsPassword()) | 689 else if (textfield_->IsPassword()) |
670 return ui::TEXT_INPUT_TYPE_PASSWORD; | 690 return ui::TEXT_INPUT_TYPE_PASSWORD; |
671 return ui::TEXT_INPUT_TYPE_TEXT; | 691 return ui::TEXT_INPUT_TYPE_TEXT; |
672 } | 692 } |
673 | 693 |
674 gfx::Rect NativeTextfieldViews::GetCaretBounds() { | 694 gfx::Rect NativeTextfieldViews::GetCaretBounds() { |
675 gfx::RenderText* render_text = GetRenderText(); | 695 return GetRenderText()->CursorBounds(); |
676 return render_text->GetCursorBounds(render_text->GetCursorPosition(), | |
677 render_text->insert_mode()); | |
678 } | 696 } |
679 | 697 |
680 bool NativeTextfieldViews::HasCompositionText() { | 698 bool NativeTextfieldViews::HasCompositionText() { |
681 return model_->HasCompositionText(); | 699 return model_->HasCompositionText(); |
682 } | 700 } |
683 | 701 |
684 bool NativeTextfieldViews::GetTextRange(ui::Range* range) { | 702 bool NativeTextfieldViews::GetTextRange(ui::Range* range) { |
685 // We don't allow the input method to retrieve or delete content from a | 703 // We don't allow the input method to retrieve or delete content from a |
686 // password box. | 704 // password box. |
687 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT) | 705 if (GetTextInputType() != ui::TEXT_INPUT_TYPE_TEXT) |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
959 | 977 |
960 void NativeTextfieldViews::OnCaretBoundsChanged() { | 978 void NativeTextfieldViews::OnCaretBoundsChanged() { |
961 // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320. | 979 // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320. |
962 if (textfield_->GetInputMethod()) | 980 if (textfield_->GetInputMethod()) |
963 textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_); | 981 textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_); |
964 | 982 |
965 // Notify selection controller | 983 // Notify selection controller |
966 if (!touch_selection_controller_.get()) | 984 if (!touch_selection_controller_.get()) |
967 return; | 985 return; |
968 gfx::RenderText* render_text = GetRenderText(); | 986 gfx::RenderText* render_text = GetRenderText(); |
969 ui::Range range = render_text->GetSelection(); | 987 const gfx::SelectionModel& sel = render_text->selection_model(); |
970 gfx::Rect start_cursor = render_text->GetCursorBounds(range.start(), false); | 988 gfx::SelectionModel start_sel(sel.selection_start(), sel.selection_start(), |
971 gfx::Rect end_cursor = render_text->GetCursorBounds(range.end(), false); | 989 sel.selection_start(), gfx::SelectionModel::LEADING); |
990 gfx::Rect start_cursor = render_text->GetCursorBounds(start_sel, false); | |
991 gfx::Rect end_cursor = render_text->GetCursorBounds(sel, false); | |
972 gfx::Rect display_rect = render_text->display_rect(); | 992 gfx::Rect display_rect = render_text->display_rect(); |
973 int total_offset_x = display_rect.x() + render_text->display_offset().x(); | 993 int total_offset_x = display_rect.x() + render_text->display_offset().x(); |
974 int total_offset_y = display_rect.y() + render_text->display_offset().y() + | 994 int total_offset_y = display_rect.y() + render_text->display_offset().y() + |
975 (display_rect.height() - start_cursor.height()) / 2; | 995 (display_rect.height() - start_cursor.height()) / 2; |
976 gfx::Point start(start_cursor.x() + total_offset_x, | 996 gfx::Point start(start_cursor.x() + total_offset_x, |
977 start_cursor.bottom() + total_offset_y); | 997 start_cursor.bottom() + total_offset_y); |
978 gfx::Point end(end_cursor.x() + total_offset_x, | 998 gfx::Point end(end_cursor.x() + total_offset_x, |
979 end_cursor.bottom() + total_offset_y); | 999 end_cursor.bottom() + total_offset_y); |
980 touch_selection_controller_->SelectionChanged(start, end); | 1000 touch_selection_controller_->SelectionChanged(start, end); |
981 } | 1001 } |
(...skipping 28 matching lines...) Expand all Loading... | |
1010 // Filter out all control characters, including tab and new line characters, | 1030 // Filter out all control characters, including tab and new line characters, |
1011 // and all characters with Alt modifier. But we need to allow characters with | 1031 // and all characters with Alt modifier. But we need to allow characters with |
1012 // AltGr modifier. | 1032 // AltGr modifier. |
1013 // On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a different | 1033 // On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a different |
1014 // flag that we don't care about. | 1034 // flag that we don't care about. |
1015 return ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) && | 1035 return ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) && |
1016 (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN; | 1036 (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN; |
1017 } | 1037 } |
1018 | 1038 |
1019 } // namespace views | 1039 } // namespace views |
OLD | NEW |