1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/base/cocoa/base_view.h"
7 NSString* kViewDidBecomeFirstResponder =
8 @"Chromium.kViewDidBecomeFirstResponder";
9 NSString* kSelectionDirection = @"Chromium.kSelectionDirection";
11 @implementation BaseView
13 - (instancetype)initWithFrame:(NSRect)frame {
14 if ((self = [super initWithFrame:frame])) {
15 [self enableTracking];
20 - (instancetype)initWithCoder:(NSCoder*)decoder {
21 if ((self = [super initWithCoder:decoder])) {
22 [self enableTracking];
28 [self disableTracking];
32 - (void)enableTracking {
33 if (trackingArea_.get())
36 NSTrackingAreaOptions trackingOptions = NSTrackingMouseEnteredAndExited |
37 NSTrackingMouseMoved |
38 NSTrackingActiveAlways |
39 NSTrackingInVisibleRect;
40 trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
41 options:trackingOptions
44 [self addTrackingArea:trackingArea_.get()];
47 - (void)disableTracking {
48 if (trackingArea_.get()) {
49 [self removeTrackingArea:trackingArea_.get()];
50 trackingArea_.reset();
54 - (void)viewDidEndLiveResize {
55 [super viewDidEndLiveResize];
57 // NSTrackingInVisibleRect doesn't work correctly with Lion's window resizing,
58 // http://crbug.com/176725 / http://openradar.appspot.com/radar?id=2773401 .
59 // Work around it by reinstalling the tracking area after window resize.
60 [self disableTracking];
61 [self enableTracking];
64 - (void)mouseEvent:(NSEvent*)theEvent {
65 // This method left intentionally blank.
68 - (EventHandled)keyEvent:(NSEvent*)theEvent {
69 // The default implementation of this method does not handle any key events.
70 // Derived classes should return kEventHandled if they handled an event,
71 // otherwise it will be forwarded on to |super|.
72 return kEventNotHandled;
75 - (void)mouseDown:(NSEvent*)theEvent {
77 [self mouseEvent:theEvent];
80 - (void)rightMouseDown:(NSEvent*)theEvent {
81 [self mouseEvent:theEvent];
84 - (void)otherMouseDown:(NSEvent*)theEvent {
85 [self mouseEvent:theEvent];
88 - (void)mouseUp:(NSEvent*)theEvent {
89 [self mouseEvent:theEvent];
92 if (pendingExitEvent_.get()) {
94 [NSEvent enterExitEventWithType:NSMouseExited
95 location:[theEvent locationInWindow]
96 modifierFlags:[theEvent modifierFlags]
97 timestamp:[theEvent timestamp]
98 windowNumber:[theEvent windowNumber]
99 context:[theEvent context]
100 eventNumber:[pendingExitEvent_.get() eventNumber]
101 trackingNumber:[pendingExitEvent_.get() trackingNumber]
102 userData:[pendingExitEvent_.get() userData]];
103 [self mouseEvent:exitEvent];
104 pendingExitEvent_.reset();
108 - (void)rightMouseUp:(NSEvent*)theEvent {
109 [self mouseEvent:theEvent];
112 - (void)otherMouseUp:(NSEvent*)theEvent {
113 [self mouseEvent:theEvent];
116 - (void)mouseMoved:(NSEvent*)theEvent {
117 [self mouseEvent:theEvent];
120 - (void)mouseDragged:(NSEvent*)theEvent {
121 [self mouseEvent:theEvent];
124 - (void)rightMouseDragged:(NSEvent*)theEvent {
125 [self mouseEvent:theEvent];
128 - (void)otherMouseDragged:(NSEvent*)theEvent {
129 [self mouseEvent:theEvent];
132 - (void)mouseEntered:(NSEvent*)theEvent {
133 if (pendingExitEvent_.get()) {
134 pendingExitEvent_.reset();
138 [self mouseEvent:theEvent];
141 - (void)mouseExited:(NSEvent*)theEvent {
142 // The tracking area will send an exit event even during a drag, which isn't
143 // how the event flow for drags should work. This stores the exit event, and
144 // sends it when the drag completes instead.
146 pendingExitEvent_.reset([theEvent retain]);
150 [self mouseEvent:theEvent];
153 - (void)keyDown:(NSEvent*)theEvent {
154 if ([self keyEvent:theEvent] != kEventHandled)
155 [super keyDown:theEvent];
158 - (void)keyUp:(NSEvent*)theEvent {
159 if ([self keyEvent:theEvent] != kEventHandled)
160 [super keyUp:theEvent];
163 - (void)flagsChanged:(NSEvent*)theEvent {
164 if ([self keyEvent:theEvent] != kEventHandled)
165 [super flagsChanged:theEvent];
168 - (gfx::Rect)flipNSRectToRect:(NSRect)rect {
169 gfx::Rect new_rect(NSRectToCGRect(rect));
170 new_rect.set_y(NSHeight([self bounds]) - new_rect.bottom());
174 - (NSRect)flipRectToNSRect:(gfx::Rect)rect {
175 NSRect new_rect(NSRectFromCGRect(rect.ToCGRect()));
176 new_rect.origin.y = NSHeight([self bounds]) - NSMaxY(new_rect);