diff options
Diffstat (limited to 'chrome/browser/cocoa/clickhold_button_cell.mm')
-rw-r--r-- | chrome/browser/cocoa/clickhold_button_cell.mm | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/clickhold_button_cell.mm b/chrome/browser/cocoa/clickhold_button_cell.mm new file mode 100644 index 0000000..c65971c --- /dev/null +++ b/chrome/browser/cocoa/clickhold_button_cell.mm @@ -0,0 +1,136 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/clickhold_button_cell.h" + +#include "base/logging.h" + +// Minimum and maximum click-hold timeout. +static const NSTimeInterval kMinTimeout = 0.01; +static const NSTimeInterval kMaxTimeout = 3600.0; + +@implementation ClickHoldButtonCell + +// Overrides: + ++ (BOOL)prefersTrackingUntilMouseUp { + return NO; +} + +- (BOOL)startTrackingAt:(NSPoint)startPoint + inView:(NSView*)controlView { + return enableClickHold_ ? + YES : + [super startTrackingAt:startPoint + inView:controlView]; +} + +- (BOOL)continueTracking:(NSPoint)lastPoint + at:(NSPoint)currentPoint + inView:(NSView*)controlView { + return enableClickHold_ ? + YES : + [super continueTracking:lastPoint + at:currentPoint + inView:controlView]; +} + +- (BOOL)trackMouse:(NSEvent*)originalEvent + inRect:(NSRect)cellFrame + ofView:(NSView*)controlView + untilMouseUp:(BOOL)untilMouseUp { + if (!enableClickHold_) { + return [super trackMouse:originalEvent + inRect:cellFrame + ofView:controlView + untilMouseUp:untilMouseUp]; + } + + // If doing click-hold, track the mouse ourselves. + NSPoint currPoint = [controlView convertPoint:[originalEvent locationInWindow] + fromView:nil]; + NSPoint lastPoint = currPoint; + NSTimeInterval timeout = + MAX(MIN(clickHoldTimeout_, kMaxTimeout), kMinTimeout); + NSDate* clickHoldBailTime = [NSDate dateWithTimeIntervalSinceNow:timeout]; + + if (![self startTrackingAt:currPoint inView:controlView]) + return NO; + + enum { + kContinueTrack, kStopClickHold, kStopMouseUp, kStopLeftRect, kStopNoContinue + } state = kContinueTrack; + do { + NSEvent* event = [NSApp nextEventMatchingMask:(NSLeftMouseDraggedMask | + NSLeftMouseUpMask) + untilDate:clickHoldBailTime + inMode:NSEventTrackingRunLoopMode + dequeue:YES]; + currPoint = [controlView convertPoint:[event locationInWindow] + fromView:nil]; + + // Time-out or drag. + if (!event || (activateOnDrag_ && ([event type] == NSLeftMouseDragged))) { + state = kStopClickHold; + + // Mouse up. + } else if ([event type] == NSLeftMouseUp) { + state = kStopMouseUp; + + // Stop tracking if mouse left frame rectangle (if requested to do so). + } else if (trackOnlyInRect_ && ![controlView mouse:currPoint + inRect:cellFrame]) { + state = kStopLeftRect; + + // Stop tracking if instructed to. + } else if (![self continueTracking:lastPoint + at:currPoint + inView:controlView]) { + state = kStopNoContinue; + } + + lastPoint = currPoint; + } while (state == kContinueTrack); + + [self stopTracking:lastPoint + at:lastPoint + inView:controlView + mouseIsUp:NO]; + + switch (state) { + case kStopClickHold: + if (clickHoldAction_) { + [static_cast<NSControl*>(controlView) sendAction:clickHoldAction_ + to:clickHoldTarget_]; + } + return YES; + + case kStopMouseUp: + if ([self action]) { + [static_cast<NSControl*>(controlView) sendAction:[self action] + to:[self target]]; + } + return YES; + + case kStopLeftRect: + case kStopNoContinue: + return NO; + + default: + NOTREACHED() << "Unknown terminating state!"; + } + + return NO; +} + +// Accessors and mutators: + +@synthesize enableClickHold = enableClickHold_; +@synthesize clickHoldTimeout = clickHoldTimeout_; +@synthesize trackOnlyInRect = trackOnlyInRect_; +@synthesize activateOnDrag = activateOnDrag_; +@synthesize clickHoldTarget = clickHoldTarget_; +@synthesize clickHoldAction = clickHoldAction_; + +@end // @implementation ClickHoldButtonCell |