#import "third_party/mozilla/NSPasteboard+Utils.h"
#import "ui/base/cocoa/appkit_utils.h"
#import "ui/base/cocoa/tracking_area.h"
-#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
using extensions::FeatureSwitch;
const ui::NinePartImageIds kPopupBorderImageIds =
IMAGE_GRID(IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW);
-const ui::NinePartImageIds kNormalBorderImageIds =
- IMAGE_GRID(IDR_OMNIBOX_BORDER_AND_SHADOW);
+const ui::NinePartImageIds kNormalBorderImageIds = IMAGE_GRID(IDR_TEXTFIELD);
// How long to wait for mouse-up on the location icon before assuming
// that the user wants to drag.
// Layout |left_decorations| against the LHS.
CalculatePositionsHelper(frame, left_decorations, NSMinXEdge,
- kLeftDecorationXOffset, kLeftDecorationXOffset,
+ kLeftDecorationXOffset, edge_width,
decorations, decoration_frames, &frame);
DCHECK_EQ(decorations->size(), decoration_frames->size());
} // namespace
+@interface AutocompleteTextFieldCell ()
+// Post an OnSetFocus notification to the observer of |controlView|.
+- (void)focusNotificationFor:(NSEvent*)event
+ ofView:(AutocompleteTextField*)controlView;
+@end
+
@implementation AutocompleteTextFieldCell
@synthesize isPopupMode = isPopupMode_;
yRadius:kCornerRadius] fill];
}
- // Interior contents.
- [self drawInteriorWithFrame:frame inView:controlView];
-
// Border.
ui::DrawNinePartImage(frame,
isPopupMode_ ? kPopupBorderImageIds
1.0,
true);
+ // Interior contents. Drawn after the border as some of the interior controls
+ // draw over the border.
+ [self drawInteriorWithFrame:frame inView:controlView];
+
// Focus ring.
if ([self showsFirstResponder]) {
NSRect focusRingRect = NSInsetRect(frame, lineWidth, lineWidth);
// |-textFrameForFrame:|.
// Superclass draws text portion WRT original |cellFrame|.
- [super drawInteriorWithFrame:cellFrame inView:controlView];
+ // Even though -isOpaque is NO due to rounded corners, we know that the text
+ // will be drawn on top of an opaque area, therefore it is safe to enable
+ // font smoothing.
+ {
+ gfx::ScopedNSGraphicsContextSaveGState scopedGState;
+ NSGraphicsContext* context = [NSGraphicsContext currentContext];
+ CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
+ CGContextSetShouldSmoothFonts(cgContext, true);
+ [super drawInteriorWithFrame:cellFrame inView:controlView];
+ }
}
- (LocationBarDecoration*)decorationForEvent:(NSEvent*)theEvent
- (BOOL)mouseDown:(NSEvent*)theEvent
inRect:(NSRect)cellFrame
ofView:(AutocompleteTextField*)controlView {
+ // TODO(groby): Factor this into three pieces - find target for event, handle
+ // delayed focus (for any and all events), execute mouseDown for target.
+
+ // Check if this mouseDown was the reason the control became firstResponder.
+ // If not, discard focus event.
+ base::scoped_nsobject<NSEvent> focusEvent(focusEvent_.release());
+ if (![theEvent isEqual:focusEvent])
+ focusEvent.reset();
+
LocationBarDecoration* decoration =
[self decorationForEvent:theEvent inRect:cellFrame ofView:controlView];
if (!decoration || !decoration->AcceptsMousePress())
// Track the mouse until the user releases the button.
[self trackMouse:theEvent
- inRect:cellFrame
+ inRect:decorationRect
ofView:controlView
untilMouseUp:YES];
+ const NSPoint mouseLocation = [[NSApp currentEvent] locationInWindow];
+ const NSPoint point = [controlView convertPoint:mouseLocation fromView:nil];
+
+ // Post delayed focus notification, if necessary.
+ if (focusEvent.get() && !button->PreventFocus(point))
+ [self focusNotificationFor:focusEvent ofView:controlView];
+ focusEvent.reset();
+
// Set the proper state (hover or normal) once the mouse has been released,
// and call |OnMousePressed| if the button was released while the mouse was
// within the bounds of the button.
- const NSPoint mouseLocation =
- [[controlView window] mouseLocationOutsideOfEventStream];
- const NSPoint point = [controlView convertPoint:mouseLocation fromView:nil];
- if (NSMouseInRect(point, cellFrame, [controlView isFlipped])) {
+ if (NSMouseInRect(point, decorationRect, [controlView isFlipped])) {
button->SetButtonState(ButtonDecoration::kButtonStateHover);
[controlView setNeedsDisplay:YES];
- handled = decoration->AsButtonDecoration()->OnMousePressed(
- [self frameForDecoration:decoration inFrame:cellFrame]);
+ handled = decoration->OnMousePressed(
+ [self frameForDecoration:decoration inFrame:cellFrame],
+ NSMakePoint(point.x - decorationRect.origin.x,
+ point.y - decorationRect.origin.y));
} else {
button->SetButtonState(ButtonDecoration::kButtonStateNormal);
[controlView setNeedsDisplay:YES];
handled = true;
}
} else {
- handled = decoration->OnMousePressed(decorationRect);
+ const NSPoint mouseLocation = [theEvent locationInWindow];
+ const NSPoint point = [controlView convertPoint:mouseLocation fromView:nil];
+ handled = decoration->OnMousePressed(
+ decorationRect,
+ NSMakePoint(point.x - decorationRect.origin.x,
+ point.y - decorationRect.origin.y));
}
return handled ? YES : NO;
return [super showsFirstResponder] && !hideFocusState_;
}
+- (void)focusNotificationFor:(NSEvent*)event
+ ofView:(AutocompleteTextField*)controlView {
+ if ([controlView observer]) {
+ const bool controlDown = ([event modifierFlags] & NSControlKeyMask) != 0;
+ [controlView observer]->OnSetFocus(controlDown);
+ }
+}
+
+- (void)handleFocusEvent:(NSEvent*)event
+ ofView:(AutocompleteTextField*)controlView {
+ // Only intercept left button click. All other events cause immediate focus.
+ if ([event type] == NSLeftMouseDown) {
+ LocationBarDecoration* decoration =
+ [self decorationForEvent:event
+ inRect:[controlView bounds]
+ ofView:controlView];
+ // Only ButtonDecorations need a delayed focus handling.
+ if (decoration && decoration->AsButtonDecoration()) {
+ focusEvent_.reset([event retain]);
+ return;
+ }
+ }
+
+ // Handle event immediately.
+ [self focusNotificationFor:event ofView:controlView];
+}
+
@end