Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ui/message_center/cocoa/popup_controller.h" | 5 #import "ui/message_center/cocoa/popup_controller.h" |
| 6 | 6 |
| 7 #include <cmath> | |
| 8 | |
| 9 #import "base/mac/foundation_util.h" | |
| 7 #import "ui/base/cocoa/window_size_constants.h" | 10 #import "ui/base/cocoa/window_size_constants.h" |
| 8 #import "ui/message_center/cocoa/notification_controller.h" | 11 #import "ui/message_center/cocoa/notification_controller.h" |
| 9 #include "ui/message_center/message_center.h" | 12 #include "ui/message_center/message_center.h" |
| 10 | 13 |
| 11 #if !defined(MAC_OS_X_VERSION_10_7) || \ | 14 #if !defined(MAC_OS_X_VERSION_10_7) || \ |
| 12 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | 15 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
| 13 enum { | 16 enum { |
| 14 NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 | 17 NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 |
| 15 }; | 18 }; |
| 19 | |
| 20 enum { | |
|
Robert Sesek
2013/05/22 23:54:29
This is copied verbatim from RenderWidgetHostViewD
Nico
2013/05/23 01:02:56
Probably a good idea. Can be in a follow-up if you
| |
| 21 NSEventPhaseNone = 0, // event not associated with a phase. | |
| 22 NSEventPhaseBegan = 0x1 << 0, | |
| 23 NSEventPhaseStationary = 0x1 << 1, | |
| 24 NSEventPhaseChanged = 0x1 << 2, | |
| 25 NSEventPhaseEnded = 0x1 << 3, | |
| 26 NSEventPhaseCancelled = 0x1 << 4, | |
| 27 }; | |
| 28 typedef NSUInteger NSEventPhase; | |
| 29 | |
| 30 enum { | |
| 31 NSEventSwipeTrackingLockDirection = 0x1 << 0, | |
| 32 NSEventSwipeTrackingClampGestureAmount = 0x1 << 1 | |
| 33 }; | |
| 34 typedef NSUInteger NSEventSwipeTrackingOptions; | |
| 35 | |
| 36 @interface NSEvent (LionAPI) | |
| 37 - (NSEventPhase)phase; | |
| 38 - (CGFloat)scrollingDeltaX; | |
| 39 - (CGFloat)scrollingDeltaY; | |
| 40 - (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options | |
| 41 dampenAmountThresholdMin:(CGFloat)minDampenThreshold | |
| 42 max:(CGFloat)maxDampenThreshold | |
| 43 usingHandler:(void (^)(CGFloat gestureAmount, | |
| 44 NSEventPhase phase, | |
| 45 BOOL isComplete, | |
| 46 BOOL* stop))trackingHandler; | |
| 47 @end | |
| 16 #endif // MAC_OS_X_VERSION_10_7 | 48 #endif // MAC_OS_X_VERSION_10_7 |
| 17 | 49 |
| 50 //////////////////////////////////////////////////////////////////////////////// | |
| 51 | |
| 52 @interface MCPopupController (Private) | |
| 53 - (void)notificationSwipeStarted; | |
| 54 - (void)notificationSwipeMoved:(CGFloat)amount; | |
| 55 - (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete; | |
| 56 @end | |
| 57 | |
| 58 // Window Subclass ///////////////////////////////////////////////////////////// | |
| 59 | |
| 60 @interface MCPopupWindow : NSWindow { | |
| 61 // The cumulative X and Y scrollingDeltas since the -scrollWheel: event began. | |
| 62 NSPoint totalScrollDelta_; | |
| 63 } | |
| 64 @end | |
| 65 | |
| 66 @implementation MCPopupWindow | |
| 67 | |
| 68 - (void)scrollWheel:(NSEvent*)event { | |
| 69 // Gesture swiping only exists on 10.7+. | |
| 70 if (![event respondsToSelector:@selector(phase)]) | |
| 71 return; | |
| 72 | |
| 73 NSEventPhase phase = [event phase]; | |
| 74 BOOL shouldTrackSwipe = NO; | |
| 75 | |
| 76 if (phase == NSEventPhaseBegan) { | |
| 77 totalScrollDelta_ = NSZeroPoint; | |
| 78 } else if (phase == NSEventPhaseChanged) { | |
| 79 shouldTrackSwipe = YES; | |
| 80 totalScrollDelta_.x += [event scrollingDeltaX]; | |
| 81 totalScrollDelta_.y += [event scrollingDeltaY]; | |
| 82 } | |
| 83 | |
| 84 // Only allow horizontal scrolling. | |
| 85 if (std::abs(totalScrollDelta_.x) < std::abs(totalScrollDelta_.y)) | |
| 86 return; | |
| 87 | |
| 88 if (shouldTrackSwipe) { | |
| 89 MCPopupController* controller = | |
| 90 base::mac::ObjCCastStrict<MCPopupController>([self windowController]); | |
| 91 | |
| 92 auto handler = ^(CGFloat gestureAmount, NSEventPhase phase, | |
| 93 BOOL isComplete, BOOL* stop) { | |
| 94 if (phase == NSEventPhaseBegan) { | |
| 95 [controller notificationSwipeStarted]; | |
| 96 return; | |
| 97 } | |
| 98 | |
| 99 [controller notificationSwipeMoved:gestureAmount]; | |
| 100 | |
| 101 BOOL ended = phase == NSEventPhaseEnded; | |
| 102 if (ended || isComplete) | |
| 103 [controller notificationSwipeEnded:ended complete:isComplete]; | |
| 104 }; | |
| 105 [event trackSwipeEventWithOptions:0 | |
| 106 dampenAmountThresholdMin:-1 | |
| 107 max:1 | |
| 108 usingHandler:handler]; | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 @end | |
| 113 | |
| 114 //////////////////////////////////////////////////////////////////////////////// | |
| 115 | |
| 18 @implementation MCPopupController | 116 @implementation MCPopupController |
| 19 | 117 |
| 20 - (id)initWithNotification:(const message_center::Notification*)notification | 118 - (id)initWithNotification:(const message_center::Notification*)notification |
| 21 messageCenter:(message_center::MessageCenter*)messageCenter { | 119 messageCenter:(message_center::MessageCenter*)messageCenter { |
| 22 scoped_nsobject<NSWindow> window( | 120 scoped_nsobject<MCPopupWindow> window( |
| 23 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater | 121 [[MCPopupWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater |
| 24 styleMask:NSBorderlessWindowMask | 122 styleMask:NSBorderlessWindowMask |
| 25 backing:NSBackingStoreBuffered | 123 backing:NSBackingStoreBuffered |
| 26 defer:YES]); | 124 defer:YES]); |
| 27 if ((self = [super initWithWindow:window])) { | 125 if ((self = [super initWithWindow:window])) { |
| 126 messageCenter_ = messageCenter; | |
| 28 notificationController_.reset( | 127 notificationController_.reset( |
| 29 [[MCNotificationController alloc] initWithNotification:notification | 128 [[MCNotificationController alloc] initWithNotification:notification |
| 30 messageCenter:messageCenter]); | 129 messageCenter:messageCenter_]); |
| 31 [window setReleasedWhenClosed:NO]; | 130 [window setReleasedWhenClosed:NO]; |
| 32 | 131 |
| 33 [window setLevel:NSFloatingWindowLevel]; | 132 [window setLevel:NSFloatingWindowLevel]; |
| 34 [window setExcludedFromWindowsMenu:YES]; | 133 [window setExcludedFromWindowsMenu:YES]; |
| 35 [window setCollectionBehavior: | 134 [window setCollectionBehavior: |
| 36 NSWindowCollectionBehaviorIgnoresCycle | | 135 NSWindowCollectionBehaviorIgnoresCycle | |
| 37 NSWindowCollectionBehaviorFullScreenAuxiliary]; | 136 NSWindowCollectionBehaviorFullScreenAuxiliary]; |
| 38 | 137 |
| 39 [window setHasShadow:YES]; | 138 [window setHasShadow:YES]; |
| 40 [window setFrame:[[notificationController_ view] frame] display:NO]; | 139 [window setFrame:[[notificationController_ view] frame] display:NO]; |
| 41 [window setContentView:[notificationController_ view]]; | 140 [window setContentView:[notificationController_ view]]; |
| 42 } | 141 } |
| 43 return self; | 142 return self; |
| 44 } | 143 } |
| 45 | 144 |
| 46 - (MCNotificationController*)notificationController { | 145 - (MCNotificationController*)notificationController { |
| 47 return notificationController_.get(); | 146 return notificationController_.get(); |
| 48 } | 147 } |
| 49 | 148 |
| 50 - (const message_center::Notification*)notification { | 149 - (const message_center::Notification*)notification { |
| 51 return [notificationController_ notification]; | 150 return [notificationController_ notification]; |
| 52 } | 151 } |
| 53 | 152 |
| 54 - (const std::string&)notificationID { | 153 - (const std::string&)notificationID { |
| 55 return [notificationController_ notificationID]; | 154 return [notificationController_ notificationID]; |
| 56 } | 155 } |
| 57 | 156 |
| 157 // Private ///////////////////////////////////////////////////////////////////// | |
| 158 | |
| 159 - (void)notificationSwipeStarted { | |
| 160 originalFrame_ = [[self window] frame]; | |
| 161 swipeGestureEnded_ = NO; | |
| 162 } | |
| 163 | |
| 164 - (void)notificationSwipeMoved:(CGFloat)amount { | |
| 165 NSWindow* window = [self window]; | |
| 166 | |
| 167 [window setAlphaValue:1.0 - std::abs(amount)]; | |
|
dewittj
2013/05/23 16:28:37
Is the linear reduction of alpha the most natural?
Robert Sesek
2013/05/23 16:31:13
This isn't actually linear. |amount| is done throu
| |
| 168 NSRect frame = [window frame]; | |
| 169 CGFloat originalMin = NSMinX(originalFrame_); | |
| 170 frame.origin.x = originalMin + (NSMidX(originalFrame_) - originalMin) * | |
| 171 -amount; | |
| 172 [window setFrame:frame display:YES]; | |
| 173 } | |
| 174 | |
| 175 - (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete { | |
| 176 swipeGestureEnded_ |= ended; | |
| 177 if (swipeGestureEnded_ && isComplete) | |
| 178 messageCenter_->RemoveNotification([self notificationID], /*by_user=*/true); | |
|
Nico
2013/05/23 01:02:56
If the user cancels a swipe, does appkit animate b
Robert Sesek
2013/05/23 13:00:58
Yup! AppKit will run the animation back for us.
dewittj
2013/05/23 16:28:37
nit: spaces between comment markers and other text
Robert Sesek
2013/05/23 16:31:13
When doing this to "name" parameters, I think this
| |
| 179 } | |
| 180 | |
| 58 @end | 181 @end |
| OLD | NEW |