summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 21:21:29 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 21:21:29 +0000
commit218236acdb72ed3fa11dee29ae2ca3341dc0d6c2 (patch)
tree97583df2914fac3f57752ca7f9fb7e3e4d2b1063 /chrome/browser/cocoa
parentc8559b7daaa7d9877fca1cf355baf62eb4c54668 (diff)
downloadchromium_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.mm83
-rw-r--r--chrome/browser/cocoa/autocomplete_text_field_cell.h6
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