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