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