diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-22 19:40:11 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-22 19:40:11 +0000 |
commit | 557c772943a7257f3c90cbe811c5ec1b7902a3ba (patch) | |
tree | 73d3e1463cb6d8d080a97192b546acc1272b49dc /chrome | |
parent | 29e87d6b41b1b6179d239b488be1d94ea7833c65 (diff) | |
download | chromium_src-557c772943a7257f3c90cbe811c5ec1b7902a3ba.zip chromium_src-557c772943a7257f3c90cbe811c5ec1b7902a3ba.tar.gz chromium_src-557c772943a7257f3c90cbe811c5ec1b7902a3ba.tar.bz2 |
Overhaul omnibox focus detection on Mac.
Rather than aiming to detect acquisition and loss of focus in
|field_|, just acknowledge that there are cases where |field_| has
focus but |model_| doesn't know. If |field_| has focus but no editing
has been done, then |model_| will take no action, so this is
reasonable.
Window resigning key just closes the popup, and doesn't affect
|model_| focus. Thus, there is no need to deal with acquiring focus
when the window becomes key again, and we can live fine within the
constraints of -*DidBeginEditing: and -*ShouldEndEditing:.
Added checks for |field_| being focussed in all the relevant places.
http://crbug.com/12338
Review URL: http://codereview.chromium.org/113746
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16776 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_mac.h | 24 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_mac.mm | 91 |
2 files changed, 87 insertions, 28 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h index e8d00fb..aec861c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h @@ -80,13 +80,22 @@ class AutocompleteEditViewMac : public AutocompleteEditView { virtual void OnBeforePossibleChange(); virtual bool OnAfterPossibleChange(); - // Helper functions which forward to |model_|, for use from - // AutocompleteEditHelper Objective-C class. + // Helper functions for use from AutocompleteEditHelper Objective-C + // class. void OnUpOrDownKeyPressed(bool up, bool by_page); void OnEscapeKeyPressed(); - // Only forwards to |model_| if the field_ has focus. - void OnSetFocus(bool f); - void OnKillFocus(); + + // Called when editing begins in the field, and before the results + // of any editing are communicated to |model_|. + void OnWillBeginEditing(); + + // Called when editing ends in the field. + void OnDidEndEditing(); + + // Called when the window |field_| is in loses key to clean up + // visual state (such as closing the popup). + void OnDidResignKey(); + void AcceptInput(WindowOpenDisposition disposition, bool for_drop); // Helper for LocationBarBridge. @@ -97,6 +106,11 @@ class AutocompleteEditViewMac : public AutocompleteEditView { // field has focus. NSRange GetSelectedRange() const; + // Returns true if |field_| is first-responder in the window. Used + // in various DCHECKS to make sure code is running in appropriate + // situations. + bool IsFirstResponder() const; + // Grab focus if needed and set the selection to |range|. void SetSelectedRange(const NSRange range); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm index c86fa29..3b66683 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm @@ -10,6 +10,31 @@ #include "chrome/browser/autocomplete/autocomplete_popup_view_mac.h" #include "chrome/browser/tab_contents/tab_contents.h" +// Focus-handling between |field_| and |model_| is a bit subtle. +// Other platforms detect change of focus, which is inconvenient +// without subclassing NSTextField (even with a subclass, the use of a +// field editor may complicate things). +// +// |model_| doesn't actually do anything when it gains focus, it just +// initializes. Visible activity happens only after the user edits. +// NSTextField delegate receives messages around starting and ending +// edits, so that sufcices to catch focus changes. Since all calls +// into |model_| start from AutocompleteEditViewMac, in the worst case +// we can add code to sync up the sense of focus as needed. +// +// I've added DCHECK(IsFirstResponder()) in the places which I believe +// should only be reachable when |field_| is being edited. If these +// fire, it probably means someone unexpected is calling into +// |model_|. +// +// Other platforms don't appear to have the sense of "key window" that +// Mac does (I believe their fields lose focus when the window loses +// focus). Rather than modifying focus outside the control's edit +// scope, when the window resigns key the autocomplete popup is +// closed. |model_| still believes it has focus, and the popup will +// be regenerated on the user's next edit. That seems to match how +// things work on other platforms. + namespace { // TODO(shess): This is ugly, find a better way. Using it right now @@ -98,7 +123,6 @@ NSRange ComponentToNSRange(const url_parse::Component& component) { } - initWithEditView:(AutocompleteEditViewMac*)view; - (void)windowDidResignKey:(NSNotification*)notification; -- (void)windowDidBecomeKey:(NSNotification*)notification; @end AutocompleteEditViewMac::AutocompleteEditViewMac( @@ -132,10 +156,6 @@ AutocompleteEditViewMac::AutocompleteEditViewMac( selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:[field_ window]]; - [nc addObserver:edit_helper_ - selector:@selector(windowDidBecomeKey:) - name:NSWindowDidBecomeKeyNotification - object:[field_ window]]; } AutocompleteEditViewMac::~AutocompleteEditViewMac() { @@ -399,12 +419,22 @@ void AutocompleteEditViewMac::OnRevertTemporaryText() { SetSelectedRange(saved_temporary_selection_); } +bool AutocompleteEditViewMac::IsFirstResponder() const { + return [field_ currentEditor] != nil ? true : false; +} + void AutocompleteEditViewMac::OnBeforePossibleChange() { + // We should only arrive here when the field is focussed. + DCHECK(IsFirstResponder()); + selection_before_change_ = GetSelectedRange(); text_before_change_ = GetText(); } bool AutocompleteEditViewMac::OnAfterPossibleChange() { + // We should only arrive here when the field is focussed. + DCHECK(IsFirstResponder()); + const NSRange new_selection(GetSelectedRange()); const std::wstring new_text(GetText()); const size_t length = new_text.length(); @@ -450,27 +480,50 @@ bool AutocompleteEditViewMac::OnAfterPossibleChange() { } void AutocompleteEditViewMac::OnUpOrDownKeyPressed(bool up, bool by_page) { + // We should only arrive here when the field is focussed. + DCHECK(IsFirstResponder()); + const int count = by_page ? model_->result().size() : 1; model_->OnUpOrDownKeyPressed(up ? -count : count); } + void AutocompleteEditViewMac::OnEscapeKeyPressed() { + // We should only arrive here when the field is focussed. + DCHECK(IsFirstResponder()); + model_->OnEscapeKeyPressed(); } -void AutocompleteEditViewMac::OnSetFocus(bool f) { - // Only forward if we actually do have the focus. - if ([field_ currentEditor]) { - model_->OnSetFocus(f); - } + +void AutocompleteEditViewMac::OnWillBeginEditing() { + // We should only arrive here when the field is focussed. + DCHECK([field_ currentEditor]); + + // TODO(shess): Having the control key depressed changes the desired + // TLD for autocomplete, which changes the results. Not sure if we + // can detect that without subclassing NSTextField. + const bool controlDown = false; + model_->OnSetFocus(controlDown); + + // Capture the current state. + OnBeforePossibleChange(); } -void AutocompleteEditViewMac::OnKillFocus() { - // TODO(shess): This would seem to be a job for |model_|. + +void AutocompleteEditViewMac::OnDidEndEditing() { ClosePopup(); // Tell the model to reset itself. model_->OnKillFocus(); } + +void AutocompleteEditViewMac::OnDidResignKey() { + ClosePopup(); +} + void AutocompleteEditViewMac::AcceptInput( WindowOpenDisposition disposition, bool for_drop) { + // We should only arrive here when the field is focussed. + DCHECK([field_ currentEditor]); + model_->AcceptInput(disposition, for_drop); } @@ -534,10 +587,7 @@ void AutocompleteEditViewMac::FocusLocation() { } - (void)controlTextDidBeginEditing:(NSNotification*)aNotification { - edit_view_->OnSetFocus(false); - - // Capture the current state. - edit_view_->OnBeforePossibleChange(); + edit_view_->OnWillBeginEditing(); } - (void)controlTextDidChange:(NSNotification*)aNotification { @@ -549,7 +599,7 @@ void AutocompleteEditViewMac::FocusLocation() { } - (BOOL)control:(NSControl*)control textShouldEndEditing:(NSText*)fieldEditor { - edit_view_->OnKillFocus(); + edit_view_->OnDidEndEditing(); return YES; @@ -559,12 +609,7 @@ void AutocompleteEditViewMac::FocusLocation() { // Signal that we've lost focus when the window resigns key. - (void)windowDidResignKey:(NSNotification*)notification { - edit_view_->OnKillFocus(); -} - -// Signal that we may have regained focus. -- (void)windowDidBecomeKey:(NSNotification*)notification { - edit_view_->OnSetFocus(false); + edit_view_->OnDidResignKey(); } @end |