diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-25 21:21:29 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-25 21:21:29 +0000 |
commit | 218236acdb72ed3fa11dee29ae2ca3341dc0d6c2 (patch) | |
tree | 97583df2914fac3f57752ca7f9fb7e3e4d2b1063 /chrome/browser/cocoa | |
parent | c8559b7daaa7d9877fca1cf355baf62eb4c54668 (diff) | |
download | chromium_src-218236acdb72ed3fa11dee29ae2ca3341dc0d6c2.zip chromium_src-218236acdb72ed3fa11dee29ae2ca3341dc0d6c2.tar.gz chromium_src-218236acdb72ed3fa11dee29ae2ca3341dc0d6c2.tar.bz2 |
OSX: Fix the select-all-on-mouse-down in Omnibox.
Getting clicks in the decoration areas right caused a change to how
clicks on the unfocused field worked. NSTextField also forwards the
event to get click-drag selection right, this does the same thing for
clicks in the decorations (other clicks are passed to super).
http://crbug.com/20142
TEST=Browse to www.google.com. Click in page. Click in omnibox
without releasing. You should get a caret insertion point.
Review URL: http://codereview.chromium.org/173362
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24325 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa')
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field.mm | 83 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_cell.h | 6 |
2 files changed, 70 insertions, 19 deletions
diff --git a/chrome/browser/cocoa/autocomplete_text_field.mm b/chrome/browser/cocoa/autocomplete_text_field.mm index c144b08..d7942e7 100644 --- a/chrome/browser/cocoa/autocomplete_text_field.mm +++ b/chrome/browser/cocoa/autocomplete_text_field.mm @@ -75,29 +75,80 @@ } } -// Clicks in the frame outside the field editor will attempt to make -// us first-responder, which will select-all. So decline -// first-responder when the field editor is active. -- (BOOL)acceptsFirstResponder { - if ([self currentEditor]) { - return NO; - } - return [super acceptsFirstResponder]; -} - // Reroute events for the decoration area to the field editor. This // will cause the cursor to be moved as close to the edge where the // event was seen as possible. // -// TODO(shess) Check this in light of the -acceptsFirstResponder -// change. It may no longer be needed. +// The reason for this code's existence is subtle. NSTextField +// implements text selection and editing in terms of a "field editor". +// This is an NSTextView which is installed as a subview of the +// control when the field becomes first responder. When the field +// editor is installed, it will get -mouseDown: events and handle +// them, rather than the text field - EXCEPT for the event which +// caused the change in first responder, or events which fall in the +// decorations outside the field editor's area. In that case, the +// default NSTextField code will setup the field editor all over +// again, which has the side effect of doing "select all" on the text. +// This effect can be observed with a normal NSTextField if you click +// in the narrow border area, and is only really a problem because in +// our case the focus ring surrounds decorations which look clickable. +// +// When the user first clicks on the field, after installing the field +// editor the default NSTextField code detects if the hit is in the +// field editor area, and if so sets the selection to {0,0} to clear +// the selection before forwarding the event to the field editor for +// processing (it will set the cursor position). This also starts the +// click-drag selection machinery. +// +// This code does the same thing for cases where the click was in the +// decoration area. This allows the user to click-drag starting from +// a decoration area and get the expected selection behaviour, +// likewise for multiple clicks in those areas. - (void)mouseDown:(NSEvent *)theEvent { - NSText* editor = [self currentEditor]; - if (editor) { - [editor mouseDown:theEvent]; - } else { + const NSPoint locationInWindow = [theEvent locationInWindow]; + const NSPoint location = [self convertPoint:locationInWindow fromView:nil]; + + const NSRect textFrame = [[self cell] textFrameForFrame:[self bounds]]; + + // A version of the textFrame which extends across the field's + // entire width. + const NSRect bounds([self bounds]); + const NSRect fullFrame(NSMakeRect(bounds.origin.x, textFrame.origin.y, + bounds.size.width, textFrame.size.height)); + + // If the mouse is in the editing area, or above or below where the + // editing area would be if we didn't add decorations, forward to + // NSTextField -mouseDown: because it does the right thing. The + // above/below test is needed because NSTextView treats mouse events + // above/below as select-to-end-in-that-direction, which makes + // things janky. + if (NSMouseInRect(location, textFrame, [self isFlipped]) || + !NSMouseInRect(location, fullFrame, [self isFlipped])) { [super mouseDown:theEvent]; + return; + } + + NSText* editor = [self currentEditor]; + + // We should only be here if we accepted first-responder status and + // have a field editor. If one of these fires, it means some + // assumptions are being broken. + DCHECK(editor != nil); + DCHECK([editor isDescendantOf:self]); + + // -becomeFirstResponder does a select-all, which we don't want + // because it can lead to a dragged-text situation. Clear the + // selection (any valid empty selection will do). + [editor setSelectedRange:NSMakeRange(0, 0)]; + + // If the event is to the right of the editing area, scroll the + // field editor to the end of the content so that the selection + // doesn't initiate from somewhere in the middle of the text. + if (location.x > NSMaxX(textFrame)) { + [editor scrollRangeToVisible:NSMakeRange([[self stringValue] length], 0)]; } + + [editor mouseDown:theEvent]; } @end diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.h b/chrome/browser/cocoa/autocomplete_text_field_cell.h index 3bcbbcf..31fa6b1 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.h +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.h @@ -56,6 +56,9 @@ - (void)setSearchHintString:(NSString*)aString; - (void)clearKeywordAndHint; +// Return the portion of the cell to use for text display. +- (NSRect)textFrameForFrame:(NSRect)cellFrame; + @end // Internal methods here exposed for unit testing. @@ -64,7 +67,4 @@ @property(readonly) NSAttributedString* keywordString; @property(readonly) NSAttributedString* hintString; -// Return the portion of the cell to use for text display. -- (NSRect)textFrameForFrame:(NSRect)cellFrame; - @end |