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