| 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/cocoa/omnibox/omnibox_view_mac.h" | 5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" |
| 6 | 6 |
| 7 #include <Carbon/Carbon.h> // kVK_Return | 7 #include <Carbon/Carbon.h> // kVK_Return |
| 8 | 8 |
| 9 #include "base/property_bag.h" | 9 #include "base/property_bag.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "grit/generated_resources.h" | 22 #include "grit/generated_resources.h" |
| 23 #include "grit/theme_resources.h" | 23 #include "grit/theme_resources.h" |
| 24 #import "third_party/mozilla/NSPasteboard+Utils.h" | 24 #import "third_party/mozilla/NSPasteboard+Utils.h" |
| 25 #include "ui/base/clipboard/clipboard.h" | 25 #include "ui/base/clipboard/clipboard.h" |
| 26 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
| 27 #include "ui/gfx/mac/nsimage_cache.h" | 27 #include "ui/gfx/mac/nsimage_cache.h" |
| 28 #include "ui/gfx/rect.h" | 28 #include "ui/gfx/rect.h" |
| 29 | 29 |
| 30 using content::WebContents; | 30 using content::WebContents; |
| 31 | 31 |
| 32 // Focus-handling between |field_| and |model_| is a bit subtle. | 32 // Focus-handling between |field_| and model() is a bit subtle. |
| 33 // Other platforms detect change of focus, which is inconvenient | 33 // Other platforms detect change of focus, which is inconvenient |
| 34 // without subclassing NSTextField (even with a subclass, the use of a | 34 // without subclassing NSTextField (even with a subclass, the use of a |
| 35 // field editor may complicate things). | 35 // field editor may complicate things). |
| 36 // | 36 // |
| 37 // |model_| doesn't actually do anything when it gains focus, it just | 37 // model() doesn't actually do anything when it gains focus, it just |
| 38 // initializes. Visible activity happens only after the user edits. | 38 // initializes. Visible activity happens only after the user edits. |
| 39 // NSTextField delegate receives messages around starting and ending | 39 // NSTextField delegate receives messages around starting and ending |
| 40 // edits, so that suffices to catch focus changes. Since all calls | 40 // edits, so that suffices to catch focus changes. Since all calls |
| 41 // into |model_| start from OmniboxViewMac, in the worst case | 41 // into model() start from OmniboxViewMac, in the worst case |
| 42 // we can add code to sync up the sense of focus as needed. | 42 // we can add code to sync up the sense of focus as needed. |
| 43 // | 43 // |
| 44 // I've added DCHECK(IsFirstResponder()) in the places which I believe | 44 // I've added DCHECK(IsFirstResponder()) in the places which I believe |
| 45 // should only be reachable when |field_| is being edited. If these | 45 // should only be reachable when |field_| is being edited. If these |
| 46 // fire, it probably means someone unexpected is calling into | 46 // fire, it probably means someone unexpected is calling into |
| 47 // |model_|. | 47 // model(). |
| 48 // | 48 // |
| 49 // Other platforms don't appear to have the sense of "key window" that | 49 // Other platforms don't appear to have the sense of "key window" that |
| 50 // Mac does (I believe their fields lose focus when the window loses | 50 // Mac does (I believe their fields lose focus when the window loses |
| 51 // focus). Rather than modifying focus outside the control's edit | 51 // focus). Rather than modifying focus outside the control's edit |
| 52 // scope, when the window resigns key the autocomplete popup is | 52 // scope, when the window resigns key the autocomplete popup is |
| 53 // closed. |model_| still believes it has focus, and the popup will | 53 // closed. model() still believes it has focus, and the popup will |
| 54 // be regenerated on the user's next edit. That seems to match how | 54 // be regenerated on the user's next edit. That seems to match how |
| 55 // things work on other platforms. | 55 // things work on other platforms. |
| 56 | 56 |
| 57 namespace { | 57 namespace { |
| 58 | 58 |
| 59 // TODO(shess): This is ugly, find a better way. Using it right now | 59 // TODO(shess): This is ugly, find a better way. Using it right now |
| 60 // so that I can crib from gtk and still be able to see that I'm using | 60 // so that I can crib from gtk and still be able to see that I'm using |
| 61 // the same values easily. | 61 // the same values easily. |
| 62 NSColor* ColorWithRGBBytes(int rr, int gg, int bb) { | 62 NSColor* ColorWithRGBBytes(int rr, int gg, int bb) { |
| 63 DCHECK_LE(rr, 255); | 63 DCHECK_LE(rr, 255); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 NSImage* OmniboxViewMac::ImageForResource(int resource_id) { | 132 NSImage* OmniboxViewMac::ImageForResource(int resource_id) { |
| 133 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 133 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 134 return rb.GetNativeImageNamed(resource_id); | 134 return rb.GetNativeImageNamed(resource_id); |
| 135 } | 135 } |
| 136 | 136 |
| 137 OmniboxViewMac::OmniboxViewMac(OmniboxEditController* controller, | 137 OmniboxViewMac::OmniboxViewMac(OmniboxEditController* controller, |
| 138 ToolbarModel* toolbar_model, | 138 ToolbarModel* toolbar_model, |
| 139 Profile* profile, | 139 Profile* profile, |
| 140 CommandUpdater* command_updater, | 140 CommandUpdater* command_updater, |
| 141 AutocompleteTextField* field) | 141 AutocompleteTextField* field) |
| 142 : model_(new OmniboxEditModel(this, controller, profile)), | 142 : OmniboxView(profile, controller, toolbar_model, command_updater), |
| 143 popup_view_(new OmniboxPopupViewMac(this, model_.get(), field)), | 143 popup_view_(new OmniboxPopupViewMac(this, model(), field)), |
| 144 controller_(controller), | |
| 145 toolbar_model_(toolbar_model), | |
| 146 command_updater_(command_updater), | |
| 147 field_(field), | 144 field_(field), |
| 148 suggest_text_length_(0), | 145 suggest_text_length_(0), |
| 149 delete_was_pressed_(false), | 146 delete_was_pressed_(false), |
| 150 delete_at_end_pressed_(false), | 147 delete_at_end_pressed_(false), |
| 151 line_height_(0) { | 148 line_height_(0) { |
| 152 DCHECK(controller); | 149 DCHECK(controller); |
| 153 DCHECK(toolbar_model); | 150 DCHECK(toolbar_model); |
| 154 DCHECK(profile); | 151 DCHECK(profile); |
| 155 DCHECK(command_updater); | 152 DCHECK(command_updater); |
| 156 DCHECK(field); | 153 DCHECK(field); |
| 157 [field_ setObserver:this]; | 154 [field_ setObserver:this]; |
| 158 | 155 |
| 159 // Needed so that editing doesn't lose the styling. | 156 // Needed so that editing doesn't lose the styling. |
| 160 [field_ setAllowsEditingTextAttributes:YES]; | 157 [field_ setAllowsEditingTextAttributes:YES]; |
| 161 | 158 |
| 162 // Get the appropriate line height for the font that we use. | 159 // Get the appropriate line height for the font that we use. |
| 163 scoped_nsobject<NSLayoutManager> | 160 scoped_nsobject<NSLayoutManager> |
| 164 layoutManager([[NSLayoutManager alloc] init]); | 161 layoutManager([[NSLayoutManager alloc] init]); |
| 165 [layoutManager setUsesScreenFonts:YES]; | 162 [layoutManager setUsesScreenFonts:YES]; |
| 166 line_height_ = [layoutManager defaultLineHeightForFont:GetFieldFont()]; | 163 line_height_ = [layoutManager defaultLineHeightForFont:GetFieldFont()]; |
| 167 DCHECK_GT(line_height_, 0); | 164 DCHECK_GT(line_height_, 0); |
| 168 } | 165 } |
| 169 | 166 |
| 170 OmniboxViewMac::~OmniboxViewMac() { | 167 OmniboxViewMac::~OmniboxViewMac() { |
| 171 // Destroy popup view before this object in case it tries to call us | 168 // Destroy popup view before this object in case it tries to call us |
| 172 // back in the destructor. Likewise for destroying the model before | 169 // back in the destructor. |
| 173 // this object. | |
| 174 popup_view_.reset(); | 170 popup_view_.reset(); |
| 175 model_.reset(); | |
| 176 | 171 |
| 177 // Disconnect from |field_|, it outlives this object. | 172 // Disconnect from |field_|, it outlives this object. |
| 178 [field_ setObserver:NULL]; | 173 [field_ setObserver:NULL]; |
| 179 } | 174 } |
| 180 | 175 |
| 181 OmniboxEditModel* OmniboxViewMac::model() { | |
| 182 return model_.get(); | |
| 183 } | |
| 184 | |
| 185 const OmniboxEditModel* OmniboxViewMac::model() const { | |
| 186 return model_.get(); | |
| 187 } | |
| 188 | |
| 189 void OmniboxViewMac::SaveStateToTab(WebContents* tab) { | 176 void OmniboxViewMac::SaveStateToTab(WebContents* tab) { |
| 190 DCHECK(tab); | 177 DCHECK(tab); |
| 191 | 178 |
| 192 const bool hasFocus = [field_ currentEditor] ? true : false; | 179 const bool hasFocus = [field_ currentEditor] ? true : false; |
| 193 | 180 |
| 194 NSRange range; | 181 NSRange range; |
| 195 if (hasFocus) { | 182 if (hasFocus) { |
| 196 range = GetSelectedRange(); | 183 range = GetSelectedRange(); |
| 197 } else { | 184 } else { |
| 198 // If we are not focussed, there is no selection. Manufacture | 185 // If we are not focussed, there is no selection. Manufacture |
| 199 // something reasonable in case it starts to matter in the future. | 186 // something reasonable in case it starts to matter in the future. |
| 200 range = NSMakeRange(0, GetTextLength()); | 187 range = NSMakeRange(0, GetTextLength()); |
| 201 } | 188 } |
| 202 | 189 |
| 203 OmniboxViewMacState state(model_->GetStateForTabSwitch(), hasFocus, range); | 190 OmniboxViewMacState state(model()->GetStateForTabSwitch(), hasFocus, range); |
| 204 StoreStateToTab(tab, state); | 191 StoreStateToTab(tab, state); |
| 205 } | 192 } |
| 206 | 193 |
| 207 void OmniboxViewMac::Update(const WebContents* tab_for_state_restoring) { | 194 void OmniboxViewMac::Update(const WebContents* tab_for_state_restoring) { |
| 208 // TODO(shess): It seems like if the tab is non-NULL, then this code | 195 // TODO(shess): It seems like if the tab is non-NULL, then this code |
| 209 // shouldn't need to be called at all. When coded that way, I find | 196 // shouldn't need to be called at all. When coded that way, I find |
| 210 // that the field isn't always updated correctly. Figure out why | 197 // that the field isn't always updated correctly. Figure out why |
| 211 // this is. Maybe this method should be refactored into more | 198 // this is. Maybe this method should be refactored into more |
| 212 // specific cases. | 199 // specific cases. |
| 213 bool user_visible = model_->UpdatePermanentText(toolbar_model_->GetText()); | 200 bool user_visible = model()->UpdatePermanentText(toolbar_model()->GetText()); |
| 214 | 201 |
| 215 if (tab_for_state_restoring) { | 202 if (tab_for_state_restoring) { |
| 216 RevertAll(); | 203 RevertAll(); |
| 217 | 204 |
| 218 const OmniboxViewMacState* state = GetStateFromTab(tab_for_state_restoring); | 205 const OmniboxViewMacState* state = GetStateFromTab(tab_for_state_restoring); |
| 219 if (state) { | 206 if (state) { |
| 220 // Should restore the user's text via SetUserText(). | 207 // Should restore the user's text via SetUserText(). |
| 221 model_->RestoreState(state->model_state); | 208 model()->RestoreState(state->model_state); |
| 222 | 209 |
| 223 // Restore focus and selection if they were present when the tab | 210 // Restore focus and selection if they were present when the tab |
| 224 // was switched away. | 211 // was switched away. |
| 225 if (state->has_focus) { | 212 if (state->has_focus) { |
| 226 // TODO(shess): Unfortunately, there is no safe way to update | 213 // TODO(shess): Unfortunately, there is no safe way to update |
| 227 // this because TabStripController -selectTabWithContents:* is | 214 // this because TabStripController -selectTabWithContents:* is |
| 228 // also messing with focus. Both parties need to agree to | 215 // also messing with focus. Both parties need to agree to |
| 229 // store existing state before anyone tries to setup the new | 216 // store existing state before anyone tries to setup the new |
| 230 // state. Anyhow, it would look something like this. | 217 // state. Anyhow, it would look something like this. |
| 231 #if 0 | 218 #if 0 |
| 232 [[field_ window] makeFirstResponder:field_]; | 219 [[field_ window] makeFirstResponder:field_]; |
| 233 [[field_ currentEditor] setSelectedRange:state->selection]; | 220 [[field_ currentEditor] setSelectedRange:state->selection]; |
| 234 #endif | 221 #endif |
| 235 } | 222 } |
| 236 } | 223 } |
| 237 } else if (user_visible) { | 224 } else if (user_visible) { |
| 238 // Restore everything to the baseline look. | 225 // Restore everything to the baseline look. |
| 239 RevertAll(); | 226 RevertAll(); |
| 240 // TODO(shess): Figure out how this case is used, to make sure | 227 // TODO(shess): Figure out how this case is used, to make sure |
| 241 // we're getting the selection and popup right. | 228 // we're getting the selection and popup right. |
| 242 | 229 |
| 243 } else { | 230 } else { |
| 244 // TODO(shess): This corresponds to _win and _gtk, except those | 231 // TODO(shess): This corresponds to _win and _gtk, except those |
| 245 // guard it with a test for whether the security level changed. | 232 // guard it with a test for whether the security level changed. |
| 246 // But AFAICT, that can only change if the text changed, and that | 233 // But AFAICT, that can only change if the text changed, and that |
| 247 // code compares the toolbar_model_ security level with the local | 234 // code compares the toolbar_model() security level with the local |
| 248 // security level. Dig in and figure out why this isn't a no-op | 235 // security level. Dig in and figure out why this isn't a no-op |
| 249 // that should go away. | 236 // that should go away. |
| 250 EmphasizeURLComponents(); | 237 EmphasizeURLComponents(); |
| 251 } | 238 } |
| 252 } | 239 } |
| 253 | 240 |
| 254 void OmniboxViewMac::OpenMatch(const AutocompleteMatch& match, | |
| 255 WindowOpenDisposition disposition, | |
| 256 const GURL& alternate_nav_url, | |
| 257 size_t selected_line) { | |
| 258 // TODO(shess): Why is the caller passing an invalid url in the | |
| 259 // first place? Make sure that case isn't being dropped on the | |
| 260 // floor. | |
| 261 if (!match.destination_url.is_valid()) { | |
| 262 return; | |
| 263 } | |
| 264 | |
| 265 model_->OpenMatch(match, disposition, alternate_nav_url, selected_line); | |
| 266 } | |
| 267 | |
| 268 string16 OmniboxViewMac::GetText() const { | 241 string16 OmniboxViewMac::GetText() const { |
| 269 return base::SysNSStringToUTF16(GetNonSuggestTextSubstring()); | 242 return base::SysNSStringToUTF16(GetNonSuggestTextSubstring()); |
| 270 } | 243 } |
| 271 | 244 |
| 272 bool OmniboxViewMac::IsEditingOrEmpty() const { | |
| 273 return model_->user_input_in_progress() || !GetTextLength(); | |
| 274 } | |
| 275 | |
| 276 int OmniboxViewMac::GetIcon() const { | |
| 277 return IsEditingOrEmpty() ? | |
| 278 AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : | |
| 279 toolbar_model_->GetIcon(); | |
| 280 } | |
| 281 | |
| 282 void OmniboxViewMac::SetUserText(const string16& text) { | |
| 283 SetUserText(text, text, true); | |
| 284 } | |
| 285 | |
| 286 void OmniboxViewMac::SetUserText(const string16& text, | |
| 287 const string16& display_text, | |
| 288 bool update_popup) { | |
| 289 model_->SetUserText(text); | |
| 290 // TODO(shess): TODO below from gtk. | |
| 291 // TODO(deanm): something about selection / focus change here. | |
| 292 SetWindowTextAndCaretPos(display_text, display_text.length(), update_popup, | |
| 293 true); | |
| 294 } | |
| 295 | |
| 296 NSRange OmniboxViewMac::GetSelectedRange() const { | 245 NSRange OmniboxViewMac::GetSelectedRange() const { |
| 297 return [[field_ currentEditor] selectedRange]; | 246 return [[field_ currentEditor] selectedRange]; |
| 298 } | 247 } |
| 299 | 248 |
| 300 NSRange OmniboxViewMac::GetMarkedRange() const { | 249 NSRange OmniboxViewMac::GetMarkedRange() const { |
| 301 DCHECK([field_ currentEditor]); | 250 DCHECK([field_ currentEditor]); |
| 302 return [(NSTextView*)[field_ currentEditor] markedRange]; | 251 return [(NSTextView*)[field_ currentEditor] markedRange]; |
| 303 } | 252 } |
| 304 | 253 |
| 305 void OmniboxViewMac::SetSelectedRange(const NSRange range) { | 254 void OmniboxViewMac::SetSelectedRange(const NSRange range) { |
| 306 // This can be called when we don't have focus. For instance, when | 255 // This can be called when we don't have focus. For instance, when |
| 307 // the user clicks the "Go" button. | 256 // the user clicks the "Go" button. |
| 308 if (model_->has_focus()) { | 257 if (model()->has_focus()) { |
| 309 // TODO(shess): If |model_| thinks we have focus, this should not | 258 // TODO(shess): If model() thinks we have focus, this should not |
| 310 // be necessary. Try to convert to DCHECK(IsFirstResponder()). | 259 // be necessary. Try to convert to DCHECK(IsFirstResponder()). |
| 311 if (![field_ currentEditor]) { | 260 if (![field_ currentEditor]) { |
| 312 [[field_ window] makeFirstResponder:field_]; | 261 [[field_ window] makeFirstResponder:field_]; |
| 313 } | 262 } |
| 314 | 263 |
| 315 // TODO(shess): What if it didn't get first responder, and there is | 264 // TODO(shess): What if it didn't get first responder, and there is |
| 316 // no field editor? This will do nothing. Well, at least it won't | 265 // no field editor? This will do nothing. Well, at least it won't |
| 317 // crash. Think of something more productive to do, or prove that | 266 // crash. Think of something more productive to do, or prove that |
| 318 // it cannot occur and DCHECK appropriately. | 267 // it cannot occur and DCHECK appropriately. |
| 319 [[field_ currentEditor] setSelectedRange:range]; | 268 [[field_ currentEditor] setSelectedRange:range]; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 // TODO(shess): Figure out what |reversed| implies. The gtk version | 324 // TODO(shess): Figure out what |reversed| implies. The gtk version |
| 376 // has it imply inverting the selection front to back, but I don't | 325 // has it imply inverting the selection front to back, but I don't |
| 377 // even know if that makes sense for Mac. | 326 // even know if that makes sense for Mac. |
| 378 | 327 |
| 379 // TODO(shess): Verify that we should be stealing focus at this | 328 // TODO(shess): Verify that we should be stealing focus at this |
| 380 // point. | 329 // point. |
| 381 SetSelectedRange(NSMakeRange(0, GetTextLength())); | 330 SetSelectedRange(NSMakeRange(0, GetTextLength())); |
| 382 } | 331 } |
| 383 | 332 |
| 384 void OmniboxViewMac::RevertAll() { | 333 void OmniboxViewMac::RevertAll() { |
| 385 ClosePopup(); | 334 OmniboxView::RevertAll(); |
| 386 model_->Revert(); | |
| 387 model_->OnChanged(); | |
| 388 [field_ clearUndoChain]; | 335 [field_ clearUndoChain]; |
| 389 } | 336 } |
| 390 | 337 |
| 391 void OmniboxViewMac::UpdatePopup() { | 338 void OmniboxViewMac::UpdatePopup() { |
| 392 model_->SetInputInProgress(true); | 339 model()->SetInputInProgress(true); |
| 393 if (!model_->has_focus()) | 340 if (!model()->has_focus()) |
| 394 return; | 341 return; |
| 395 | 342 |
| 396 // Comment copied from OmniboxViewWin::UpdatePopup(): | 343 // Comment copied from OmniboxViewWin::UpdatePopup(): |
| 397 // Don't inline autocomplete when: | 344 // Don't inline autocomplete when: |
| 398 // * The user is deleting text | 345 // * The user is deleting text |
| 399 // * The caret/selection isn't at the end of the text | 346 // * The caret/selection isn't at the end of the text |
| 400 // * The user has just pasted in something that replaced all the text | 347 // * The user has just pasted in something that replaced all the text |
| 401 // * The user is trying to compose something in an IME | 348 // * The user is trying to compose something in an IME |
| 402 bool prevent_inline_autocomplete = IsImeComposing(); | 349 bool prevent_inline_autocomplete = IsImeComposing(); |
| 403 NSTextView* editor = (NSTextView*)[field_ currentEditor]; | 350 NSTextView* editor = (NSTextView*)[field_ currentEditor]; |
| 404 if (editor) { | 351 if (editor) { |
| 405 if (NSMaxRange([editor selectedRange]) < | 352 if (NSMaxRange([editor selectedRange]) < |
| 406 [[editor textStorage] length] - suggest_text_length_) | 353 [[editor textStorage] length] - suggest_text_length_) |
| 407 prevent_inline_autocomplete = true; | 354 prevent_inline_autocomplete = true; |
| 408 } | 355 } |
| 409 | 356 |
| 410 model_->StartAutocomplete([editor selectedRange].length != 0, | 357 model()->StartAutocomplete([editor selectedRange].length != 0, |
| 411 prevent_inline_autocomplete); | 358 prevent_inline_autocomplete); |
| 412 } | 359 } |
| 413 | 360 |
| 414 void OmniboxViewMac::ClosePopup() { | 361 void OmniboxViewMac::CloseOmniboxPopup() { |
| 415 model_->StopAutocomplete(); | 362 // Call both base class methods. |
| 363 ClosePopup(); |
| 364 OmniboxView::CloseOmniboxPopup(); |
| 416 } | 365 } |
| 417 | 366 |
| 418 void OmniboxViewMac::SetFocus() { | 367 void OmniboxViewMac::SetFocus() { |
| 419 } | 368 } |
| 420 | 369 |
| 421 void OmniboxViewMac::SetText(const string16& display_text) { | 370 void OmniboxViewMac::SetText(const string16& display_text) { |
| 422 // If we are setting the text directly, there cannot be any suggest text. | 371 // If we are setting the text directly, there cannot be any suggest text. |
| 423 suggest_text_length_ = 0; | 372 suggest_text_length_ = 0; |
| 424 SetTextInternal(display_text); | 373 SetTextInternal(display_text); |
| 425 } | 374 } |
| 426 | 375 |
| 427 void OmniboxViewMac::SetTextInternal(const string16& display_text) { | 376 void OmniboxViewMac::SetTextInternal(const string16& display_text) { |
| 428 NSString* ss = base::SysUTF16ToNSString(display_text); | 377 NSString* ss = base::SysUTF16ToNSString(display_text); |
| 429 NSMutableAttributedString* as = | 378 NSMutableAttributedString* as = |
| 430 [[[NSMutableAttributedString alloc] initWithString:ss] autorelease]; | 379 [[[NSMutableAttributedString alloc] initWithString:ss] autorelease]; |
| 431 | 380 |
| 432 ApplyTextAttributes(display_text, as); | 381 ApplyTextAttributes(display_text, as); |
| 433 | 382 |
| 434 [field_ setAttributedStringValue:as]; | 383 [field_ setAttributedStringValue:as]; |
| 435 | 384 |
| 436 // TODO(shess): This may be an appropriate place to call: | 385 // TODO(shess): This may be an appropriate place to call: |
| 437 // model_->OnChanged(); | 386 // model()->OnChanged(); |
| 438 // In the current implementation, this tells LocationBarViewMac to | 387 // In the current implementation, this tells LocationBarViewMac to |
| 439 // mess around with |model_| and update |field_|. Unfortunately, | 388 // mess around with model() and update |field_|. Unfortunately, |
| 440 // when I look at our peer implementations, it's not entirely clear | 389 // when I look at our peer implementations, it's not entirely clear |
| 441 // to me if this is safe. SetTextInternal() is sort of an utility method, | 390 // to me if this is safe. SetTextInternal() is sort of an utility method, |
| 442 // and different callers sometimes have different needs. Research | 391 // and different callers sometimes have different needs. Research |
| 443 // this issue so that it can be added safely. | 392 // this issue so that it can be added safely. |
| 444 | 393 |
| 445 // TODO(shess): Also, consider whether this code couldn't just | 394 // TODO(shess): Also, consider whether this code couldn't just |
| 446 // manage things directly. Windows uses a series of overlaid view | 395 // manage things directly. Windows uses a series of overlaid view |
| 447 // objects to accomplish the hinting stuff that OnChanged() does, so | 396 // objects to accomplish the hinting stuff that OnChanged() does, so |
| 448 // it makes sense to have it in the controller that lays those | 397 // it makes sense to have it in the controller that lays those |
| 449 // things out. Mac instead pushes the support into a custom | 398 // things out. Mac instead pushes the support into a custom |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 [storage setAttributes:[NSDictionary dictionary] | 439 [storage setAttributes:[NSDictionary dictionary] |
| 491 range:NSMakeRange(0, [storage length])]; | 440 range:NSMakeRange(0, [storage length])]; |
| 492 ApplyTextAttributes(GetText(), storage); | 441 ApplyTextAttributes(GetText(), storage); |
| 493 | 442 |
| 494 [storage endEditing]; | 443 [storage endEditing]; |
| 495 } else { | 444 } else { |
| 496 SetText(GetText()); | 445 SetText(GetText()); |
| 497 } | 446 } |
| 498 } | 447 } |
| 499 | 448 |
| 500 void OmniboxViewMac::TextChanged() { | |
| 501 EmphasizeURLComponents(); | |
| 502 model_->OnChanged(); | |
| 503 } | |
| 504 | |
| 505 void OmniboxViewMac::ApplyTextAttributes(const string16& display_text, | 449 void OmniboxViewMac::ApplyTextAttributes(const string16& display_text, |
| 506 NSMutableAttributedString* as) { | 450 NSMutableAttributedString* as) { |
| 507 NSUInteger as_length = [as length]; | 451 NSUInteger as_length = [as length]; |
| 508 NSRange as_entire_string = NSMakeRange(0, as_length); | 452 NSRange as_entire_string = NSMakeRange(0, as_length); |
| 509 | 453 |
| 510 [as addAttribute:NSFontAttributeName value:GetFieldFont() | 454 [as addAttribute:NSFontAttributeName value:GetFieldFont() |
| 511 range:as_entire_string]; | 455 range:as_entire_string]; |
| 512 | 456 |
| 513 // A kinda hacky way to add breaking at periods. This is what Safari does. | 457 // A kinda hacky way to add breaking at periods. This is what Safari does. |
| 514 // This works for IDNs too, despite the "en_US". | 458 // This works for IDNs too, despite the "en_US". |
| 515 [as addAttribute:@"NSLanguage" value:@"en_US_POSIX" | 459 [as addAttribute:@"NSLanguage" value:@"en_US_POSIX" |
| 516 range:as_entire_string]; | 460 range:as_entire_string]; |
| 517 | 461 |
| 518 // Make a paragraph style locking in the standard line height as the maximum, | 462 // Make a paragraph style locking in the standard line height as the maximum, |
| 519 // otherwise the baseline may shift "downwards". | 463 // otherwise the baseline may shift "downwards". |
| 520 scoped_nsobject<NSMutableParagraphStyle> | 464 scoped_nsobject<NSMutableParagraphStyle> |
| 521 paragraph_style([[NSMutableParagraphStyle alloc] init]); | 465 paragraph_style([[NSMutableParagraphStyle alloc] init]); |
| 522 [paragraph_style setMaximumLineHeight:line_height_]; | 466 [paragraph_style setMaximumLineHeight:line_height_]; |
| 523 [as addAttribute:NSParagraphStyleAttributeName value:paragraph_style | 467 [as addAttribute:NSParagraphStyleAttributeName value:paragraph_style |
| 524 range:as_entire_string]; | 468 range:as_entire_string]; |
| 525 | 469 |
| 526 // Grey out the suggest text. | 470 // Grey out the suggest text. |
| 527 [as addAttribute:NSForegroundColorAttributeName value:SuggestTextColor() | 471 [as addAttribute:NSForegroundColorAttributeName value:SuggestTextColor() |
| 528 range:NSMakeRange(as_length - suggest_text_length_, | 472 range:NSMakeRange(as_length - suggest_text_length_, |
| 529 suggest_text_length_)]; | 473 suggest_text_length_)]; |
| 530 | 474 |
| 531 url_parse::Component scheme, host; | 475 url_parse::Component scheme, host; |
| 532 AutocompleteInput::ParseForEmphasizeComponents( | 476 AutocompleteInput::ParseForEmphasizeComponents( |
| 533 display_text, model_->GetDesiredTLD(), &scheme, &host); | 477 display_text, model()->GetDesiredTLD(), &scheme, &host); |
| 534 const bool emphasize = model_->CurrentTextIsURL() && (host.len > 0); | 478 const bool emphasize = model()->CurrentTextIsURL() && (host.len > 0); |
| 535 if (emphasize) { | 479 if (emphasize) { |
| 536 [as addAttribute:NSForegroundColorAttributeName value:BaseTextColor() | 480 [as addAttribute:NSForegroundColorAttributeName value:BaseTextColor() |
| 537 range:as_entire_string]; | 481 range:as_entire_string]; |
| 538 | 482 |
| 539 [as addAttribute:NSForegroundColorAttributeName value:HostTextColor() | 483 [as addAttribute:NSForegroundColorAttributeName value:HostTextColor() |
| 540 range:ComponentToNSRange(host)]; | 484 range:ComponentToNSRange(host)]; |
| 541 } | 485 } |
| 542 | 486 |
| 543 // TODO(shess): GTK has this as a member var, figure out why. | 487 // TODO(shess): GTK has this as a member var, figure out why. |
| 544 // [Could it be to not change if no change? If so, I'm guessing | 488 // [Could it be to not change if no change? If so, I'm guessing |
| 545 // AppKit may already handle that.] | 489 // AppKit may already handle that.] |
| 546 const ToolbarModel::SecurityLevel security_level = | 490 const ToolbarModel::SecurityLevel security_level = |
| 547 toolbar_model_->GetSecurityLevel(); | 491 toolbar_model()->GetSecurityLevel(); |
| 548 | 492 |
| 549 // Emphasize the scheme for security UI display purposes (if necessary). | 493 // Emphasize the scheme for security UI display purposes (if necessary). |
| 550 if (!model_->user_input_in_progress() && scheme.is_nonempty() && | 494 if (!model()->user_input_in_progress() && scheme.is_nonempty() && |
| 551 (security_level != ToolbarModel::NONE)) { | 495 (security_level != ToolbarModel::NONE)) { |
| 552 NSColor* color; | 496 NSColor* color; |
| 553 if (security_level == ToolbarModel::EV_SECURE || | 497 if (security_level == ToolbarModel::EV_SECURE || |
| 554 security_level == ToolbarModel::SECURE) { | 498 security_level == ToolbarModel::SECURE) { |
| 555 color = SecureSchemeColor(); | 499 color = SecureSchemeColor(); |
| 556 } else if (security_level == ToolbarModel::SECURITY_ERROR) { | 500 } else if (security_level == ToolbarModel::SECURITY_ERROR) { |
| 557 color = SecurityErrorSchemeColor(); | 501 color = SecurityErrorSchemeColor(); |
| 558 // Add a strikethrough through the scheme. | 502 // Add a strikethrough through the scheme. |
| 559 [as addAttribute:NSStrikethroughStyleAttributeName | 503 [as addAttribute:NSStrikethroughStyleAttributeName |
| 560 value:[NSNumber numberWithInt:NSUnderlineStyleSingle] | 504 value:[NSNumber numberWithInt:NSUnderlineStyleSingle] |
| 561 range:ComponentToNSRange(scheme)]; | 505 range:ComponentToNSRange(scheme)]; |
| 562 } else if (security_level == ToolbarModel::SECURITY_WARNING) { | 506 } else if (security_level == ToolbarModel::SECURITY_WARNING) { |
| 563 color = BaseTextColor(); | 507 color = BaseTextColor(); |
| 564 } else { | 508 } else { |
| 565 NOTREACHED(); | 509 NOTREACHED(); |
| 566 color = BaseTextColor(); | 510 color = BaseTextColor(); |
| 567 } | 511 } |
| 568 [as addAttribute:NSForegroundColorAttributeName value:color | 512 [as addAttribute:NSForegroundColorAttributeName value:color |
| 569 range:ComponentToNSRange(scheme)]; | 513 range:ComponentToNSRange(scheme)]; |
| 570 } | 514 } |
| 571 } | 515 } |
| 572 | 516 |
| 573 void OmniboxViewMac::OnTemporaryTextMaybeChanged(const string16& display_text, | 517 void OmniboxViewMac::OnTemporaryTextMaybeChanged(const string16& display_text, |
| 574 bool save_original_selection) { | 518 bool save_original_selection) { |
| 575 if (save_original_selection) | 519 if (save_original_selection) |
| 576 saved_temporary_selection_ = GetSelectedRange(); | 520 saved_temporary_selection_ = GetSelectedRange(); |
| 577 | 521 |
| 578 suggest_text_length_ = 0; | 522 suggest_text_length_ = 0; |
| 579 SetWindowTextAndCaretPos(display_text, display_text.size(), false, false); | 523 SetWindowTextAndCaretPos(display_text, display_text.size(), false, false); |
| 580 model_->OnChanged(); | 524 model()->OnChanged(); |
| 581 [field_ clearUndoChain]; | 525 [field_ clearUndoChain]; |
| 582 } | 526 } |
| 583 | 527 |
| 584 void OmniboxViewMac::OnStartingIME() { | 528 void OmniboxViewMac::OnStartingIME() { |
| 585 // Reset the suggest text just before starting an IME composition session, | 529 // Reset the suggest text just before starting an IME composition session, |
| 586 // otherwise the IME composition may be interrupted when the suggest text | 530 // otherwise the IME composition may be interrupted when the suggest text |
| 587 // gets reset by the IME composition change. | 531 // gets reset by the IME composition change. |
| 588 SetInstantSuggestion(string16(), false); | 532 SetInstantSuggestion(string16(), false); |
| 589 } | 533 } |
| 590 | 534 |
| 591 bool OmniboxViewMac::OnInlineAutocompleteTextMaybeChanged( | 535 bool OmniboxViewMac::OnInlineAutocompleteTextMaybeChanged( |
| 592 const string16& display_text, | 536 const string16& display_text, |
| 593 size_t user_text_length) { | 537 size_t user_text_length) { |
| 594 // TODO(shess): Make sure that this actually works. The round trip | 538 // TODO(shess): Make sure that this actually works. The round trip |
| 595 // to native form and back may mean that it's the same but not the | 539 // to native form and back may mean that it's the same but not the |
| 596 // same. | 540 // same. |
| 597 if (display_text == GetText()) | 541 if (display_text == GetText()) |
| 598 return false; | 542 return false; |
| 599 | 543 |
| 600 DCHECK_LE(user_text_length, display_text.size()); | 544 DCHECK_LE(user_text_length, display_text.size()); |
| 601 const NSRange range = | 545 const NSRange range = |
| 602 NSMakeRange(user_text_length, display_text.size() - user_text_length); | 546 NSMakeRange(user_text_length, display_text.size() - user_text_length); |
| 603 SetTextAndSelectedRange(display_text, range); | 547 SetTextAndSelectedRange(display_text, range); |
| 604 model_->OnChanged(); | 548 model()->OnChanged(); |
| 605 [field_ clearUndoChain]; | 549 [field_ clearUndoChain]; |
| 606 | 550 |
| 607 return true; | 551 return true; |
| 608 } | 552 } |
| 609 | 553 |
| 610 void OmniboxViewMac::OnRevertTemporaryText() { | 554 void OmniboxViewMac::OnRevertTemporaryText() { |
| 611 SetSelectedRange(saved_temporary_selection_); | 555 SetSelectedRange(saved_temporary_selection_); |
| 612 } | 556 } |
| 613 | 557 |
| 614 bool OmniboxViewMac::IsFirstResponder() const { | 558 bool OmniboxViewMac::IsFirstResponder() const { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 // TODO(shess): In our implementation, we can catch -deleteBackward: | 592 // TODO(shess): In our implementation, we can catch -deleteBackward: |
| 649 // and other methods to provide positive knowledge that a delete | 593 // and other methods to provide positive knowledge that a delete |
| 650 // occured, rather than intuiting it from context. Consider whether | 594 // occured, rather than intuiting it from context. Consider whether |
| 651 // that would be a stronger approach. | 595 // that would be a stronger approach. |
| 652 const bool just_deleted_text = | 596 const bool just_deleted_text = |
| 653 (length < text_before_change_.length() && | 597 (length < text_before_change_.length() && |
| 654 new_selection.location <= selection_before_change_.location); | 598 new_selection.location <= selection_before_change_.location); |
| 655 | 599 |
| 656 delete_at_end_pressed_ = false; | 600 delete_at_end_pressed_ = false; |
| 657 | 601 |
| 658 const bool something_changed = model_->OnAfterPossibleChange( | 602 const bool something_changed = model()->OnAfterPossibleChange( |
| 659 text_before_change_, new_text, new_selection.location, | 603 text_before_change_, new_text, new_selection.location, |
| 660 NSMaxRange(new_selection), selection_differs, text_differs, | 604 NSMaxRange(new_selection), selection_differs, text_differs, |
| 661 just_deleted_text, !IsImeComposing()); | 605 just_deleted_text, !IsImeComposing()); |
| 662 | 606 |
| 663 if (delete_was_pressed_ && at_end_of_edit) | 607 if (delete_was_pressed_ && at_end_of_edit) |
| 664 delete_at_end_pressed_ = true; | 608 delete_at_end_pressed_ = true; |
| 665 | 609 |
| 666 // Restyle in case the user changed something. | 610 // Restyle in case the user changed something. |
| 667 // TODO(shess): I believe there are multiple-redraw cases, here. | 611 // TODO(shess): I believe there are multiple-redraw cases, here. |
| 668 // Linux watches for something_changed && text_differs, but that | 612 // Linux watches for something_changed && text_differs, but that |
| 669 // fails for us in case you copy the URL and paste the identical URL | 613 // fails for us in case you copy the URL and paste the identical URL |
| 670 // back (we'll lose the styling). | 614 // back (we'll lose the styling). |
| 671 TextChanged(); | 615 TextChanged(); |
| 672 | 616 |
| 673 delete_was_pressed_ = false; | 617 delete_was_pressed_ = false; |
| 674 | 618 |
| 675 return something_changed; | 619 return something_changed; |
| 676 } | 620 } |
| 677 | 621 |
| 678 gfx::NativeView OmniboxViewMac::GetNativeView() const { | 622 gfx::NativeView OmniboxViewMac::GetNativeView() const { |
| 679 return field_; | 623 return field_; |
| 680 } | 624 } |
| 681 | 625 |
| 682 gfx::NativeView OmniboxViewMac::GetRelativeWindowForPopup() const { | 626 gfx::NativeView OmniboxViewMac::GetRelativeWindowForPopup() const { |
| 683 // Not used on mac. | 627 // Not used on mac. |
| 684 NOTREACHED(); | 628 NOTREACHED(); |
| 685 return NULL; | 629 return NULL; |
| 686 } | 630 } |
| 687 | 631 |
| 688 CommandUpdater* OmniboxViewMac::GetCommandUpdater() { | |
| 689 return command_updater_; | |
| 690 } | |
| 691 | |
| 692 void OmniboxViewMac::SetInstantSuggestion(const string16& suggest_text, | 632 void OmniboxViewMac::SetInstantSuggestion(const string16& suggest_text, |
| 693 bool animate_to_complete) { | 633 bool animate_to_complete) { |
| 694 NSString* text = GetNonSuggestTextSubstring(); | 634 NSString* text = GetNonSuggestTextSubstring(); |
| 695 bool needs_update = (suggest_text_length_ > 0); | 635 bool needs_update = (suggest_text_length_ > 0); |
| 696 | 636 |
| 697 // Append the new suggest text. | 637 // Append the new suggest text. |
| 698 suggest_text_length_ = suggest_text.length(); | 638 suggest_text_length_ = suggest_text.length(); |
| 699 if (suggest_text_length_ > 0) { | 639 if (suggest_text_length_ > 0) { |
| 700 text = [text stringByAppendingString:base::SysUTF16ToNSString( | 640 text = [text stringByAppendingString:base::SysUTF16ToNSString( |
| 701 suggest_text)]; | 641 suggest_text)]; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 731 // We should only arrive here when the field is focussed. | 671 // We should only arrive here when the field is focussed. |
| 732 DCHECK([field_ currentEditor]); | 672 DCHECK([field_ currentEditor]); |
| 733 } | 673 } |
| 734 | 674 |
| 735 void OmniboxViewMac::OnBeforeChange() { | 675 void OmniboxViewMac::OnBeforeChange() { |
| 736 // Capture the current state. | 676 // Capture the current state. |
| 737 OnBeforePossibleChange(); | 677 OnBeforePossibleChange(); |
| 738 } | 678 } |
| 739 | 679 |
| 740 void OmniboxViewMac::OnDidChange() { | 680 void OmniboxViewMac::OnDidChange() { |
| 741 // Figure out what changed and notify the model_. | 681 // Figure out what changed and notify the model. |
| 742 OnAfterPossibleChange(); | 682 OnAfterPossibleChange(); |
| 743 } | 683 } |
| 744 | 684 |
| 745 void OmniboxViewMac::OnDidEndEditing() { | 685 void OmniboxViewMac::OnDidEndEditing() { |
| 746 ClosePopup(); | 686 ClosePopup(); |
| 747 } | 687 } |
| 748 | 688 |
| 749 bool OmniboxViewMac::OnDoCommandBySelector(SEL cmd) { | 689 bool OmniboxViewMac::OnDoCommandBySelector(SEL cmd) { |
| 750 // We should only arrive here when the field is focussed. | 690 // We should only arrive here when the field is focussed. |
| 751 DCHECK(IsFirstResponder()); | 691 DCHECK(IsFirstResponder()); |
| 752 | 692 |
| 753 if (cmd != @selector(moveRight:) && | 693 if (cmd != @selector(moveRight:) && |
| 754 cmd != @selector(insertTab:) && | 694 cmd != @selector(insertTab:) && |
| 755 cmd != @selector(insertTabIgnoringFieldEditor:)) { | 695 cmd != @selector(insertTabIgnoringFieldEditor:)) { |
| 756 // Reset the suggest text for any change other than key right or tab. | 696 // Reset the suggest text for any change other than key right or tab. |
| 757 // TODO(rohitrao): This is here to prevent complications when editing text. | 697 // TODO(rohitrao): This is here to prevent complications when editing text. |
| 758 // See if this can be removed. | 698 // See if this can be removed. |
| 759 SetInstantSuggestion(string16(), false); | 699 SetInstantSuggestion(string16(), false); |
| 760 } | 700 } |
| 761 | 701 |
| 762 if (cmd == @selector(deleteForward:)) | 702 if (cmd == @selector(deleteForward:)) |
| 763 delete_was_pressed_ = true; | 703 delete_was_pressed_ = true; |
| 764 | 704 |
| 765 // Don't intercept up/down-arrow or backtab if the popup isn't open. | 705 // Don't intercept up/down-arrow or backtab if the popup isn't open. |
| 766 if (popup_view_->IsOpen()) { | 706 if (popup_view_->IsOpen()) { |
| 767 if (cmd == @selector(moveDown:)) { | 707 if (cmd == @selector(moveDown:)) { |
| 768 model_->OnUpOrDownKeyPressed(1); | 708 model()->OnUpOrDownKeyPressed(1); |
| 769 return true; | 709 return true; |
| 770 } | 710 } |
| 771 | 711 |
| 772 if (cmd == @selector(moveUp:)) { | 712 if (cmd == @selector(moveUp:)) { |
| 773 model_->OnUpOrDownKeyPressed(-1); | 713 model()->OnUpOrDownKeyPressed(-1); |
| 774 return true; | 714 return true; |
| 775 } | 715 } |
| 776 | 716 |
| 777 if (cmd == @selector(insertBacktab:) && | 717 if (cmd == @selector(insertBacktab:) && |
| 778 model_->popup_model()->selected_line_state() == | 718 model()->popup_model()->selected_line_state() == |
| 779 OmniboxPopupModel::KEYWORD) { | 719 OmniboxPopupModel::KEYWORD) { |
| 780 model_->ClearKeyword(GetText()); | 720 model()->ClearKeyword(GetText()); |
| 781 return true; | 721 return true; |
| 782 } | 722 } |
| 783 } | 723 } |
| 784 | 724 |
| 785 if (cmd == @selector(moveRight:)) { | 725 if (cmd == @selector(moveRight:)) { |
| 786 // Only commit suggested text if the cursor is all the way to the right and | 726 // Only commit suggested text if the cursor is all the way to the right and |
| 787 // there is no selection. | 727 // there is no selection. |
| 788 if (suggest_text_length_ > 0 && IsCaretAtEnd()) { | 728 if (suggest_text_length_ > 0 && IsCaretAtEnd()) { |
| 789 model_->CommitSuggestedText(true); | 729 model()->CommitSuggestedText(true); |
| 790 return true; | 730 return true; |
| 791 } | 731 } |
| 792 } | 732 } |
| 793 | 733 |
| 794 if (cmd == @selector(scrollPageDown:)) { | 734 if (cmd == @selector(scrollPageDown:)) { |
| 795 model_->OnUpOrDownKeyPressed(model_->result().size()); | 735 model()->OnUpOrDownKeyPressed(model()->result().size()); |
| 796 return true; | 736 return true; |
| 797 } | 737 } |
| 798 | 738 |
| 799 if (cmd == @selector(scrollPageUp:)) { | 739 if (cmd == @selector(scrollPageUp:)) { |
| 800 model_->OnUpOrDownKeyPressed(-model_->result().size()); | 740 model()->OnUpOrDownKeyPressed(-model()->result().size()); |
| 801 return true; | 741 return true; |
| 802 } | 742 } |
| 803 | 743 |
| 804 if (cmd == @selector(cancelOperation:)) { | 744 if (cmd == @selector(cancelOperation:)) { |
| 805 return model_->OnEscapeKeyPressed(); | 745 return model()->OnEscapeKeyPressed(); |
| 806 } | 746 } |
| 807 | 747 |
| 808 if ((cmd == @selector(insertTab:) || | 748 if ((cmd == @selector(insertTab:) || |
| 809 cmd == @selector(insertTabIgnoringFieldEditor:)) && | 749 cmd == @selector(insertTabIgnoringFieldEditor:)) && |
| 810 model_->is_keyword_hint()) { | 750 model()->is_keyword_hint()) { |
| 811 return model_->AcceptKeyword(); | 751 return model()->AcceptKeyword(); |
| 812 } | 752 } |
| 813 | 753 |
| 814 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op | 754 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op |
| 815 // behavior with the proper WindowOpenDisposition. | 755 // behavior with the proper WindowOpenDisposition. |
| 816 NSEvent* event = [NSApp currentEvent]; | 756 NSEvent* event = [NSApp currentEvent]; |
| 817 if (cmd == @selector(insertNewline:) || | 757 if (cmd == @selector(insertNewline:) || |
| 818 (cmd == @selector(noop:) && | 758 (cmd == @selector(noop:) && |
| 819 ([event type] == NSKeyDown || [event type] == NSKeyUp) && | 759 ([event type] == NSKeyDown || [event type] == NSKeyUp) && |
| 820 [event keyCode] == kVK_Return)) { | 760 [event keyCode] == kVK_Return)) { |
| 821 WindowOpenDisposition disposition = | 761 WindowOpenDisposition disposition = |
| 822 event_utils::WindowOpenDispositionFromNSEvent(event); | 762 event_utils::WindowOpenDispositionFromNSEvent(event); |
| 823 model_->AcceptInput(disposition, false); | 763 model()->AcceptInput(disposition, false); |
| 824 // Opening a URL in a background tab should also revert the omnibox contents | 764 // Opening a URL in a background tab should also revert the omnibox contents |
| 825 // to their original state. We cannot do a blanket revert in OpenURL() | 765 // to their original state. We cannot do a blanket revert in OpenURL() |
| 826 // because middle-clicks also open in a new background tab, but those should | 766 // because middle-clicks also open in a new background tab, but those should |
| 827 // not revert the omnibox text. | 767 // not revert the omnibox text. |
| 828 RevertAll(); | 768 RevertAll(); |
| 829 return true; | 769 return true; |
| 830 } | 770 } |
| 831 | 771 |
| 832 // Option-Return | 772 // Option-Return |
| 833 if (cmd == @selector(insertNewlineIgnoringFieldEditor:)) { | 773 if (cmd == @selector(insertNewlineIgnoringFieldEditor:)) { |
| 834 model_->AcceptInput(NEW_FOREGROUND_TAB, false); | 774 model()->AcceptInput(NEW_FOREGROUND_TAB, false); |
| 835 return true; | 775 return true; |
| 836 } | 776 } |
| 837 | 777 |
| 838 // When the user does Control-Enter, the existing content has "www." | 778 // When the user does Control-Enter, the existing content has "www." |
| 839 // prepended and ".com" appended. |model_| should already have | 779 // prepended and ".com" appended. model() should already have |
| 840 // received notification when the Control key was depressed, but it | 780 // received notification when the Control key was depressed, but it |
| 841 // is safe to tell it twice. | 781 // is safe to tell it twice. |
| 842 if (cmd == @selector(insertLineBreak:)) { | 782 if (cmd == @selector(insertLineBreak:)) { |
| 843 OnControlKeyChanged(true); | 783 OnControlKeyChanged(true); |
| 844 WindowOpenDisposition disposition = | 784 WindowOpenDisposition disposition = |
| 845 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); | 785 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); |
| 846 model_->AcceptInput(disposition, false); | 786 model()->AcceptInput(disposition, false); |
| 847 return true; | 787 return true; |
| 848 } | 788 } |
| 849 | 789 |
| 850 if (cmd == @selector(deleteBackward:)) { | 790 if (cmd == @selector(deleteBackward:)) { |
| 851 if (OnBackspacePressed()) { | 791 if (OnBackspacePressed()) { |
| 852 return true; | 792 return true; |
| 853 } | 793 } |
| 854 } | 794 } |
| 855 | 795 |
| 856 if (cmd == @selector(deleteForward:)) { | 796 if (cmd == @selector(deleteForward:)) { |
| 857 const NSUInteger modifiers = [[NSApp currentEvent] modifierFlags]; | 797 const NSUInteger modifiers = [[NSApp currentEvent] modifierFlags]; |
| 858 if ((modifiers & NSShiftKeyMask) != 0) { | 798 if ((modifiers & NSShiftKeyMask) != 0) { |
| 859 if (model_->popup_model()->IsOpen()) { | 799 if (model()->popup_model()->IsOpen()) { |
| 860 model_->popup_model()->TryDeletingCurrentItem(); | 800 model()->popup_model()->TryDeletingCurrentItem(); |
| 861 return true; | 801 return true; |
| 862 } | 802 } |
| 863 } | 803 } |
| 864 } | 804 } |
| 865 | 805 |
| 866 return false; | 806 return false; |
| 867 } | 807 } |
| 868 | 808 |
| 869 void OmniboxViewMac::OnSetFocus(bool control_down) { | 809 void OmniboxViewMac::OnSetFocus(bool control_down) { |
| 870 model_->OnSetFocus(control_down); | 810 model()->OnSetFocus(control_down); |
| 871 controller_->OnSetFocus(); | 811 controller()->OnSetFocus(); |
| 872 } | 812 } |
| 873 | 813 |
| 874 void OmniboxViewMac::OnKillFocus() { | 814 void OmniboxViewMac::OnKillFocus() { |
| 875 // Tell the model to reset itself. | 815 // Tell the model to reset itself. |
| 876 model_->OnWillKillFocus(NULL); | 816 model()->OnWillKillFocus(NULL); |
| 877 model_->OnKillFocus(); | 817 model()->OnKillFocus(); |
| 878 controller_->OnKillFocus(); | 818 controller()->OnKillFocus(); |
| 879 } | 819 } |
| 880 | 820 |
| 881 bool OmniboxViewMac::CanCopy() { | 821 bool OmniboxViewMac::CanCopy() { |
| 882 const NSRange selection = GetSelectedRange(); | 822 const NSRange selection = GetSelectedRange(); |
| 883 return selection.length > 0; | 823 return selection.length > 0; |
| 884 } | 824 } |
| 885 | 825 |
| 886 void OmniboxViewMac::CopyToPasteboard(NSPasteboard* pb) { | 826 void OmniboxViewMac::CopyToPasteboard(NSPasteboard* pb) { |
| 887 DCHECK(CanCopy()); | 827 DCHECK(CanCopy()); |
| 888 | 828 |
| 889 const NSRange selection = GetSelectedRange(); | 829 const NSRange selection = GetSelectedRange(); |
| 890 string16 text = base::SysNSStringToUTF16( | 830 string16 text = base::SysNSStringToUTF16( |
| 891 [[field_ stringValue] substringWithRange:selection]); | 831 [[field_ stringValue] substringWithRange:selection]); |
| 892 | 832 |
| 893 GURL url; | 833 GURL url; |
| 894 bool write_url = false; | 834 bool write_url = false; |
| 895 model_->AdjustTextForCopy(selection.location, IsSelectAll(), &text, &url, | 835 model()->AdjustTextForCopy(selection.location, IsSelectAll(), &text, &url, |
| 896 &write_url); | 836 &write_url); |
| 897 | 837 |
| 898 NSString* nstext = base::SysUTF16ToNSString(text); | 838 NSString* nstext = base::SysUTF16ToNSString(text); |
| 899 [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; | 839 [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; |
| 900 [pb setString:nstext forType:NSStringPboardType]; | 840 [pb setString:nstext forType:NSStringPboardType]; |
| 901 | 841 |
| 902 if (write_url) { | 842 if (write_url) { |
| 903 [pb declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:nil]; | 843 [pb declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:nil]; |
| 904 [pb setDataForURL:base::SysUTF8ToNSString(url.spec()) title:nstext]; | 844 [pb setDataForURL:base::SysUTF8ToNSString(url.spec()) title:nstext]; |
| 905 } | 845 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 918 // -shouldChangeTextInRange:* and -didChangeText are documented in | 858 // -shouldChangeTextInRange:* and -didChangeText are documented in |
| 919 // NSTextView as things you need to do if you write additional | 859 // NSTextView as things you need to do if you write additional |
| 920 // user-initiated editing functions. They cause the appropriate | 860 // user-initiated editing functions. They cause the appropriate |
| 921 // delegate methods to be called. | 861 // delegate methods to be called. |
| 922 // TODO(shess): It would be nice to separate the Cocoa-specific code | 862 // TODO(shess): It would be nice to separate the Cocoa-specific code |
| 923 // from the Chrome-specific code. | 863 // from the Chrome-specific code. |
| 924 NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]); | 864 NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]); |
| 925 const NSRange selectedRange = GetSelectedRange(); | 865 const NSRange selectedRange = GetSelectedRange(); |
| 926 if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) { | 866 if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) { |
| 927 // Record this paste, so we can do different behavior. | 867 // Record this paste, so we can do different behavior. |
| 928 model_->on_paste(); | 868 model()->on_paste(); |
| 929 | 869 |
| 930 // Force a Paste operation to trigger the text_changed code in | 870 // Force a Paste operation to trigger the text_changed code in |
| 931 // OnAfterPossibleChange(), even if identical contents are pasted | 871 // OnAfterPossibleChange(), even if identical contents are pasted |
| 932 // into the text box. | 872 // into the text box. |
| 933 text_before_change_.clear(); | 873 text_before_change_.clear(); |
| 934 | 874 |
| 935 [editor replaceCharactersInRange:selectedRange withString:s]; | 875 [editor replaceCharactersInRange:selectedRange withString:s]; |
| 936 [editor didChangeText]; | 876 [editor didChangeText]; |
| 937 } | 877 } |
| 938 } | 878 } |
| 939 | 879 |
| 940 bool OmniboxViewMac::CanPasteAndGo() { | 880 bool OmniboxViewMac::CanPasteAndGo() { |
| 941 return model_->CanPasteAndGo(GetClipboardText()); | 881 return model()->CanPasteAndGo(GetClipboardText()); |
| 942 } | 882 } |
| 943 | 883 |
| 944 int OmniboxViewMac::GetPasteActionStringId() { | 884 int OmniboxViewMac::GetPasteActionStringId() { |
| 945 string16 text(GetClipboardText()); | 885 string16 text(GetClipboardText()); |
| 946 DCHECK(model_->CanPasteAndGo(text)); | 886 DCHECK(model()->CanPasteAndGo(text)); |
| 947 return model_->IsPasteAndSearch(GetClipboardText()) ? | 887 return model()->IsPasteAndSearch(GetClipboardText()) ? |
| 948 IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO; | 888 IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO; |
| 949 } | 889 } |
| 950 | 890 |
| 951 void OmniboxViewMac::OnPasteAndGo() { | 891 void OmniboxViewMac::OnPasteAndGo() { |
| 952 string16 text(GetClipboardText()); | 892 string16 text(GetClipboardText()); |
| 953 if (model_->CanPasteAndGo(text)) | 893 if (model()->CanPasteAndGo(text)) |
| 954 model_->PasteAndGo(text); | 894 model()->PasteAndGo(text); |
| 955 } | 895 } |
| 956 | 896 |
| 957 void OmniboxViewMac::OnFrameChanged() { | 897 void OmniboxViewMac::OnFrameChanged() { |
| 958 // TODO(shess): UpdatePopupAppearance() is called frequently, so it | 898 // TODO(shess): UpdatePopupAppearance() is called frequently, so it |
| 959 // should be really cheap, but in this case we could probably make | 899 // should be really cheap, but in this case we could probably make |
| 960 // things even cheaper by refactoring between the popup-placement | 900 // things even cheaper by refactoring between the popup-placement |
| 961 // code and the matrix-population code. | 901 // code and the matrix-population code. |
| 962 popup_view_->UpdatePopupAppearance(); | 902 popup_view_->UpdatePopupAppearance(); |
| 963 model_->PopupBoundsChangedTo(popup_view_->GetTargetBounds()); | 903 model()->PopupBoundsChangedTo(popup_view_->GetTargetBounds()); |
| 964 | 904 |
| 965 // Give controller a chance to rearrange decorations. | 905 // Give controller a chance to rearrange decorations. |
| 966 model_->OnChanged(); | 906 model()->OnChanged(); |
| 907 } |
| 908 |
| 909 void OmniboxViewMac::ClosePopup() { |
| 910 OmniboxView::CloseOmniboxPopup(); |
| 967 } | 911 } |
| 968 | 912 |
| 969 bool OmniboxViewMac::OnBackspacePressed() { | 913 bool OmniboxViewMac::OnBackspacePressed() { |
| 970 // Don't intercept if not in keyword search mode. | 914 // Don't intercept if not in keyword search mode. |
| 971 if (model_->is_keyword_hint() || model_->keyword().empty()) { | 915 if (model()->is_keyword_hint() || model()->keyword().empty()) { |
| 972 return false; | 916 return false; |
| 973 } | 917 } |
| 974 | 918 |
| 975 // Don't intercept if there is a selection, or the cursor isn't at | 919 // Don't intercept if there is a selection, or the cursor isn't at |
| 976 // the leftmost position. | 920 // the leftmost position. |
| 977 const NSRange selection = GetSelectedRange(); | 921 const NSRange selection = GetSelectedRange(); |
| 978 if (selection.length > 0 || selection.location > 0) { | 922 if (selection.length > 0 || selection.location > 0) { |
| 979 return false; | 923 return false; |
| 980 } | 924 } |
| 981 | 925 |
| 982 // We're showing a keyword and the user pressed backspace at the | 926 // We're showing a keyword and the user pressed backspace at the |
| 983 // beginning of the text. Delete the selected keyword. | 927 // beginning of the text. Delete the selected keyword. |
| 984 model_->ClearKeyword(GetText()); | 928 model()->ClearKeyword(GetText()); |
| 985 return true; | 929 return true; |
| 986 } | 930 } |
| 987 | 931 |
| 988 NSRange OmniboxViewMac::SelectionRangeForProposedRange(NSRange proposed_range) { | 932 NSRange OmniboxViewMac::SelectionRangeForProposedRange(NSRange proposed_range) { |
| 989 // Should never call this function unless editing is in progress. | 933 // Should never call this function unless editing is in progress. |
| 990 DCHECK([field_ currentEditor]); | 934 DCHECK([field_ currentEditor]); |
| 991 | 935 |
| 992 if (![field_ currentEditor]) | 936 if (![field_ currentEditor]) |
| 993 return proposed_range; | 937 return proposed_range; |
| 994 | 938 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1006 if (start > max) | 950 if (start > max) |
| 1007 start = max; | 951 start = max; |
| 1008 | 952 |
| 1009 if (end > max) | 953 if (end > max) |
| 1010 end = max; | 954 end = max; |
| 1011 | 955 |
| 1012 return NSMakeRange(start, end - start); | 956 return NSMakeRange(start, end - start); |
| 1013 } | 957 } |
| 1014 | 958 |
| 1015 void OmniboxViewMac::OnControlKeyChanged(bool pressed) { | 959 void OmniboxViewMac::OnControlKeyChanged(bool pressed) { |
| 1016 model_->OnControlKeyChanged(pressed); | 960 model()->OnControlKeyChanged(pressed); |
| 1017 } | 961 } |
| 1018 | 962 |
| 1019 void OmniboxViewMac::FocusLocation(bool select_all) { | 963 void OmniboxViewMac::FocusLocation(bool select_all) { |
| 1020 if ([field_ isEditable]) { | 964 if ([field_ isEditable]) { |
| 1021 // If the text field has a field editor, it's the first responder, meaning | 965 // If the text field has a field editor, it's the first responder, meaning |
| 1022 // that it's already focused. makeFirstResponder: will select all, so only | 966 // that it's already focused. makeFirstResponder: will select all, so only |
| 1023 // call it if this behavior is desired. | 967 // call it if this behavior is desired. |
| 1024 if (select_all || ![field_ currentEditor]) | 968 if (select_all || ![field_ currentEditor]) |
| 1025 [[field_ window] makeFirstResponder:field_]; | 969 [[field_ window] makeFirstResponder:field_]; |
| 1026 DCHECK_EQ([field_ currentEditor], [[field_ window] firstResponder]); | 970 DCHECK_EQ([field_ currentEditor], [[field_ window] firstResponder]); |
| 1027 } | 971 } |
| 1028 } | 972 } |
| 1029 | 973 |
| 1030 // static | 974 // static |
| 1031 NSFont* OmniboxViewMac::GetFieldFont() { | 975 NSFont* OmniboxViewMac::GetFieldFont() { |
| 1032 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 976 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 1033 return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont(); | 977 return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont(); |
| 1034 } | 978 } |
| 1035 | 979 |
| 980 int OmniboxViewMac::GetOmniboxTextLength() const { |
| 981 return static_cast<int>(GetTextLength()); |
| 982 } |
| 983 |
| 1036 NSUInteger OmniboxViewMac::GetTextLength() const { | 984 NSUInteger OmniboxViewMac::GetTextLength() const { |
| 1037 return ([field_ currentEditor] ? | 985 return ([field_ currentEditor] ? |
| 1038 [[[field_ currentEditor] string] length] : | 986 [[[field_ currentEditor] string] length] : |
| 1039 [[field_ stringValue] length]) - suggest_text_length_; | 987 [[field_ stringValue] length]) - suggest_text_length_; |
| 1040 } | 988 } |
| 1041 | 989 |
| 1042 void OmniboxViewMac::PlaceCaretAt(NSUInteger pos) { | |
| 1043 DCHECK(pos <= GetTextLength()); | |
| 1044 SetSelectedRange(NSMakeRange(pos, pos)); | |
| 1045 } | |
| 1046 | |
| 1047 bool OmniboxViewMac::IsCaretAtEnd() const { | 990 bool OmniboxViewMac::IsCaretAtEnd() const { |
| 1048 const NSRange selection = GetSelectedRange(); | 991 const NSRange selection = GetSelectedRange(); |
| 1049 return selection.length == 0 && selection.location == GetTextLength(); | 992 return selection.length == 0 && selection.location == GetTextLength(); |
| 1050 } | 993 } |
| OLD | NEW |