Home | History | Annotate | Download | only in cocoa
      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.
      4 
      5 #include "ui/base/cocoa/base_view.h"
      6 
      7 NSString* kViewDidBecomeFirstResponder =
      8     @"Chromium.kViewDidBecomeFirstResponder";
      9 NSString* kSelectionDirection = @"Chromium.kSelectionDirection";
     10 
     11 const int kTrackingOptions = NSTrackingMouseMoved |
     12                              NSTrackingMouseEnteredAndExited |
     13                              NSTrackingActiveAlways;
     14 
     15 @implementation BaseView
     16 
     17 - (void)dealloc {
     18   if (trackingArea_.get())
     19     [self removeTrackingArea:trackingArea_.get()];
     20   trackingArea_.reset(nil);
     21 
     22   [super dealloc];
     23 }
     24 
     25 - (void)mouseEvent:(NSEvent*)theEvent {
     26   // This method left intentionally blank.
     27 }
     28 
     29 - (EventHandled)keyEvent:(NSEvent*)theEvent {
     30   // The default implementation of this method does not handle any key events.
     31   // Derived classes should return kEventHandled if they handled an event,
     32   // otherwise it will be forwarded on to |super|.
     33   return kEventNotHandled;
     34 }
     35 
     36 - (void)mouseDown:(NSEvent*)theEvent {
     37   dragging_ = YES;
     38   [self mouseEvent:theEvent];
     39 }
     40 
     41 - (void)rightMouseDown:(NSEvent*)theEvent {
     42   [self mouseEvent:theEvent];
     43 }
     44 
     45 - (void)otherMouseDown:(NSEvent*)theEvent {
     46   [self mouseEvent:theEvent];
     47 }
     48 
     49 - (void)mouseUp:(NSEvent*)theEvent {
     50   [self mouseEvent:theEvent];
     51 
     52   dragging_ = NO;
     53   if (pendingExitEvent_.get()) {
     54     NSEvent* exitEvent =
     55         [NSEvent enterExitEventWithType:NSMouseExited
     56                                location:[theEvent locationInWindow]
     57                           modifierFlags:[theEvent modifierFlags]
     58                               timestamp:[theEvent timestamp]
     59                            windowNumber:[theEvent windowNumber]
     60                                 context:[theEvent context]
     61                             eventNumber:[pendingExitEvent_.get() eventNumber]
     62                          trackingNumber:[pendingExitEvent_.get() trackingNumber]
     63                                userData:[pendingExitEvent_.get() userData]];
     64     [self mouseEvent:exitEvent];
     65     pendingExitEvent_.reset();
     66   }
     67 }
     68 
     69 - (void)rightMouseUp:(NSEvent*)theEvent {
     70   [self mouseEvent:theEvent];
     71 }
     72 
     73 - (void)otherMouseUp:(NSEvent*)theEvent {
     74   [self mouseEvent:theEvent];
     75 }
     76 
     77 - (void)mouseMoved:(NSEvent*)theEvent {
     78   [self mouseEvent:theEvent];
     79 }
     80 
     81 - (void)mouseDragged:(NSEvent*)theEvent {
     82   [self mouseEvent:theEvent];
     83 }
     84 
     85 - (void)rightMouseDragged:(NSEvent*)theEvent {
     86   [self mouseEvent:theEvent];
     87 }
     88 
     89 - (void)otherMouseDragged:(NSEvent*)theEvent {
     90   [self mouseEvent:theEvent];
     91 }
     92 
     93 - (void)mouseEntered:(NSEvent*)theEvent {
     94   if (pendingExitEvent_.get()) {
     95     pendingExitEvent_.reset();
     96     return;
     97   }
     98 
     99   [self mouseEvent:theEvent];
    100 }
    101 
    102 - (void)mouseExited:(NSEvent*)theEvent {
    103   // The tracking area will send an exit event even during a drag, which isn't
    104   // how the event flow for drags should work. This stores the exit event, and
    105   // sends it when the drag completes instead.
    106   if (dragging_) {
    107     pendingExitEvent_.reset([theEvent retain]);
    108     return;
    109   }
    110 
    111   [self mouseEvent:theEvent];
    112 }
    113 
    114 - (void)keyDown:(NSEvent*)theEvent {
    115   if ([self keyEvent:theEvent] != kEventHandled)
    116     [super keyDown:theEvent];
    117 }
    118 
    119 - (void)keyUp:(NSEvent*)theEvent {
    120   if ([self keyEvent:theEvent] != kEventHandled)
    121     [super keyUp:theEvent];
    122 }
    123 
    124 - (void)flagsChanged:(NSEvent*)theEvent {
    125   if ([self keyEvent:theEvent] != kEventHandled)
    126     [super flagsChanged:theEvent];
    127 }
    128 
    129 - (gfx::Rect)flipNSRectToRect:(NSRect)rect {
    130   gfx::Rect new_rect(NSRectToCGRect(rect));
    131   new_rect.set_y(NSHeight([self bounds]) - new_rect.bottom());
    132   return new_rect;
    133 }
    134 
    135 - (NSRect)flipRectToNSRect:(gfx::Rect)rect {
    136   NSRect new_rect(NSRectFromCGRect(rect.ToCGRect()));
    137   new_rect.origin.y = NSHeight([self bounds]) - NSMaxY(new_rect);
    138   return new_rect;
    139 }
    140 
    141 - (void)updateTrackingAreas {
    142   [super updateTrackingAreas];
    143 
    144   // NSTrackingInVisibleRect doesn't work correctly with Lion's window resizing,
    145   // http://crbug.com/176725 / http://openradar.appspot.com/radar?id=2773401 .
    146   // Tear down old tracking area and create a new one as workaround.
    147   if (trackingArea_.get())
    148     [self removeTrackingArea:trackingArea_.get()];
    149   trackingArea_.reset([[CrTrackingArea alloc] initWithRect:[self bounds]
    150                                                    options:kTrackingOptions
    151                                                      owner:self
    152                                                   userInfo:nil]);
    153   [self addTrackingArea:trackingArea_.get()];
    154 }
    155 
    156 @end
    157