Commit 9b142396 authored by erikchen's avatar erikchen Committed by Commit bot

Mac: Clicking an omnibox decoration should not highlight the omnibox.

Prior to this CL, the AutocompleteTextField becomes first responder if the user
left-clicks a decoration. This is a bug that this CL fixes. This also fixes a
bug where ZeroSuggest did not disappear when the user drags the origin chip.

BUG=356887

Review URL: https://codereview.chromium.org/1011943002

Cr-Commit-Position: refs/heads/master@{#329781}
parent a04c0468
......@@ -392,6 +392,17 @@ const CGFloat kAnimationDuration = 0.2;
DCHECK_EQ([self currentEditor], [[self window] firstResponder]);
return NO;
}
// If the event is a left-mouse click, and it lands on a decoration, then the
// event should not cause the text field to become first responder.
NSEvent* event = [NSApp currentEvent];
if ([event type] == NSLeftMouseDown) {
LocationBarDecoration* decoration =
[[self cell] decorationForEvent:event inRect:[self bounds] ofView:self];
if (decoration && decoration->AcceptsMousePress())
return NO;
}
return [super acceptsFirstResponder];
}
......
......@@ -39,22 +39,6 @@ class MockDecoration : public LocationBarDecoration {
MOCK_METHOD0(GetMenu, NSMenu*());
};
class MockButtonDecoration : public ButtonDecoration {
public:
// Note: It does not matter which images are used here - but ButtonDecoration
// needs _some_ images to work properly.
MockButtonDecoration()
: ButtonDecoration(IMAGE_GRID(IDR_OMNIBOX_EV_BUBBLE),
IDR_OMNIBOX_EV_BUBBLE_CENTER,
IMAGE_GRID(IDR_OMNIBOX_EV_BUBBLE),
IDR_OMNIBOX_EV_BUBBLE_CENTER,
IMAGE_GRID(IDR_OMNIBOX_EV_BUBBLE),
IDR_OMNIBOX_EV_BUBBLE_CENTER,
3) {}
void Hide() { SetVisible(false); }
MOCK_METHOD2(OnMousePressed, bool(NSRect frame, NSPoint location));
};
// Mock up an incrementing event number.
NSUInteger eventNumber = 0;
......@@ -170,6 +154,31 @@ class AutocompleteTextFieldObserverTest : public AutocompleteTextFieldTest {
AutocompleteTextFieldTest::TearDown();
}
// Returns the center point of the decoration.
NSPoint ClickLocationForDecoration(LocationBarDecoration* decoration) {
AutocompleteTextFieldCell* cell = [field_ cell];
NSRect decoration_rect =
[cell frameForDecoration:decoration inFrame:[field_ bounds]];
EXPECT_FALSE(NSIsEmptyRect(decoration_rect));
return NSMakePoint(NSMidX(decoration_rect), NSMidY(decoration_rect));
}
void SendMouseClickToDecoration(LocationBarDecoration* decoration) {
NSPoint point = ClickLocationForDecoration(decoration);
NSEvent* downEvent = Event(field_, point, NSLeftMouseDown);
NSEvent* upEvent = Event(field_, point, NSLeftMouseUp);
// Can't just use -sendEvent:, since that doesn't populate -currentEvent.
[NSApp postEvent:downEvent atStart:YES];
[NSApp postEvent:upEvent atStart:NO];
NSEvent* next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:next_event];
}
StrictMock<MockAutocompleteTextFieldObserver> field_observer_;
};
......@@ -789,61 +798,56 @@ TEST_F(AutocompleteTextFieldTest, HideFocusState) {
EXPECT_TRUE([FieldEditor() shouldDrawInsertionPoint]);
}
// Verify that OnSetFocus for button decorations is only sent after the
// decoration is picked as the target for the subsequent -mouseDown:. Otherwise
// hiding a ButtonDecoration in OnSetFocus will prevent a call to
// OnMousePressed, since it is already hidden at the time of mouseDown.
TEST_F(AutocompleteTextFieldObserverTest, ButtonDecorationFocus) {
// Add the mock button.
MockButtonDecoration mock_button;
mock_button.SetVisible(true);
// Verify that clicking a decoration that accepts mouse clicks does not focus
// the Omnibox.
TEST_F(AutocompleteTextFieldObserverTest,
ClickingDecorationDoesNotFocusOmnibox) {
AutocompleteTextFieldCell* cell = [field_ cell];
[cell addLeftDecoration:&mock_button];
// Ensure button is hidden when OnSetFocus() is called.
EXPECT_CALL(field_observer_, OnSetFocus(false)).WillOnce(
testing::InvokeWithoutArgs(&mock_button, &MockButtonDecoration::Hide));
// Ignore incidental calls.
// Set up a non-interactive decoration.
MockDecoration noninteractive_decoration;
noninteractive_decoration.SetVisible(true);
EXPECT_CALL(noninteractive_decoration, AcceptsMousePress())
.WillRepeatedly(testing::Return(false));
[cell addLeftDecoration:&noninteractive_decoration];
// Set up an interactive decoration.
MockDecoration interactive_decoration;
EXPECT_CALL(interactive_decoration, AcceptsMousePress())
.WillRepeatedly(testing::Return(true));
interactive_decoration.SetVisible(true);
[cell addLeftDecoration:&interactive_decoration];
EXPECT_CALL(interactive_decoration, OnMousePressed(_, _))
.WillRepeatedly(testing::Return(true));
// Ignore incidental calls. The exact frequency of these calls doesn't matter
// as they are auxiliary.
EXPECT_CALL(field_observer_, SelectionRangeForProposedRange(_))
.WillRepeatedly(testing::Return(NSMakeRange(0, 0)));
EXPECT_CALL(field_observer_, OnMouseDown(_));
// Still expect an OnMousePressed on the button.
EXPECT_CALL(mock_button, OnMousePressed(_, _))
.WillOnce(testing::Return(true));
// Get click point for button decoration.
NSRect button_rect =
[cell frameForDecoration:&mock_button inFrame:[field_ bounds]];
EXPECT_FALSE(NSIsEmptyRect(button_rect));
NSPoint click_location =
NSMakePoint(NSMidX(button_rect), NSMidY(button_rect));
EXPECT_CALL(field_observer_, OnMouseDown(_)).Times(testing::AnyNumber());
EXPECT_CALL(field_observer_, OnSetFocus(false)).Times(testing::AnyNumber());
EXPECT_CALL(field_observer_, OnKillFocus()).Times(testing::AnyNumber());
EXPECT_CALL(field_observer_, OnDidEndEditing()).Times(testing::AnyNumber());
// Ensure the field is currently not first responder.
[test_window() makePretendKeyWindowAndSetFirstResponder:nil];
EXPECT_NSNE([[field_ window] firstResponder], field_);
// Execute button click event sequence.
NSEvent* downEvent = Event(field_, click_location, NSLeftMouseDown);
NSEvent* upEvent = Event(field_, click_location, NSLeftMouseUp);
// Can't just use -sendEvent:, since that doesn't populate -currentEvent.
[NSApp postEvent:downEvent atStart:YES];
[NSApp postEvent:upEvent atStart:NO];
NSEvent* next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:next_event];
// Expectations check that both OnSetFocus and OnMouseDown were called.
// Additionally, ensure button is hidden and field is firstResponder.
EXPECT_FALSE(mock_button.IsVisible());
EXPECT_TRUE(NSIsEmptyRect([cell frameForDecoration:&mock_left_decoration_
inFrame:[field_ bounds]]));
EXPECT_TRUE([base::mac::ObjCCastStrict<NSView>(
[[field_ window] firstResponder]) isDescendantOf:field_]);
NSResponder* firstResponder = [[field_ window] firstResponder];
EXPECT_FALSE(
[base::mac::ObjCCast<NSView>(firstResponder) isDescendantOf:field_]);
// Clicking an interactive decoration doesn't change the first responder.
SendMouseClickToDecoration(&interactive_decoration);
EXPECT_NSEQ(firstResponder, [[field_ window] firstResponder]);
// Clicking a non-interactive decoration focuses the Omnibox.
SendMouseClickToDecoration(&noninteractive_decoration);
firstResponder = [[field_ window] firstResponder];
EXPECT_TRUE(
[base::mac::ObjCCast<NSView>(firstResponder) isDescendantOf:field_]);
// Clicking an interactive decoration doesn't change the first responder.
SendMouseClickToDecoration(&interactive_decoration);
EXPECT_NSEQ(firstResponder, [[field_ window] firstResponder]);
}
TEST_F(AutocompleteTextFieldObserverTest, SendsEditingMessages) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment