scroll_view_with_no_scrollbars.mm revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright 2013 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/app_list/cocoa/scroll_view_with_no_scrollbars.h"
6
7#include "base/mac/mac_util.h"
8#include "base/mac/scoped_cftyperef.h"
9#include "base/mac/scoped_nsobject.h"
10
11#if !defined(MAC_OS_X_VERSION_10_7) || \
12    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
13
14enum {
15   NSEventPhaseNone       = 0,
16   NSEventPhaseBegan      = 0x1 << 0,
17   NSEventPhaseStationary = 0x1 << 1,
18   NSEventPhaseChanged    = 0x1 << 2,
19   NSEventPhaseEnded      = 0x1 << 3,
20   NSEventPhaseCancelled  = 0x1 << 4,
21};
22typedef NSUInteger NSEventPhase;
23
24@interface NSEvent (LionAPI)
25
26- (NSEventPhase)momentumPhase;
27- (NSEventPhase)phase;
28
29@end
30
31#endif  // 10.7
32
33@interface InvisibleScroller : NSScroller;
34@end
35
36@implementation InvisibleScroller
37
38// Makes it non-interactive (and invisible) on Lion with both 10.6 and 10.7
39// SDKs. TODO(tapted): Find a way to make it non-interactive on Snow Leopard.
40// TODO(tapted): Find a way to make it take up no space on Lion with a 10.6 SDK.
41- (NSRect)rectForPart:(NSScrollerPart)aPart {
42  return NSZeroRect;
43}
44
45@end
46
47@implementation ScrollViewWithNoScrollbars
48
49@synthesize delegate = delegate_;
50
51- (id)initWithFrame:(NSRect)frame {
52  if ((self = [super initWithFrame:frame])) {
53    [self setHasHorizontalScroller:base::mac::IsOSLionOrLater()];
54    NSRect horizontalScrollerRect = [self bounds];
55    horizontalScrollerRect.size.height = 0;
56    base::scoped_nsobject<InvisibleScroller> horizontalScroller(
57        [[InvisibleScroller alloc] initWithFrame:horizontalScrollerRect]);
58    [self setHorizontalScroller:horizontalScroller];
59  }
60  return self;
61}
62
63- (void)endGestureWithEvent:(NSEvent*)event {
64  [super endGestureWithEvent:event];
65  if (!base::mac::IsOSLionOrLater())
66    [delegate_ userScrolling:NO];
67}
68
69- (void)scrollWheel:(NSEvent*)event {
70  if ([event subtype] == NSMouseEventSubtype) {
71    // Since the scroll view has no vertical scroller, regular up and down mouse
72    // wheel events would be ignored. This maps mouse wheel events to a
73    // horizontal scroll event of one line, to turn pages.
74    BOOL downOrRight;
75    if ([event deltaX] != 0)
76      downOrRight = [event deltaX] > 0;
77    else if ([event deltaY] != 0)
78      downOrRight = [event deltaY] > 0;
79    else
80      return;
81
82    base::ScopedCFTypeRef<CGEventRef> cgEvent(CGEventCreateScrollWheelEvent(
83        NULL, kCGScrollEventUnitLine, 2, 0, downOrRight ? 1 : -1));
84    [super scrollWheel:[NSEvent eventWithCGEvent:cgEvent]];
85    return;
86  }
87
88  [super scrollWheel:event];
89  if (![event respondsToSelector:@selector(momentumPhase)])
90    return;
91
92  BOOL scrollComplete = [event momentumPhase] == NSEventPhaseEnded ||
93      ([event momentumPhase] == NSEventPhaseNone &&
94          [event phase] == NSEventPhaseEnded);
95
96  [delegate_ userScrolling:!scrollComplete];
97}
98
99@end
100