Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/views/omnibox/omnibox_view_views.h" | 5 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/app/chrome_command_ids.h" | 10 #include "chrome/app/chrome_command_ids.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 // kAutocompleteEditFontPixelSizeInPopup. They should be changed accordingly | 95 // kAutocompleteEditFontPixelSizeInPopup. They should be changed accordingly |
| 96 // if font size for autocomplete edit (in popup) change. | 96 // if font size for autocomplete edit (in popup) change. |
| 97 const int kAutocompleteVerticalMargin = 1; | 97 const int kAutocompleteVerticalMargin = 1; |
| 98 const int kAutocompleteVerticalMarginInPopup = 2; | 98 const int kAutocompleteVerticalMarginInPopup = 2; |
| 99 | 99 |
| 100 int GetEditFontPixelSize(bool popup_window_mode) { | 100 int GetEditFontPixelSize(bool popup_window_mode) { |
| 101 return popup_window_mode ? kAutocompleteEditFontPixelSizeInPopup : | 101 return popup_window_mode ? kAutocompleteEditFontPixelSizeInPopup : |
| 102 kAutocompleteEditFontPixelSize; | 102 kAutocompleteEditFontPixelSize; |
| 103 } | 103 } |
| 104 | 104 |
| 105 // Copies |selected_text| as text to the primary clipboard. | |
| 106 void DoCopyText(const string16& selected_text) { | |
| 107 ui::ScopedClipboardWriter scw(ui::Clipboard::GetForCurrentThread(), | |
| 108 ui::Clipboard::BUFFER_STANDARD); | |
| 109 scw.WriteText(selected_text); | |
| 110 } | |
| 111 | |
| 112 // This will write |url| and |text| to the clipboard as a well-formed URL. | 105 // This will write |url| and |text| to the clipboard as a well-formed URL. |
| 113 void DoCopyURL(const GURL& url, const string16& text) { | 106 void DoCopyURL(const GURL& url, const string16& text) { |
| 114 BookmarkNodeData data; | 107 BookmarkNodeData data; |
| 115 data.ReadFromTuple(url, text); | 108 data.ReadFromTuple(url, text); |
| 116 data.WriteToClipboard(NULL); | 109 data.WriteToClipboard(NULL); |
| 117 } | 110 } |
| 118 | 111 |
| 119 } // namespace | 112 } // namespace |
| 120 | 113 |
| 121 // Textfield for autocomplete that intercepts events that are necessary | |
| 122 // for OmniboxViewViews. | |
| 123 class OmniboxViewViews::AutocompleteTextfield : public views::Textfield { | |
| 124 public: | |
| 125 AutocompleteTextfield(OmniboxViewViews* omnibox_view, | |
| 126 LocationBarView* location_bar_view) | |
| 127 : views::Textfield(views::Textfield::STYLE_DEFAULT), | |
| 128 omnibox_view_(omnibox_view), | |
| 129 location_bar_view_(location_bar_view) { | |
| 130 DCHECK(omnibox_view_); | |
| 131 RemoveBorder(); | |
| 132 set_id(VIEW_ID_OMNIBOX); | |
| 133 } | |
| 134 | |
| 135 // views::View implementation | |
| 136 virtual void OnFocus() OVERRIDE { | |
| 137 views::Textfield::OnFocus(); | |
| 138 omnibox_view_->HandleFocusIn(); | |
| 139 } | |
| 140 | |
| 141 virtual void OnBlur() OVERRIDE { | |
| 142 views::Textfield::OnBlur(); | |
| 143 omnibox_view_->HandleFocusOut(); | |
| 144 } | |
| 145 | |
| 146 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE { | |
| 147 // Use our own implementation of paste. See OnPaste() for details. | |
| 148 if (!read_only() && event.IsControlDown() && | |
| 149 event.key_code() == ui::VKEY_V) { | |
| 150 omnibox_view_->OnBeforePossibleChange(); | |
| 151 omnibox_view_->OnPaste(); | |
| 152 omnibox_view_->OnAfterPossibleChange(); | |
| 153 return true; | |
| 154 } | |
| 155 bool handled = views::Textfield::OnKeyPressed(event); | |
| 156 return omnibox_view_->HandleAfterKeyEvent(event, handled) || handled; | |
| 157 } | |
| 158 | |
| 159 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE { | |
| 160 return omnibox_view_->HandleKeyReleaseEvent(event); | |
| 161 } | |
| 162 | |
| 163 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { | |
| 164 // Pass through the views::Textfield's return value; we don't need to | |
| 165 // override its behavior. | |
| 166 bool result = views::Textfield::OnMousePressed(event); | |
| 167 omnibox_view_->HandleMousePressEvent(event); | |
| 168 return result; | |
| 169 } | |
| 170 | |
| 171 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { | |
| 172 bool result = views::Textfield::OnMouseDragged(event); | |
| 173 omnibox_view_->HandleMouseDragEvent(event); | |
| 174 return result; | |
| 175 } | |
| 176 | |
| 177 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { | |
| 178 views::Textfield::OnMouseReleased(event); | |
| 179 omnibox_view_->HandleMouseReleaseEvent(event); | |
| 180 } | |
| 181 | |
| 182 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | |
| 183 views::Textfield::OnGestureEvent(event); | |
| 184 omnibox_view_->HandleGestureEvent(*event); | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 OmniboxViewViews* omnibox_view_; | |
| 189 LocationBarView* location_bar_view_; | |
| 190 | |
| 191 DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield); | |
| 192 }; | |
| 193 | |
| 194 // static | 114 // static |
| 195 const char OmniboxViewViews::kViewClassName[] = "BrowserOmniboxViewViews"; | 115 const char OmniboxViewViews::kViewClassName[] = "BrowserOmniboxViewViews"; |
| 196 | 116 |
| 197 OmniboxViewViews::OmniboxViewViews(OmniboxEditController* controller, | 117 OmniboxViewViews::OmniboxViewViews(OmniboxEditController* controller, |
| 198 ToolbarModel* toolbar_model, | 118 ToolbarModel* toolbar_model, |
| 199 Profile* profile, | 119 Profile* profile, |
| 200 CommandUpdater* command_updater, | 120 CommandUpdater* command_updater, |
| 201 bool popup_window_mode, | 121 bool popup_window_mode, |
| 202 LocationBarView* location_bar) | 122 LocationBarView* location_bar) |
| 203 : OmniboxView(profile, controller, toolbar_model, command_updater), | 123 : OmniboxView(profile, controller, toolbar_model, command_updater), |
| 204 textfield_(NULL), | |
| 205 popup_window_mode_(popup_window_mode), | 124 popup_window_mode_(popup_window_mode), |
| 206 security_level_(ToolbarModel::NONE), | 125 security_level_(ToolbarModel::NONE), |
| 207 ime_composing_before_change_(false), | 126 ime_composing_before_change_(false), |
| 208 delete_at_end_pressed_(false), | 127 delete_at_end_pressed_(false), |
| 209 location_bar_view_(location_bar), | 128 location_bar_view_(location_bar), |
| 210 ime_candidate_window_open_(false), | 129 ime_candidate_window_open_(false), |
| 211 select_all_on_mouse_release_(false), | 130 select_all_on_mouse_release_(false), |
| 212 select_all_on_gesture_tap_(false) { | 131 select_all_on_gesture_tap_(false) { |
| 132 RemoveBorder(); | |
| 133 set_id(VIEW_ID_OMNIBOX); | |
| 213 } | 134 } |
| 214 | 135 |
| 215 OmniboxViewViews::~OmniboxViewViews() { | 136 OmniboxViewViews::~OmniboxViewViews() { |
| 216 #if defined(OS_CHROMEOS) | 137 #if defined(OS_CHROMEOS) |
| 217 chromeos::input_method::GetInputMethodManager()-> | 138 chromeos::input_method::GetInputMethodManager()-> |
| 218 RemoveCandidateWindowObserver(this); | 139 RemoveCandidateWindowObserver(this); |
| 219 #endif | 140 #endif |
| 220 | 141 |
| 221 // Explicitly teardown members which have a reference to us. Just to be safe | 142 // Explicitly teardown members which have a reference to us. Just to be safe |
| 222 // we want them to be destroyed before destroying any other internal state. | 143 // we want them to be destroyed before destroying any other internal state. |
| 223 popup_view_.reset(); | 144 popup_view_.reset(); |
| 224 } | 145 } |
| 225 | 146 |
| 226 //////////////////////////////////////////////////////////////////////////////// | 147 //////////////////////////////////////////////////////////////////////////////// |
| 227 // OmniboxViewViews public: | 148 // OmniboxViewViews public: |
| 228 | 149 |
| 229 void OmniboxViewViews::Init() { | 150 void OmniboxViewViews::Init() { |
| 230 // The height of the text view is going to change based on the font used. We | 151 // The height of the text view is going to change based on the font used. We |
| 231 // don't want to stretch the height, and we want it vertically centered. | 152 // don't want to stretch the height, and we want it vertically centered. |
| 232 // TODO(oshima): make sure the above happens with views. | 153 // TODO(oshima): make sure the above happens with views. |
| 233 textfield_ = new AutocompleteTextfield(this, location_bar_view_); | 154 SetController(this); |
| 234 textfield_->SetController(this); | 155 SetTextInputType(ui::TEXT_INPUT_TYPE_URL); |
| 235 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL); | 156 SetBackgroundColor(location_bar_view_->GetColor( |
| 236 textfield_->SetBackgroundColor(location_bar_view_->GetColor( | |
| 237 ToolbarModel::NONE, LocationBarView::BACKGROUND)); | 157 ToolbarModel::NONE, LocationBarView::BACKGROUND)); |
| 238 | 158 |
| 239 if (popup_window_mode_) | 159 if (popup_window_mode_) |
| 240 textfield_->SetReadOnly(true); | 160 SetReadOnly(true); |
| 241 | 161 |
| 242 const int font_size = GetEditFontPixelSize(popup_window_mode_); | 162 const int font_size = GetEditFontPixelSize(popup_window_mode_); |
| 243 const int old_size = textfield_->font().GetFontSize(); | 163 if (font_size != font().GetFontSize()) |
| 244 if (font_size != old_size) | 164 SetFont(font().DeriveFont(font_size - font().GetFontSize())); |
| 245 textfield_->SetFont(textfield_->font().DeriveFont(font_size - old_size)); | |
| 246 | 165 |
| 247 // Create popup view using the same font as |textfield_|'s. | 166 // Initialize the popup view using the same font. |
| 248 popup_view_.reset( | 167 popup_view_.reset(OmniboxPopupContentsView::Create( |
| 249 OmniboxPopupContentsView::Create( | 168 font(), this, model(), location_bar_view_)); |
| 250 textfield_->font(), this, model(), location_bar_view_)); | |
| 251 | 169 |
| 252 // A null-border to zero out the focused border on textfield. | 170 // A null-border to zero out the focused border on textfield. |
| 253 const int vertical_margin = !popup_window_mode_ ? | 171 const int vertical_margin = !popup_window_mode_ ? |
| 254 kAutocompleteVerticalMargin : kAutocompleteVerticalMarginInPopup; | 172 kAutocompleteVerticalMargin : kAutocompleteVerticalMarginInPopup; |
| 255 set_border(views::Border::CreateEmptyBorder(vertical_margin, 0, | 173 set_border(views::Border::CreateEmptyBorder(vertical_margin, 0, |
| 256 vertical_margin, 0)); | 174 vertical_margin, 0)); |
| 257 #if defined(OS_CHROMEOS) | 175 #if defined(OS_CHROMEOS) |
| 258 chromeos::input_method::GetInputMethodManager()-> | 176 chromeos::input_method::GetInputMethodManager()-> |
| 259 AddCandidateWindowObserver(this); | 177 AddCandidateWindowObserver(this); |
| 260 #endif | 178 #endif |
| 261 } | 179 } |
| 262 | 180 |
| 263 gfx::Font OmniboxViewViews::GetFont() { | 181 gfx::Font OmniboxViewViews::GetFont() { |
| 264 return textfield_->font(); | 182 return font(); |
| 265 } | 183 } |
| 266 | 184 |
| 267 int OmniboxViewViews::WidthOfTextAfterCursor() { | 185 int OmniboxViewViews::WidthOfTextAfterCursor() { |
| 268 ui::Range sel; | 186 ui::Range sel; |
| 269 textfield_->GetSelectedRange(&sel); | 187 GetSelectedRange(&sel); |
| 270 // See comments in LocationBarView::Layout as to why this uses -1. | 188 // See comments in LocationBarView::Layout as to why this uses -1. |
| 271 const int start = std::max(0, static_cast<int>(sel.end()) - 1); | 189 const int start = std::max(0, static_cast<int>(sel.end()) - 1); |
| 272 // TODO: add horizontal margin. | 190 // TODO: add horizontal margin. |
| 273 return textfield_->font().GetStringWidth(GetText().substr(start)); | 191 return font().GetStringWidth(text().substr(start)); |
| 274 } | 192 } |
| 275 | 193 |
| 276 bool OmniboxViewViews::HandleAfterKeyEvent(const ui::KeyEvent& event, | 194 //////////////////////////////////////////////////////////////////////////////// |
| 277 bool handled) { | 195 // OmniboxViewViews, views::View implementation: |
|
Peter Kasting
2013/02/18 18:57:47
Nit: Again, we don't directly override View.
Pers
msw
2013/02/18 20:58:21
I'm not a big fan either, but I fixed it rather th
| |
| 196 | |
| 197 std::string OmniboxViewViews::GetClassName() const { | |
| 198 return kViewClassName; | |
| 199 } | |
| 200 | |
| 201 void OmniboxViewViews::OnGestureEvent(ui::GestureEvent* event) { | |
| 202 views::Textfield::OnGestureEvent(event); | |
| 203 if (!HasFocus() && event->type() == ui::ET_GESTURE_TAP_DOWN) { | |
| 204 select_all_on_gesture_tap_ = true; | |
| 205 return; | |
| 206 } | |
| 207 if (select_all_on_gesture_tap_ && event->type() == ui::ET_GESTURE_TAP) | |
| 208 SelectAll(false); | |
| 209 select_all_on_gesture_tap_ = false; | |
| 210 } | |
| 211 | |
| 212 void OmniboxViewViews::GetAccessibleState(ui::AccessibleViewState* state) { | |
| 213 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION); | |
| 214 } | |
| 215 | |
| 216 void OmniboxViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) { | |
| 217 if (popup_view_->IsOpen()) | |
| 218 popup_view_->UpdatePopupAppearance(); | |
| 219 } | |
| 220 | |
| 221 bool OmniboxViewViews::OnMousePressed(const ui::MouseEvent& event) { | |
| 222 const bool result = views::Textfield::OnMousePressed(event); | |
| 223 select_all_on_mouse_release_ = | |
| 224 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) && | |
| 225 (!HasFocus() || (model()->focus_state() == OMNIBOX_FOCUS_INVISIBLE)); | |
| 226 // Restore caret visibility whenever the user clicks in the omnibox in a way | |
| 227 // that would give it focus. We must handle this case separately here because | |
| 228 // if the omnibox currently has invisible focus, the mouse event won't trigger | |
| 229 // either SetFocus() or OmniboxEditModel::OnSetFocus(). | |
| 230 if (select_all_on_mouse_release_) | |
| 231 model()->SetCaretVisibility(true); | |
| 232 return result; | |
| 233 } | |
| 234 | |
| 235 bool OmniboxViewViews::OnMouseDragged(const ui::MouseEvent& event) { | |
| 236 select_all_on_mouse_release_ = false; | |
| 237 return views::Textfield::OnMouseDragged(event); | |
| 238 } | |
| 239 | |
| 240 void OmniboxViewViews::OnMouseReleased(const ui::MouseEvent& event) { | |
| 241 views::Textfield::OnMouseReleased(event); | |
| 242 if ((event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) && | |
| 243 select_all_on_mouse_release_) { | |
| 244 // Select all in the reverse direction so as not to scroll the caret | |
| 245 // into view and shift the contents jarringly. | |
| 246 SelectAll(true); | |
| 247 } | |
| 248 select_all_on_mouse_release_ = false; | |
| 249 } | |
| 250 | |
| 251 bool OmniboxViewViews::OnKeyPressed(const ui::KeyEvent& event) { | |
| 252 // Use our own implementation of paste. See OnPaste() for details. | |
| 253 if (!read_only() && event.IsControlDown() && | |
| 254 event.key_code() == ui::VKEY_V) { | |
| 255 OnBeforePossibleChange(); | |
| 256 OnPaste(); | |
| 257 OnAfterPossibleChange(); | |
| 258 return true; | |
| 259 } | |
| 260 bool handled = views::Textfield::OnKeyPressed(event); | |
| 261 | |
| 278 if (event.key_code() == ui::VKEY_RETURN) { | 262 if (event.key_code() == ui::VKEY_RETURN) { |
| 279 bool alt_held = event.IsAltDown(); | 263 bool alt_held = event.IsAltDown(); |
| 280 model()->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); | 264 model()->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false); |
| 281 handled = true; | 265 handled = true; |
| 282 } else if (!handled && event.key_code() == ui::VKEY_ESCAPE) { | 266 } else if (!handled && event.key_code() == ui::VKEY_ESCAPE) { |
| 283 // We can handle the Escape key if textfield did not handle it. | 267 // Let the model handle the Escape key or continue its propagation. |
| 284 // If it's not handled by us, then we need to propagate it up to the parent | |
| 285 // widgets, so that Escape accelerator can still work. | |
| 286 handled = model()->OnEscapeKeyPressed(); | 268 handled = model()->OnEscapeKeyPressed(); |
| 287 } else if (event.key_code() == ui::VKEY_CONTROL) { | 269 } else if (event.key_code() == ui::VKEY_CONTROL) { |
| 288 // Omnibox2 can switch its contents while pressing a control key. To switch | 270 // Omnibox2 can switch its contents while pressing a control key. To switch |
| 289 // the contents of omnibox2, we notify the OmniboxEditModel class when the | 271 // the contents of omnibox2, we notify the OmniboxEditModel class when the |
| 290 // control-key state is changed. | 272 // control-key state is changed. |
| 291 model()->OnControlKeyChanged(true); | 273 model()->OnControlKeyChanged(true); |
| 292 } else if (!handled && event.key_code() == ui::VKEY_DELETE && | 274 } else if (!handled && event.key_code() == ui::VKEY_DELETE && |
| 293 event.IsShiftDown()) { | 275 event.IsShiftDown()) { |
| 294 // If shift+del didn't change the text, we let this delete an entry from | 276 // If shift+del didn't change the text, we let this delete an entry from |
| 295 // the popup. We can't check to see if the IME handled it because even if | 277 // the popup. We can't check to see if the IME handled it because even if |
| 296 // nothing is selected, the IME or the TextView still report handling it. | 278 // nothing is selected, the IME or the TextView still report handling it. |
| 297 if (model()->popup_model()->IsOpen()) | 279 if (model()->popup_model()->IsOpen()) |
| 298 model()->popup_model()->TryDeletingCurrentItem(); | 280 model()->popup_model()->TryDeletingCurrentItem(); |
| 299 } else if (!handled && event.key_code() == ui::VKEY_UP) { | 281 } else if (!handled && event.key_code() == ui::VKEY_UP) { |
| 300 model()->OnUpOrDownKeyPressed(-1); | 282 model()->OnUpOrDownKeyPressed(-1); |
| 301 handled = true; | 283 handled = true; |
| 302 } else if (!handled && event.key_code() == ui::VKEY_DOWN) { | 284 } else if (!handled && event.key_code() == ui::VKEY_DOWN) { |
| 303 model()->OnUpOrDownKeyPressed(1); | 285 model()->OnUpOrDownKeyPressed(1); |
| 304 handled = true; | 286 handled = true; |
| 305 } else if (!handled && | 287 } else if (!handled && |
| 306 event.key_code() == ui::VKEY_TAB && | 288 event.key_code() == ui::VKEY_TAB && |
| 307 !event.IsControlDown()) { | 289 !event.IsControlDown()) { |
| 308 if (model()->is_keyword_hint() && !event.IsShiftDown()) { | 290 if (model()->is_keyword_hint() && !event.IsShiftDown()) { |
| 309 handled = model()->AcceptKeyword(); | 291 handled = model()->AcceptKeyword(); |
| 310 } else if (model()->popup_model()->IsOpen()) { | 292 } else if (model()->popup_model()->IsOpen()) { |
| 311 if (event.IsShiftDown() && | 293 if (event.IsShiftDown() && |
| 312 model()->popup_model()->selected_line_state() == | 294 model()->popup_model()->selected_line_state() == |
| 313 OmniboxPopupModel::KEYWORD) { | 295 OmniboxPopupModel::KEYWORD) { |
| 314 model()->ClearKeyword(GetText()); | 296 model()->ClearKeyword(text()); |
| 315 } else { | 297 } else { |
| 316 model()->OnUpOrDownKeyPressed(event.IsShiftDown() ? -1 : 1); | 298 model()->OnUpOrDownKeyPressed(event.IsShiftDown() ? -1 : 1); |
| 317 } | 299 } |
| 318 handled = true; | 300 handled = true; |
| 319 } else { | 301 } else { |
| 320 string16::size_type start = 0; | 302 string16::size_type start = 0; |
| 321 string16::size_type end = 0; | 303 string16::size_type end = 0; |
| 322 size_t length = GetTextLength(); | 304 const size_t length = text().length(); |
| 323 GetSelectionBounds(&start, &end); | 305 GetSelectionBounds(&start, &end); |
| 324 if (start != end || start < length) { | 306 if (start != end || start < length) { |
| 325 OnBeforePossibleChange(); | 307 OnBeforePossibleChange(); |
| 326 textfield_->SelectRange(ui::Range(length, length)); | 308 SelectRange(ui::Range(length, length)); |
| 327 OnAfterPossibleChange(); | 309 OnAfterPossibleChange(); |
| 328 handled = true; | 310 handled = true; |
| 329 } | 311 } |
| 330 | 312 |
| 331 // TODO(Oshima): handle instant | 313 // TODO(msw|oshima): Handle Instant. |
| 332 } | 314 } |
| 333 } | 315 } |
| 334 // TODO(oshima): page up & down | 316 // TODO(msw|oshima): Handle page up and page down. |
| 335 | 317 |
| 336 return handled; | 318 return handled; |
| 337 } | 319 } |
| 338 | 320 |
| 339 bool OmniboxViewViews::HandleKeyReleaseEvent(const ui::KeyEvent& event) { | 321 bool OmniboxViewViews::OnKeyReleased(const ui::KeyEvent& event) { |
| 340 // Omnibox2 can switch its contents while pressing a control key. To switch | 322 // Omnibox2 can switch its contents while pressing a control key. To switch |
| 341 // the contents of omnibox2, we notify the OmniboxEditModel class when the | 323 // the contents of omnibox2, we notify the OmniboxEditModel class when the |
| 342 // control-key state is changed. | 324 // control-key state is changed. |
| 343 if (event.key_code() == ui::VKEY_CONTROL) { | 325 if (event.key_code() == ui::VKEY_CONTROL) { |
| 344 // TODO(oshima): investigate if we need to support keyboard with two | 326 // TODO(oshima): investigate if we need to support keyboard with two |
| 345 // controls. | 327 // controls. |
| 346 model()->OnControlKeyChanged(false); | 328 model()->OnControlKeyChanged(false); |
| 347 return true; | 329 return true; |
| 348 } | 330 } |
| 349 return false; | 331 return false; |
| 350 } | 332 } |
| 351 | 333 |
| 352 void OmniboxViewViews::HandleMousePressEvent(const ui::MouseEvent& event) { | 334 void OmniboxViewViews::OnFocus() { |
| 353 select_all_on_mouse_release_ = | 335 views::Textfield::OnFocus(); |
| 354 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) && | |
| 355 (!textfield_->HasFocus() || | |
| 356 (model()->focus_state() == OMNIBOX_FOCUS_INVISIBLE)); | |
| 357 // Restore caret visibility whenever the user clicks in the omnibox in a way | |
| 358 // that would give it focus. We must handle this case separately here because | |
| 359 // if the omnibox currently has invisible focus, the mouse event won't trigger | |
| 360 // either SetFocus() or OmniboxEditModel::OnSetFocus(). | |
| 361 if (select_all_on_mouse_release_) | |
| 362 model()->SetCaretVisibility(true); | |
| 363 } | |
| 364 | |
| 365 void OmniboxViewViews::HandleMouseDragEvent(const ui::MouseEvent& event) { | |
| 366 select_all_on_mouse_release_ = false; | |
| 367 } | |
| 368 | |
| 369 void OmniboxViewViews::HandleMouseReleaseEvent(const ui::MouseEvent& event) { | |
| 370 if ((event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) && | |
| 371 select_all_on_mouse_release_) { | |
| 372 // Select all in the reverse direction so as not to scroll the caret | |
| 373 // into view and shift the contents jarringly. | |
| 374 SelectAll(true); | |
| 375 } | |
| 376 select_all_on_mouse_release_ = false; | |
| 377 } | |
| 378 | |
| 379 void OmniboxViewViews::HandleGestureEvent(const ui::GestureEvent& event) { | |
| 380 if (!textfield_->HasFocus() && event.type() == ui::ET_GESTURE_TAP_DOWN) { | |
| 381 select_all_on_gesture_tap_ = true; | |
| 382 return; | |
| 383 } | |
| 384 if (select_all_on_gesture_tap_ && event.type() == ui::ET_GESTURE_TAP) | |
| 385 SelectAll(false); | |
| 386 select_all_on_gesture_tap_ = false; | |
| 387 } | |
| 388 | |
| 389 void OmniboxViewViews::HandleFocusIn() { | |
| 390 // TODO(oshima): Get control key state. | 336 // TODO(oshima): Get control key state. |
| 391 model()->OnSetFocus(false); | 337 model()->OnSetFocus(false); |
| 392 // Don't call controller()->OnSetFocus as this view has already | 338 // Don't call controller()->OnSetFocus as this view has already |
| 393 // acquired the focus. | 339 // acquired the focus. |
| 394 } | 340 } |
| 395 | 341 |
| 396 void OmniboxViewViews::HandleFocusOut() { | 342 void OmniboxViewViews::OnBlur() { |
| 343 views::Textfield::OnBlur(); | |
| 397 gfx::NativeView native_view = NULL; | 344 gfx::NativeView native_view = NULL; |
| 398 #if defined(USE_AURA) | 345 #if defined(USE_AURA) |
| 399 views::Widget* widget = GetWidget(); | 346 views::Widget* widget = GetWidget(); |
| 400 if (widget) { | 347 if (widget) { |
| 401 aura::client::FocusClient* client = | 348 aura::client::FocusClient* client = |
| 402 aura::client::GetFocusClient(widget->GetNativeView()); | 349 aura::client::GetFocusClient(widget->GetNativeView()); |
| 403 if (client) | 350 if (client) |
| 404 native_view = client->GetFocusedWindow(); | 351 native_view = client->GetFocusedWindow(); |
| 405 } | 352 } |
| 406 #endif | 353 #endif |
| 407 model()->OnWillKillFocus(native_view); | 354 model()->OnWillKillFocus(native_view); |
| 408 // Close the popup. | 355 // Close the popup. |
| 409 CloseOmniboxPopup(); | 356 CloseOmniboxPopup(); |
| 410 // Tell the model to reset itself. | 357 // Tell the model to reset itself. |
| 411 model()->OnKillFocus(); | 358 model()->OnKillFocus(); |
| 412 controller()->OnKillFocus(); | 359 controller()->OnKillFocus(); |
| 413 } | 360 } |
| 414 | 361 |
| 415 void OmniboxViewViews::SetLocationEntryFocusable(bool focusable) { | |
| 416 textfield_->set_focusable(focusable); | |
| 417 } | |
| 418 | |
| 419 bool OmniboxViewViews::IsLocationEntryFocusableInRootView() const { | |
| 420 return textfield_->IsFocusable(); | |
| 421 } | |
| 422 | |
| 423 //////////////////////////////////////////////////////////////////////////////// | |
| 424 // OmniboxViewViews, views::View implementation: | |
| 425 void OmniboxViewViews::Layout() { | |
| 426 gfx::Insets insets = GetInsets(); | |
| 427 textfield_->SetBounds(insets.left(), insets.top(), | |
| 428 width() - insets.width(), | |
| 429 height() - insets.height()); | |
| 430 } | |
| 431 | |
| 432 void OmniboxViewViews::GetAccessibleState(ui::AccessibleViewState* state) { | |
| 433 state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION); | |
| 434 } | |
| 435 | |
| 436 std::string OmniboxViewViews::GetClassName() const { | |
| 437 return kViewClassName; | |
| 438 } | |
| 439 | |
| 440 void OmniboxViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) { | |
| 441 if (popup_view_->IsOpen()) | |
| 442 popup_view_->UpdatePopupAppearance(); | |
| 443 } | |
| 444 | |
| 445 //////////////////////////////////////////////////////////////////////////////// | 362 //////////////////////////////////////////////////////////////////////////////// |
| 446 // OmniboxViewViews, OmniboxView implementation: | 363 // OmniboxViewViews, OmniboxView implementation: |
| 447 | 364 |
| 448 void OmniboxViewViews::SaveStateToTab(WebContents* tab) { | 365 void OmniboxViewViews::SaveStateToTab(WebContents* tab) { |
| 449 DCHECK(tab); | 366 DCHECK(tab); |
| 450 | 367 |
| 451 // We don't want to keep the IME status, so force quit the current | 368 // We don't want to keep the IME status, so force quit the current |
| 452 // session here. It may affect the selection status, so order is | 369 // session here. It may affect the selection status, so order is |
| 453 // also important. | 370 // also important. |
| 454 if (textfield_->IsIMEComposing()) { | 371 if (IsIMEComposing()) { |
| 455 textfield_->GetTextInputClient()->ConfirmCompositionText(); | 372 GetTextInputClient()->ConfirmCompositionText(); |
| 456 textfield_->GetInputMethod()->CancelComposition(textfield_); | 373 GetInputMethod()->CancelComposition(this); |
| 457 } | 374 } |
| 458 | 375 |
| 459 // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. | 376 // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. |
| 460 OmniboxEditModel::State model_state = model()->GetStateForTabSwitch(); | 377 OmniboxEditModel::State model_state = model()->GetStateForTabSwitch(); |
| 461 gfx::SelectionModel selection; | 378 gfx::SelectionModel selection; |
| 462 textfield_->GetSelectionModel(&selection); | 379 GetSelectionModel(&selection); |
| 463 tab->SetUserData( | 380 tab->SetUserData( |
| 464 kAutocompleteEditStateKey, | 381 kAutocompleteEditStateKey, |
| 465 new AutocompleteEditState(model_state, ViewState(selection))); | 382 new AutocompleteEditState(model_state, ViewState(selection))); |
| 466 } | 383 } |
| 467 | 384 |
| 468 void OmniboxViewViews::Update(const WebContents* contents) { | 385 void OmniboxViewViews::Update(const WebContents* contents) { |
| 469 // NOTE: We're getting the URL text here from the ToolbarModel. | 386 // NOTE: We're getting the URL text here from the ToolbarModel. |
| 470 bool visibly_changed_permanent_text = | 387 bool visibly_changed_permanent_text = |
| 471 model()->UpdatePermanentText(toolbar_model()->GetText(true)); | 388 model()->UpdatePermanentText(toolbar_model()->GetText(true)); |
| 472 ToolbarModel::SecurityLevel security_level = | 389 ToolbarModel::SecurityLevel security_level = |
| 473 toolbar_model()->GetSecurityLevel(); | 390 toolbar_model()->GetSecurityLevel(); |
| 474 bool changed_security_level = (security_level != security_level_); | 391 bool changed_security_level = (security_level != security_level_); |
| 475 security_level_ = security_level; | 392 security_level_ = security_level; |
| 476 | 393 |
| 477 // TODO(oshima): Copied from gtk implementation which is | 394 // TODO(oshima): Copied from gtk implementation which is |
| 478 // slightly different from WIN impl. Find out the correct implementation | 395 // slightly different from WIN impl. Find out the correct implementation |
| 479 // for views-implementation. | 396 // for views-implementation. |
| 480 if (contents) { | 397 if (contents) { |
| 481 RevertAll(); | 398 RevertAll(); |
| 482 const AutocompleteEditState* state = static_cast<AutocompleteEditState*>( | 399 const AutocompleteEditState* state = static_cast<AutocompleteEditState*>( |
| 483 contents->GetUserData(&kAutocompleteEditStateKey)); | 400 contents->GetUserData(&kAutocompleteEditStateKey)); |
| 484 if (state) { | 401 if (state) { |
| 485 model()->RestoreState(state->model_state); | 402 model()->RestoreState(state->model_state); |
| 486 | 403 |
| 487 // Move the marks for the cursor and the other end of the selection to | 404 // Move the marks for the cursor and the other end of the selection to |
| 488 // the previously-saved offsets (but preserve PRIMARY). | 405 // the previously-saved offsets (but preserve PRIMARY). |
| 489 textfield_->SelectSelectionModel(state->view_state.selection_model); | 406 SelectSelectionModel(state->view_state.selection_model); |
| 490 // We do not carry over the current edit history to another tab. | 407 // We do not carry over the current edit history to another tab. |
| 491 // TODO(oshima): consider saving/restoring edit history. | 408 // TODO(oshima): consider saving/restoring edit history. |
| 492 textfield_->ClearEditHistory(); | 409 ClearEditHistory(); |
| 493 } | 410 } |
| 494 } else if (visibly_changed_permanent_text) { | 411 } else if (visibly_changed_permanent_text) { |
| 495 RevertAll(); | 412 RevertAll(); |
| 496 } else if (changed_security_level) { | 413 } else if (changed_security_level) { |
| 497 EmphasizeURLComponents(); | 414 EmphasizeURLComponents(); |
| 498 } | 415 } |
| 499 } | 416 } |
| 500 | 417 |
| 501 string16 OmniboxViewViews::GetText() const { | 418 string16 OmniboxViewViews::GetText() const { |
| 502 // TODO(oshima): IME support | 419 // TODO(oshima): IME support |
| 503 return textfield_->text(); | 420 return text(); |
| 504 } | 421 } |
| 505 | 422 |
| 506 void OmniboxViewViews::SetWindowTextAndCaretPos(const string16& text, | 423 void OmniboxViewViews::SetWindowTextAndCaretPos(const string16& text, |
| 507 size_t caret_pos, | 424 size_t caret_pos, |
| 508 bool update_popup, | 425 bool update_popup, |
| 509 bool notify_text_changed) { | 426 bool notify_text_changed) { |
| 510 const ui::Range range(caret_pos, caret_pos); | 427 const ui::Range range(caret_pos, caret_pos); |
| 511 SetTextAndSelectedRange(text, range); | 428 SetTextAndSelectedRange(text, range); |
| 512 | 429 |
| 513 if (update_popup) | 430 if (update_popup) |
| 514 UpdatePopup(); | 431 UpdatePopup(); |
| 515 | 432 |
| 516 if (notify_text_changed) | 433 if (notify_text_changed) |
| 517 TextChanged(); | 434 TextChanged(); |
| 518 } | 435 } |
| 519 | 436 |
| 520 void OmniboxViewViews::SetForcedQuery() { | 437 void OmniboxViewViews::SetForcedQuery() { |
| 521 const string16 current_text(GetText()); | 438 const string16 current_text(text()); |
| 522 const size_t start = current_text.find_first_not_of(kWhitespaceUTF16); | 439 const size_t start = current_text.find_first_not_of(kWhitespaceUTF16); |
| 523 if (start == string16::npos || (current_text[start] != '?')) | 440 if (start == string16::npos || (current_text[start] != '?')) |
| 524 SetUserText(ASCIIToUTF16("?")); | 441 SetUserText(ASCIIToUTF16("?")); |
| 525 else | 442 else |
| 526 textfield_->SelectRange(ui::Range(current_text.size(), start + 1)); | 443 SelectRange(ui::Range(current_text.size(), start + 1)); |
| 527 } | 444 } |
| 528 | 445 |
| 529 bool OmniboxViewViews::IsSelectAll() const { | 446 bool OmniboxViewViews::IsSelectAll() const { |
| 530 // TODO(oshima): IME support. | 447 // TODO(oshima): IME support. |
| 531 return textfield_->text() == textfield_->GetSelectedText(); | 448 return text() == GetSelectedText(); |
| 532 } | 449 } |
| 533 | 450 |
| 534 bool OmniboxViewViews::DeleteAtEndPressed() { | 451 bool OmniboxViewViews::DeleteAtEndPressed() { |
| 535 return delete_at_end_pressed_; | 452 return delete_at_end_pressed_; |
| 536 } | 453 } |
| 537 | 454 |
| 538 void OmniboxViewViews::GetSelectionBounds(string16::size_type* start, | 455 void OmniboxViewViews::GetSelectionBounds(string16::size_type* start, |
| 539 string16::size_type* end) const { | 456 string16::size_type* end) const { |
| 540 ui::Range range; | 457 ui::Range range; |
| 541 textfield_->GetSelectedRange(&range); | 458 GetSelectedRange(&range); |
| 542 if (range.is_empty()) { | 459 if (range.is_empty()) { |
| 543 // Omnibox API expects that selection bounds is at cursor position | 460 // Omnibox API expects that selection bounds is at cursor position |
| 544 // if there is no selection. | 461 // if there is no selection. |
| 545 *start = textfield_->GetCursorPosition(); | 462 *start = GetCursorPosition(); |
| 546 *end = textfield_->GetCursorPosition(); | 463 *end = GetCursorPosition(); |
| 547 } else { | 464 } else { |
| 548 *start = static_cast<size_t>(range.end()); | 465 *start = static_cast<size_t>(range.end()); |
| 549 *end = static_cast<size_t>(range.start()); | 466 *end = static_cast<size_t>(range.start()); |
| 550 } | 467 } |
| 551 } | 468 } |
| 552 | 469 |
| 553 void OmniboxViewViews::SelectAll(bool reversed) { | 470 void OmniboxViewViews::SelectAll(bool reversed) { |
| 554 textfield_->SelectAll(reversed); | 471 views::Textfield::SelectAll(reversed); |
| 555 } | 472 } |
| 556 | 473 |
| 557 void OmniboxViewViews::UpdatePopup() { | 474 void OmniboxViewViews::UpdatePopup() { |
| 558 model()->SetInputInProgress(true); | 475 model()->SetInputInProgress(true); |
| 559 if (ime_candidate_window_open_) | 476 if (ime_candidate_window_open_) |
| 560 return; | 477 return; |
| 561 if (!model()->has_focus()) | 478 if (!model()->has_focus()) |
| 562 return; | 479 return; |
| 563 | 480 |
| 564 // Don't inline autocomplete when the caret/selection isn't at the end of | 481 // Prevent inline autocomplete when the caret isn't at the end of the text, |
| 565 // the text, or in the middle of composition. | 482 // and during IME composition editing. |
| 566 ui::Range sel; | 483 ui::Range sel; |
| 567 textfield_->GetSelectedRange(&sel); | 484 GetSelectedRange(&sel); |
| 568 bool no_inline_autocomplete = | 485 model()->StartAutocomplete(!sel.is_empty(), |
|
Peter Kasting
2013/02/18 18:57:47
Nit: Each line with arguments should have the argu
msw
2013/02/18 20:58:21
Done.
| |
| 569 sel.GetMax() < GetTextLength() || textfield_->IsIMEComposing(); | 486 sel.GetMax() < text().length() || IsIMEComposing()); |
| 570 | |
| 571 model()->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete); | |
| 572 } | 487 } |
| 573 | 488 |
| 574 void OmniboxViewViews::SetFocus() { | 489 void OmniboxViewViews::SetFocus() { |
| 575 // In views-implementation, the focus is on textfield rather than OmniboxView. | 490 RequestFocus(); |
| 576 textfield_->RequestFocus(); | |
| 577 // Restore caret visibility if focus is explicitly requested. This is | 491 // Restore caret visibility if focus is explicitly requested. This is |
| 578 // necessary because if we already have invisible focus, the RequestFocus() | 492 // necessary because if we already have invisible focus, the RequestFocus() |
| 579 // call above will short-circuit, preventing us from reaching | 493 // call above will short-circuit, preventing us from reaching |
| 580 // OmniboxEditModel::OnSetFocus(), which handles restoring visibility when the | 494 // OmniboxEditModel::OnSetFocus(), which handles restoring visibility when the |
| 581 // omnibox regains focus after losing focus. | 495 // omnibox regains focus after losing focus. |
| 582 model()->SetCaretVisibility(true); | 496 model()->SetCaretVisibility(true); |
| 583 } | 497 } |
| 584 | 498 |
| 585 void OmniboxViewViews::ApplyCaretVisibility() { | 499 void OmniboxViewViews::ApplyCaretVisibility() { |
| 586 textfield_->SetCursorEnabled(model()->is_caret_visible()); | 500 SetCursorEnabled(model()->is_caret_visible()); |
| 587 } | 501 } |
| 588 | 502 |
| 589 void OmniboxViewViews::OnTemporaryTextMaybeChanged( | 503 void OmniboxViewViews::OnTemporaryTextMaybeChanged( |
| 590 const string16& display_text, | 504 const string16& display_text, |
| 591 bool save_original_selection, | 505 bool save_original_selection, |
| 592 bool notify_text_changed) { | 506 bool notify_text_changed) { |
| 593 if (save_original_selection) | 507 if (save_original_selection) |
| 594 textfield_->GetSelectedRange(&saved_temporary_selection_); | 508 GetSelectedRange(&saved_temporary_selection_); |
| 595 | 509 |
| 596 SetWindowTextAndCaretPos(display_text, display_text.length(), false, | 510 SetWindowTextAndCaretPos(display_text, display_text.length(), false, |
| 597 notify_text_changed); | 511 notify_text_changed); |
| 598 } | 512 } |
| 599 | 513 |
| 600 bool OmniboxViewViews::OnInlineAutocompleteTextMaybeChanged( | 514 bool OmniboxViewViews::OnInlineAutocompleteTextMaybeChanged( |
| 601 const string16& display_text, | 515 const string16& display_text, |
| 602 size_t user_text_length) { | 516 size_t user_text_length) { |
| 603 if (display_text == GetText()) | 517 if (display_text == text()) |
| 604 return false; | 518 return false; |
| 605 ui::Range range(display_text.size(), user_text_length); | 519 ui::Range range(display_text.size(), user_text_length); |
| 606 SetTextAndSelectedRange(display_text, range); | 520 SetTextAndSelectedRange(display_text, range); |
| 607 TextChanged(); | 521 TextChanged(); |
| 608 return true; | 522 return true; |
| 609 } | 523 } |
| 610 | 524 |
| 611 void OmniboxViewViews::OnRevertTemporaryText() { | 525 void OmniboxViewViews::OnRevertTemporaryText() { |
| 612 textfield_->SelectRange(saved_temporary_selection_); | 526 SelectRange(saved_temporary_selection_); |
| 527 TextChanged(); | |
| 613 } | 528 } |
| 614 | 529 |
| 615 void OmniboxViewViews::OnBeforePossibleChange() { | 530 void OmniboxViewViews::OnBeforePossibleChange() { |
| 616 // Record our state. | 531 // Record our state. |
| 617 text_before_change_ = GetText(); | 532 text_before_change_ = text(); |
| 618 textfield_->GetSelectedRange(&sel_before_change_); | 533 GetSelectedRange(&sel_before_change_); |
| 619 ime_composing_before_change_ = textfield_->IsIMEComposing(); | 534 ime_composing_before_change_ = IsIMEComposing(); |
| 620 } | 535 } |
| 621 | 536 |
| 622 bool OmniboxViewViews::OnAfterPossibleChange() { | 537 bool OmniboxViewViews::OnAfterPossibleChange() { |
| 623 ui::Range new_sel; | 538 ui::Range new_sel; |
| 624 textfield_->GetSelectedRange(&new_sel); | 539 GetSelectedRange(&new_sel); |
| 625 | 540 |
| 626 // See if the text or selection have changed since OnBeforePossibleChange(). | 541 // See if the text or selection have changed since OnBeforePossibleChange(). |
| 627 const string16 new_text = GetText(); | 542 const string16 new_text = text(); |
| 628 const bool text_changed = (new_text != text_before_change_) || | 543 const bool text_changed = (new_text != text_before_change_) || |
| 629 (ime_composing_before_change_ != textfield_->IsIMEComposing()); | 544 (ime_composing_before_change_ != IsIMEComposing()); |
| 630 const bool selection_differs = | 545 const bool selection_differs = |
| 631 !((sel_before_change_.is_empty() && new_sel.is_empty()) || | 546 !((sel_before_change_.is_empty() && new_sel.is_empty()) || |
| 632 sel_before_change_.EqualsIgnoringDirection(new_sel)); | 547 sel_before_change_.EqualsIgnoringDirection(new_sel)); |
| 633 | 548 |
| 634 // When the user has deleted text, we don't allow inline autocomplete. Make | 549 // When the user has deleted text, we don't allow inline autocomplete. Make |
| 635 // sure to not flag cases like selecting part of the text and then pasting | 550 // sure to not flag cases like selecting part of the text and then pasting |
| 636 // (or typing) the prefix of that selection. (We detect these by making | 551 // (or typing) the prefix of that selection. (We detect these by making |
| 637 // sure the caret, which should be after any insertion, hasn't moved | 552 // sure the caret, which should be after any insertion, hasn't moved |
| 638 // forward of the old selection start.) | 553 // forward of the old selection start.) |
| 639 const bool just_deleted_text = | 554 const bool just_deleted_text = |
| 640 (text_before_change_.length() > new_text.length()) && | 555 (text_before_change_.length() > new_text.length()) && |
| 641 (new_sel.start() <= sel_before_change_.GetMin()); | 556 (new_sel.start() <= sel_before_change_.GetMin()); |
| 642 | 557 |
| 643 const bool something_changed = model()->OnAfterPossibleChange( | 558 const bool something_changed = model()->OnAfterPossibleChange( |
| 644 text_before_change_, new_text, new_sel.start(), new_sel.end(), | 559 text_before_change_, new_text, new_sel.start(), new_sel.end(), |
| 645 selection_differs, text_changed, just_deleted_text, | 560 selection_differs, text_changed, just_deleted_text, !IsIMEComposing()); |
| 646 !textfield_->IsIMEComposing()); | |
| 647 | 561 |
| 648 // If only selection was changed, we don't need to call model()'s | 562 // If only selection was changed, we don't need to call model()'s |
| 649 // OnChanged() method, which is called in TextChanged(). | 563 // OnChanged() method, which is called in TextChanged(). |
| 650 // But we still need to call EmphasizeURLComponents() to make sure the text | 564 // But we still need to call EmphasizeURLComponents() to make sure the text |
| 651 // attributes are updated correctly. | 565 // attributes are updated correctly. |
| 652 if (something_changed && text_changed) | 566 if (something_changed && text_changed) |
| 653 TextChanged(); | 567 TextChanged(); |
| 654 else if (selection_differs) | 568 else if (selection_differs) |
| 655 EmphasizeURLComponents(); | 569 EmphasizeURLComponents(); |
| 656 else if (delete_at_end_pressed_) | 570 else if (delete_at_end_pressed_) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 676 string16 OmniboxViewViews::GetInstantSuggestion() const { | 590 string16 OmniboxViewViews::GetInstantSuggestion() const { |
| 677 #if defined(OS_WIN) || defined(USE_AURA) | 591 #if defined(OS_WIN) || defined(USE_AURA) |
| 678 return location_bar_view_->GetInstantSuggestion(); | 592 return location_bar_view_->GetInstantSuggestion(); |
| 679 #else | 593 #else |
| 680 return string16(); | 594 return string16(); |
| 681 #endif | 595 #endif |
| 682 } | 596 } |
| 683 | 597 |
| 684 int OmniboxViewViews::TextWidth() const { | 598 int OmniboxViewViews::TextWidth() const { |
| 685 // TODO(oshima): add horizontal margin. | 599 // TODO(oshima): add horizontal margin. |
| 686 return textfield_->font().GetStringWidth(textfield_->text()); | 600 return font().GetStringWidth(text()); |
| 687 } | 601 } |
| 688 | 602 |
| 689 bool OmniboxViewViews::IsImeComposing() const { | 603 bool OmniboxViewViews::IsImeComposing() const { |
| 690 return false; | 604 return false; |
| 691 } | 605 } |
| 692 | 606 |
| 693 int OmniboxViewViews::GetMaxEditWidth(int entry_width) const { | 607 int OmniboxViewViews::GetMaxEditWidth(int entry_width) const { |
| 694 return entry_width; | 608 return entry_width; |
| 695 } | 609 } |
| 696 | 610 |
| 697 views::View* OmniboxViewViews::AddToView(views::View* parent) { | 611 views::View* OmniboxViewViews::AddToView(views::View* parent) { |
| 698 parent->AddChildView(this); | 612 parent->AddChildView(this); |
|
Peter Kasting
2013/02/18 18:57:47
Can we nuke this function entirely now? Seems lik
msw
2013/02/18 20:58:21
I'll try this in a followup, OmniboxViewWin::AddTo
| |
| 699 AddChildView(textfield_); | |
| 700 return this; | 613 return this; |
| 701 } | 614 } |
| 702 | 615 |
| 703 int OmniboxViewViews::OnPerformDrop(const ui::DropTargetEvent& event) { | 616 int OmniboxViewViews::OnPerformDrop(const ui::DropTargetEvent& event) { |
| 704 NOTIMPLEMENTED(); | 617 NOTIMPLEMENTED(); |
| 705 return ui::DragDropTypes::DRAG_NONE; | 618 return ui::DragDropTypes::DRAG_NONE; |
| 706 } | 619 } |
| 707 | 620 |
| 708 //////////////////////////////////////////////////////////////////////////////// | 621 //////////////////////////////////////////////////////////////////////////////// |
| 709 // OmniboxViewViews, views::TextfieldController implementation: | 622 // OmniboxViewViews, views::TextfieldController implementation: |
| 710 | 623 |
| 711 void OmniboxViewViews::ContentsChanged(views::Textfield* sender, | 624 void OmniboxViewViews::ContentsChanged(views::Textfield* sender, |
| 712 const string16& new_contents) { | 625 const string16& new_contents) { |
| 713 } | 626 } |
| 714 | 627 |
| 715 bool OmniboxViewViews::HandleKeyEvent(views::Textfield* textfield, | 628 bool OmniboxViewViews::HandleKeyEvent(views::Textfield* textfield, |
| 716 const ui::KeyEvent& event) { | 629 const ui::KeyEvent& event) { |
| 717 delete_at_end_pressed_ = false; | 630 delete_at_end_pressed_ = false; |
| 718 | 631 |
| 719 if (event.key_code() == ui::VKEY_BACK) { | 632 if (event.key_code() == ui::VKEY_BACK) { |
| 720 // Checks if it's currently in keyword search mode. | 633 // Checks if it's currently in keyword search mode. |
| 721 if (model()->is_keyword_hint() || model()->keyword().empty()) | 634 if (model()->is_keyword_hint() || model()->keyword().empty()) |
|
Peter Kasting
2013/02/18 18:57:47
Nit: I wouldn't mind just combining these three co
msw
2013/02/18 20:58:21
Done.
| |
| 722 return false; | 635 return false; |
| 723 // If there is selection, let textfield handle the backspace. | 636 // No extra handling is needed if there is a selection. |
| 724 if (textfield_->HasSelection()) | 637 if (HasSelection()) |
| 725 return false; | 638 return false; |
| 726 // If not at the begining of the text, let textfield handle the backspace. | 639 // No extra handling is needed if the cursor is not leading the text. |
| 727 if (textfield_->GetCursorPosition()) | 640 if (GetCursorPosition()) |
| 728 return false; | 641 return false; |
| 729 model()->ClearKeyword(GetText()); | 642 model()->ClearKeyword(text()); |
| 730 return true; | 643 return true; |
| 731 } | 644 } |
| 732 | 645 |
| 733 if (event.key_code() == ui::VKEY_DELETE && !event.IsAltDown()) { | 646 if (event.key_code() == ui::VKEY_DELETE && !event.IsAltDown()) { |
| 734 delete_at_end_pressed_ = | 647 delete_at_end_pressed_ = |
| 735 (!textfield_->HasSelection() && | 648 (!HasSelection() && GetCursorPosition() == text().length()); |
| 736 textfield_->GetCursorPosition() == textfield_->text().length()); | |
| 737 } | 649 } |
| 738 | 650 |
| 739 // Though the Textfield usually handles the right-arrow key for LTR text or | 651 // Handle the right-arrow key for LTR text and the left-arrow key for RTL text |
| 740 // left-arrow key for RTL text, we need to handle it if we have gray text | 652 // if there is an Instant suggestion (gray text) that needs to be committed. |
| 741 // (Instant suggestion) that needs to be committed. | 653 if (GetCursorPosition() == text().length()) { |
| 742 if (textfield_->GetCursorPosition() == textfield_->text().length()) { | 654 base::i18n::TextDirection direction = GetTextDirection(); |
| 743 base::i18n::TextDirection direction = textfield_->GetTextDirection(); | |
| 744 if ((direction == base::i18n::LEFT_TO_RIGHT && | 655 if ((direction == base::i18n::LEFT_TO_RIGHT && |
| 745 event.key_code() == ui::VKEY_RIGHT) || | 656 event.key_code() == ui::VKEY_RIGHT) || |
| 746 (direction == base::i18n::RIGHT_TO_LEFT && | 657 (direction == base::i18n::RIGHT_TO_LEFT && |
| 747 event.key_code() == ui::VKEY_LEFT)) { | 658 event.key_code() == ui::VKEY_LEFT)) { |
| 748 return model()->CommitSuggestedText(true); | 659 return model()->CommitSuggestedText(true); |
| 749 } | 660 } |
| 750 } | 661 } |
| 751 | 662 |
| 752 return false; | 663 return false; |
| 753 } | 664 } |
| 754 | 665 |
| 755 void OmniboxViewViews::OnBeforeUserAction(views::Textfield* sender) { | 666 void OmniboxViewViews::OnBeforeUserAction(views::Textfield* sender) { |
| 756 OnBeforePossibleChange(); | 667 OnBeforePossibleChange(); |
| 757 } | 668 } |
| 758 | 669 |
| 759 void OmniboxViewViews::OnAfterUserAction(views::Textfield* sender) { | 670 void OmniboxViewViews::OnAfterUserAction(views::Textfield* sender) { |
| 760 OnAfterPossibleChange(); | 671 OnAfterPossibleChange(); |
| 761 } | 672 } |
| 762 | 673 |
| 763 void OmniboxViewViews::OnAfterCutOrCopy() { | 674 void OmniboxViewViews::OnAfterCutOrCopy() { |
| 764 ui::Range selection_range; | 675 ui::Range selection_range; |
| 765 textfield_->GetSelectedRange(&selection_range); | 676 GetSelectedRange(&selection_range); |
| 766 ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread(); | 677 ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread(); |
| 767 string16 selected_text; | 678 string16 selected_text; |
| 768 cb->ReadText(ui::Clipboard::BUFFER_STANDARD, &selected_text); | 679 cb->ReadText(ui::Clipboard::BUFFER_STANDARD, &selected_text); |
| 769 const string16 text = textfield_->text(); | |
| 770 GURL url; | 680 GURL url; |
| 771 bool write_url; | 681 bool write_url; |
| 772 model()->AdjustTextForCopy(selection_range.GetMin(), selected_text == text, | 682 model()->AdjustTextForCopy(selection_range.GetMin(), selected_text == text(), |
| 773 &selected_text, &url, &write_url); | 683 &selected_text, &url, &write_url); |
| 774 if (write_url) | 684 if (write_url) { |
| 775 DoCopyURL(url, selected_text); | 685 DoCopyURL(url, selected_text); |
| 776 else | 686 } else { |
| 777 DoCopyText(selected_text); | 687 ui::ScopedClipboardWriter scoped_clipboard_writer( |
| 688 ui::Clipboard::GetForCurrentThread(), ui::Clipboard::BUFFER_STANDARD); | |
| 689 scoped_clipboard_writer.WriteText(selected_text); | |
| 690 } | |
| 778 } | 691 } |
| 779 | 692 |
| 780 void OmniboxViewViews::OnWriteDragData(ui::OSExchangeData* data) { | 693 void OmniboxViewViews::OnWriteDragData(ui::OSExchangeData* data) { |
| 781 ui::Range selection_range; | 694 ui::Range selection_range; |
| 782 textfield_->GetSelectedRange(&selection_range); | 695 GetSelectedRange(&selection_range); |
| 783 string16 selected_text = textfield_->GetSelectedText(); | 696 string16 selected_text = GetSelectedText(); |
| 784 const string16 text = textfield_->text(); | |
| 785 GURL url; | 697 GURL url; |
| 786 bool write_url; | 698 bool write_url; |
| 787 model()->AdjustTextForCopy(selection_range.start(), selected_text == text, | 699 model()->AdjustTextForCopy(selection_range.start(), selected_text == text(), |
| 788 &selected_text, &url, &write_url); | 700 &selected_text, &url, &write_url); |
| 789 data->SetString(selected_text); | 701 data->SetString(selected_text); |
| 790 if (write_url) | 702 if (write_url) |
| 791 data->SetURL(url, selected_text); | 703 data->SetURL(url, selected_text); |
| 792 } | 704 } |
| 793 | 705 |
| 794 void OmniboxViewViews::AppendDropFormats( | 706 void OmniboxViewViews::AppendDropFormats( |
| 795 int* formats, | 707 int* formats, |
| 796 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { | 708 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
| 797 *formats = *formats | ui::OSExchangeData::URL; | 709 *formats = *formats | ui::OSExchangeData::URL; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 void OmniboxViewViews::CandidateWindowClosed( | 800 void OmniboxViewViews::CandidateWindowClosed( |
| 889 chromeos::input_method::InputMethodManager* manager) { | 801 chromeos::input_method::InputMethodManager* manager) { |
| 890 ime_candidate_window_open_ = false; | 802 ime_candidate_window_open_ = false; |
| 891 UpdatePopup(); | 803 UpdatePopup(); |
| 892 } | 804 } |
| 893 #endif | 805 #endif |
| 894 | 806 |
| 895 //////////////////////////////////////////////////////////////////////////////// | 807 //////////////////////////////////////////////////////////////////////////////// |
| 896 // OmniboxViewViews, private: | 808 // OmniboxViewViews, private: |
| 897 | 809 |
| 898 size_t OmniboxViewViews::GetTextLength() const { | 810 int OmniboxViewViews::GetOmniboxTextLength() const { |
| 899 // TODO(oshima): Support instant, IME. | 811 // TODO(oshima): Support instant, IME. |
| 900 return textfield_->text().length(); | 812 return static_cast<int>(text().length()); |
| 901 } | |
| 902 | |
| 903 int OmniboxViewViews::GetOmniboxTextLength() const { | |
| 904 return static_cast<int>(GetTextLength()); | |
| 905 } | 813 } |
| 906 | 814 |
| 907 void OmniboxViewViews::EmphasizeURLComponents() { | 815 void OmniboxViewViews::EmphasizeURLComponents() { |
| 908 // See whether the contents are a URL with a non-empty host portion, which we | 816 // See whether the contents are a URL with a non-empty host portion, which we |
| 909 // should emphasize. To check for a URL, rather than using the type returned | 817 // should emphasize. To check for a URL, rather than using the type returned |
| 910 // by Parse(), ask the model, which will check the desired page transition for | 818 // by Parse(), ask the model, which will check the desired page transition for |
| 911 // this input. This can tell us whether an UNKNOWN input string is going to | 819 // this input. This can tell us whether an UNKNOWN input string is going to |
| 912 // be treated as a search or a navigation, and is the same method the Paste | 820 // be treated as a search or a navigation, and is the same method the Paste |
| 913 // And Go system uses. | 821 // And Go system uses. |
| 914 string16 text = GetText(); | |
| 915 url_parse::Component scheme, host; | 822 url_parse::Component scheme, host; |
| 916 AutocompleteInput::ParseForEmphasizeComponents(text, model()->GetDesiredTLD(), | 823 AutocompleteInput::ParseForEmphasizeComponents( |
| 917 &scheme, &host); | 824 text(), model()->GetDesiredTLD(), &scheme, &host); |
| 918 const bool emphasize = model()->CurrentTextIsURL() && (host.len > 0); | 825 const bool emphasize = model()->CurrentTextIsURL() && (host.len > 0); |
| 919 textfield_->SetColor(location_bar_view_->GetColor(security_level_, | 826 SetColor(location_bar_view_->GetColor(security_level_, |
| 920 emphasize ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT)); | 827 emphasize ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT)); |
| 921 if (emphasize) { | 828 if (emphasize) { |
| 922 textfield_->ApplyColor( | 829 ApplyColor( |
| 923 location_bar_view_->GetColor(security_level_, LocationBarView::TEXT), | 830 location_bar_view_->GetColor(security_level_, LocationBarView::TEXT), |
| 924 ui::Range(host.begin, host.end())); | 831 ui::Range(host.begin, host.end())); |
| 925 } | 832 } |
| 926 | 833 |
| 927 // Emphasize the scheme for security UI display purposes (if necessary). | 834 // Emphasize the scheme for security UI display purposes (if necessary). |
| 928 // Note that we check CurrentTextIsURL() because if we're replacing search | 835 // Note that we check CurrentTextIsURL() because if we're replacing search |
| 929 // URLs with search terms, we may have a non-URL even when the user is not | 836 // URLs with search terms, we may have a non-URL even when the user is not |
| 930 // editing; and in some cases, e.g. for "site:foo.com" searches, the parser | 837 // editing; and in some cases, e.g. for "site:foo.com" searches, the parser |
| 931 // may have incorrectly identified a qualifier as a scheme. | 838 // may have incorrectly identified a qualifier as a scheme. |
| 932 if (!model()->user_input_in_progress() && model()->CurrentTextIsURL() && | 839 if (!model()->user_input_in_progress() && model()->CurrentTextIsURL() && |
| 933 scheme.is_nonempty() && (security_level_ != ToolbarModel::NONE)) { | 840 scheme.is_nonempty() && (security_level_ != ToolbarModel::NONE)) { |
| 934 SkColor security_color = location_bar_view_->GetColor( | 841 SkColor security_color = location_bar_view_->GetColor( |
| 935 security_level_, LocationBarView::SECURITY_TEXT); | 842 security_level_, LocationBarView::SECURITY_TEXT); |
| 936 const bool strike = (security_level_ == ToolbarModel::SECURITY_ERROR); | 843 const bool strike = (security_level_ == ToolbarModel::SECURITY_ERROR); |
| 937 const ui::Range scheme_range(scheme.begin, scheme.end()); | 844 const ui::Range scheme_range(scheme.begin, scheme.end()); |
| 938 textfield_->ApplyColor(security_color, scheme_range); | 845 ApplyColor(security_color, scheme_range); |
| 939 textfield_->ApplyStyle(gfx::DIAGONAL_STRIKE, strike, scheme_range); | 846 ApplyStyle(gfx::DIAGONAL_STRIKE, strike, scheme_range); |
| 940 } | 847 } |
| 941 } | 848 } |
| 942 | 849 |
| 943 void OmniboxViewViews::SetTextAndSelectedRange(const string16& text, | 850 void OmniboxViewViews::SetTextAndSelectedRange(const string16& text, |
| 944 const ui::Range& range) { | 851 const ui::Range& range) { |
| 945 if (text != GetText()) | 852 SetText(text); |
| 946 textfield_->SetText(text); | 853 SelectRange(range); |
| 947 textfield_->SelectRange(range); | |
| 948 } | 854 } |
| 949 | 855 |
| 950 string16 OmniboxViewViews::GetSelectedText() const { | 856 string16 OmniboxViewViews::GetSelectedText() const { |
| 951 // TODO(oshima): Support instant, IME. | 857 // TODO(oshima): Support instant, IME. |
| 952 return textfield_->GetSelectedText(); | 858 return views::Textfield::GetSelectedText(); |
| 953 } | 859 } |
| 954 | 860 |
| 955 void OmniboxViewViews::CopyURL() { | 861 void OmniboxViewViews::CopyURL() { |
| 956 DoCopyURL(toolbar_model()->GetURL(), toolbar_model()->GetText(false)); | 862 DoCopyURL(toolbar_model()->GetURL(), toolbar_model()->GetText(false)); |
| 957 } | 863 } |
| 958 | 864 |
| 959 void OmniboxViewViews::OnPaste() { | 865 void OmniboxViewViews::OnPaste() { |
| 960 // Replace the selection if we have something to paste. | 866 // Replace the selection if we have something to paste. |
| 961 const string16 text(GetClipboardText()); | 867 const string16 text(GetClipboardText()); |
| 962 if (!text.empty()) { | 868 if (!text.empty()) { |
| 963 // Record this paste, so we can do different behavior. | 869 // Record this paste, so we can do different behavior. |
| 964 model()->on_paste(); | 870 model()->on_paste(); |
| 965 // Force a Paste operation to trigger the text_changed code in | 871 // Force a Paste operation to trigger the text_changed code in |
| 966 // OnAfterPossibleChange(), even if identical contents are pasted into the | 872 // OnAfterPossibleChange(), even if identical contents are pasted. |
| 967 // text box. | |
| 968 text_before_change_.clear(); | 873 text_before_change_.clear(); |
| 969 textfield_->ReplaceSelection(text); | 874 ReplaceSelection(text); |
| 970 } | 875 } |
| 971 } | 876 } |
| OLD | NEW |