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 |