diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-17 04:07:50 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-17 04:07:50 +0000 |
commit | da80205aeedefe6a562113bf86b13c5714dcdc82 (patch) | |
tree | 19b8a32cc1dca9ac4a235c373118a3945b0bd1ac | |
parent | aaf124502e4c86acf98b88998fca3afcdb88a234 (diff) | |
download | chromium_src-da80205aeedefe6a562113bf86b13c5714dcdc82.zip chromium_src-da80205aeedefe6a562113bf86b13c5714dcdc82.tar.gz chromium_src-da80205aeedefe6a562113bf86b13c5714dcdc82.tar.bz2 |
[Mac] Allow omnibox decorations to decline mouse events.
Certain decorations like the keyword-search bubble let mouse events
fall through to the field, as indicated by an i-beam cursor. This
change causes decorations next to the text area to be aggregated into
the text-area's cursor rect.
BUG=41612
TEST=Keyword-search bubble shows I-beam cursor.
TEST=Location icon and star and page actions show arrow.
Review URL: http://codereview.chromium.org/2825048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52807 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 65 insertions, 16 deletions
diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field.mm index 041cff8..6464510 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field.mm +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field.mm @@ -204,19 +204,6 @@ [undoManager_ removeAllActions]; } -// Show the I-beam cursor unless the mouse is over an image within the field -// (Page Actions or the security icon) in which case show the arrow cursor. -// TODO(rohitrao): Should default to the arrow cursor. http://crbug.com/41612 -- (void)resetCursorRects { - NSRect fieldBounds = [self bounds]; - [self addCursorRect:fieldBounds cursor:[NSCursor IBeamCursor]]; - - // TODO(shess): This needs to traverse the LocationBarDecorations - // and put up a cursor for them, too. Except for the keyword-search - // stuff? Sigh. - // http://crbug.com/48867 -} - // TODO(shess): -resetFieldEditorFrameIfNeeded is the place where // changes to the cell layout should be flushed. LocationBarViewMac // and ToolbarController are calling this routine directly, and I diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.h b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.h index cbb3e63..d1150e2 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.h +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.h @@ -82,6 +82,11 @@ class LocationBarDecoration; inRect:(NSRect)cellFrame ofView:(AutocompleteTextField*)controlView; +// Overridden from StyledTextFieldCell to include decorations adjacent +// to the text area which don't handle mouse clicks themselves. +// Keyword-search bubble, for instance. +- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame; + @end // Internal methods here exposed for unit testing. diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm index 3d62be6..4e46456 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm @@ -167,7 +167,9 @@ void CalculatePositionsHelper( // |decorations| will contain the resulting visible decorations, and // |decoration_frames| will contain their frames in the same // coordinates as |frame|. Decorations will be ordered left to right. -void CalculatePositionsInFrame( +// As a convenience returns the index of the first right-hand +// decoration. +size_t CalculatePositionsInFrame( NSRect frame, const std::vector<LocationBarDecoration*>& left_decorations, const std::vector<LocationBarDecoration*>& right_decorations, @@ -199,6 +201,7 @@ void CalculatePositionsInFrame( decoration_frames->end()); *remaining_frame = frame; + return left_count; } } // namespace @@ -386,6 +389,46 @@ void CalculatePositionsInFrame( return textFrame; } +- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame { + std::vector<LocationBarDecoration*> decorations; + std::vector<NSRect> decorationFrames; + NSRect textFrame; + size_t left_count = + CalculatePositionsInFrame(cellFrame, leftDecorations_, rightDecorations_, + &decorations, &decorationFrames, &textFrame); + + // Determine the left-most extent for the i-beam cursor. + CGFloat minX = NSMinX(textFrame); + for (size_t index = left_count; index--; ) { + if (decorations[index]->AcceptsMousePress()) + break; + + // If at leftmost decoration, expand to edge of cell. + if (!index) { + minX = NSMinX(cellFrame); + } else { + minX = NSMinX(decorationFrames[index]) - kDecorationHorizontalPad; + } + } + + // Determine the right-most extent for the i-beam cursor. + CGFloat maxX = NSMaxX(textFrame); + for (size_t index = left_count; index < decorations.size(); ++index) { + if (decorations[index]->AcceptsMousePress()) + break; + + // If at rightmost decoration, expand to edge of cell. + if (index == decorations.size() - 1) { + maxX = NSMaxX(cellFrame); + } else { + maxX = NSMaxX(decorationFrames[index]) + kDecorationHorizontalPad; + } + } + + // I-beam cursor covers left-most to right-most. + return NSMakeRect(minX, NSMinY(textFrame), maxX - minX, NSHeight(textFrame)); +} + - (void)drawHintWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { DCHECK(hintString_); @@ -466,7 +509,7 @@ void CalculatePositionsInFrame( ofView:(AutocompleteTextField*)controlView { LocationBarDecoration* decoration = [self decorationForEvent:theEvent inRect:cellFrame ofView:controlView]; - if (!decoration) + if (!decoration || !decoration->AcceptsMousePress()) return NO; NSRect decorationRect = diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm index d3a4bfd..6dfa50b 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell_unittest.mm @@ -178,6 +178,7 @@ TEST_F(AutocompleteTextFieldCellTest, TextFrame) { // The cursor frame should stay the same throughout. const NSRect cursorFrame([cell textCursorFrameForFrame:bounds]); + EXPECT_TRUE(NSEqualRects(cursorFrame, bounds)); // At default settings, everything goes to the text area. textFrame = [cell textFrameForFrame:bounds]; @@ -185,7 +186,7 @@ TEST_F(AutocompleteTextFieldCellTest, TextFrame) { EXPECT_TRUE(NSContainsRect(bounds, textFrame)); EXPECT_EQ(NSMinX(bounds), NSMinX(textFrame)); EXPECT_EQ(NSMaxX(bounds), NSMaxX(textFrame)); - EXPECT_TRUE(NSEqualRects(cursorFrame, textFrame)); + EXPECT_TRUE(NSContainsRect(cursorFrame, textFrame)); // Small search hint leaves text frame to left. [cell setSearchHintString:@"Search hint" availableWidth:kWidth]; diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm index 64ffbd8..8e27682 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_unittest.mm @@ -32,6 +32,7 @@ class MockDecoration : public LocationBarDecoration { void SetVisible(bool visible) { visible_ = visible; } virtual void DrawInFrame(NSRect frame, NSView* control_view) { ; } + virtual bool AcceptsMousePress() { return true; } MOCK_METHOD1(OnMousePressed, bool(NSRect frame)); MOCK_METHOD0(GetMenu, NSMenu*()); diff --git a/chrome/browser/cocoa/location_bar/content_setting_decoration.h b/chrome/browser/cocoa/location_bar/content_setting_decoration.h index 9ff6eda..bba2140 100644 --- a/chrome/browser/cocoa/location_bar/content_setting_decoration.h +++ b/chrome/browser/cocoa/location_bar/content_setting_decoration.h @@ -28,6 +28,7 @@ class ContentSettingDecoration : public ImageDecoration { void UpdateFromTabContents(const TabContents* tab_contents); // Overridden from |LocationBarDecoration| + virtual bool AcceptsMousePress() { return true; } virtual bool OnMousePressed(NSRect frame); virtual NSString* GetToolTip(); diff --git a/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h b/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h index ea1697a..0cdd960 100644 --- a/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h +++ b/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h @@ -29,6 +29,7 @@ class EVBubbleDecoration : public BubbleDecoration { virtual NSPasteboard* GetDragPasteboard(); virtual NSImage* GetDragImage(); virtual bool OnMousePressed(NSRect frame); + virtual bool AcceptsMousePress() { return true; } private: LocationIconDecoration* location_icon_; // weak, owned by location bar. diff --git a/chrome/browser/cocoa/location_bar/location_bar_decoration.h b/chrome/browser/cocoa/location_bar/location_bar_decoration.h index 9500e42..51571cc 100644 --- a/chrome/browser/cocoa/location_bar/location_bar_decoration.h +++ b/chrome/browser/cocoa/location_bar/location_bar_decoration.h @@ -46,6 +46,13 @@ class LocationBarDecoration { // Returns the tooltip for this decoration, return |nil| for no tooltip. virtual NSString* GetToolTip() { return nil; } + // Decorations which do not accept mouse events are treated like the + // field's background for purposes of selecting text. When such + // decorations are adjacent to the text area, they will show the + // I-beam cursor. Decorations which do accept mouse events will get + // an arrow cursor when the mouse is over them. + virtual bool AcceptsMousePress() { return false; } + // Determine if the item can act as a drag source. virtual bool IsDraggable() { return false; } diff --git a/chrome/browser/cocoa/location_bar/location_icon_decoration.h b/chrome/browser/cocoa/location_bar/location_icon_decoration.h index 18952d2..9d705a8 100644 --- a/chrome/browser/cocoa/location_bar/location_icon_decoration.h +++ b/chrome/browser/cocoa/location_bar/location_icon_decoration.h @@ -26,6 +26,7 @@ class LocationIconDecoration : public ImageDecoration { // Show the page info panel on click. virtual bool OnMousePressed(NSRect frame); + virtual bool AcceptsMousePress() { return true; } private: // The location bar view that owns us. diff --git a/chrome/browser/cocoa/location_bar/page_action_decoration.h b/chrome/browser/cocoa/location_bar/page_action_decoration.h index 17a7e33..7bbf443 100644 --- a/chrome/browser/cocoa/location_bar/page_action_decoration.h +++ b/chrome/browser/cocoa/location_bar/page_action_decoration.h @@ -50,6 +50,7 @@ class PageActionDecoration : public ImageDecoration, NSPoint GetBubblePointInFrame(NSRect frame); // Overridden from |LocationBarDecoration| + virtual bool AcceptsMousePress() { return true; } virtual bool OnMousePressed(NSRect frame); virtual NSString* GetToolTip(); virtual NSMenu* GetMenu(); diff --git a/chrome/browser/cocoa/location_bar/star_decoration.h b/chrome/browser/cocoa/location_bar/star_decoration.h index e39f9a8..6fbe91d 100644 --- a/chrome/browser/cocoa/location_bar/star_decoration.h +++ b/chrome/browser/cocoa/location_bar/star_decoration.h @@ -26,6 +26,7 @@ class StarDecoration : public ImageDecoration { NSPoint GetBubblePointInFrame(NSRect frame); // Implement |LocationBarDecoration|. + virtual bool AcceptsMousePress() { return true; } virtual bool OnMousePressed(NSRect frame); virtual NSString* GetToolTip(); |