OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "chrome/browser/ui/cocoa/status_bubble_mac.h" | 5 #include "chrome/browser/ui/cocoa/status_bubble_mac.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/mac/mac_util.h" | 11 #include "base/mac/mac_util.h" |
| 12 #include "base/mac/scoped_block.h" |
| 13 #include "base/mac/sdk_forward_declarations.h" |
12 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
13 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
14 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
15 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
16 #import "chrome/browser/ui/cocoa/bubble_view.h" | 18 #import "chrome/browser/ui/cocoa/bubble_view.h" |
17 #include "chrome/browser/ui/elide_url.h" | 19 #include "chrome/browser/ui/elide_url.h" |
18 #include "net/base/net_util.h" | 20 #include "net/base/net_util.h" |
19 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" | 21 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" |
20 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSBezierPath+RoundRect
.h" | 22 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSBezierPath+RoundRect
.h" |
21 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSColor+Luminance.h" | 23 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSColor+Luminance.h" |
22 #include "ui/base/cocoa/window_size_constants.h" | 24 #include "ui/base/cocoa/window_size_constants.h" |
23 #include "ui/gfx/font_list.h" | 25 #include "ui/gfx/font_list.h" |
24 #include "ui/gfx/point.h" | 26 #include "ui/gfx/point.h" |
25 #include "ui/gfx/text_elider.h" | 27 #include "ui/gfx/text_elider.h" |
26 #include "ui/gfx/text_utils.h" | 28 #include "ui/gfx/text_utils.h" |
27 | 29 |
28 namespace { | 30 namespace { |
29 | 31 |
30 const int kWindowHeight = 18; | 32 const int kWindowHeight = 18; |
31 | 33 |
32 // The width of the bubble in relation to the width of the parent window. | 34 // The width of the bubble in relation to the width of the parent window. |
33 const CGFloat kWindowWidthPercent = 1.0 / 3.0; | 35 const CGFloat kWindowWidthPercent = 1.0 / 3.0; |
34 | 36 |
35 // How close the mouse can get to the infobubble before it starts sliding | 37 // How close the mouse can get to the infobubble before it starts sliding |
36 // off-screen. | 38 // off-screen. |
37 const int kMousePadding = 20; | 39 const int kMousePadding = 20; |
38 | 40 |
39 const int kTextPadding = 3; | 41 const int kTextPadding = 3; |
40 | 42 |
41 // The animation key used for fade-in and fade-out transitions. | |
42 NSString* const kFadeAnimationKey = @"alphaValue"; | |
43 | |
44 // The status bubble's maximum opacity, when fully faded in. | 43 // The status bubble's maximum opacity, when fully faded in. |
45 const CGFloat kBubbleOpacity = 1.0; | 44 const CGFloat kBubbleOpacity = 1.0; |
46 | 45 |
47 // Delay before showing or hiding the bubble after a SetStatus or SetURL call. | 46 // Delay before showing or hiding the bubble after a SetStatus or SetURL call. |
48 const int64 kShowDelayMS = 80; | 47 const int64 kShowDelayMS = 80; |
49 const int64 kHideDelayMS = 250; | 48 const int64 kHideDelayMS = 250; |
50 | 49 |
51 // How long each fade should last. | 50 // How long each fade should last. |
52 const NSTimeInterval kShowFadeInDurationSeconds = 0.120; | 51 const NSTimeInterval kShowFadeInDurationSeconds = 0.120; |
53 const NSTimeInterval kHideFadeOutDurationSeconds = 0.200; | 52 const NSTimeInterval kHideFadeOutDurationSeconds = 0.200; |
54 | 53 |
55 // The minimum representable time interval. This can be used as the value | 54 // The minimum representable time interval. This can be used as the value |
56 // passed to +[NSAnimationContext setDuration:] to stop an in-progress | 55 // passed to +[NSAnimationContext setDuration:] to stop an in-progress |
57 // animation as quickly as possible. | 56 // animation as quickly as possible. |
58 const NSTimeInterval kMinimumTimeInterval = | 57 const NSTimeInterval kMinimumTimeInterval = |
59 std::numeric_limits<NSTimeInterval>::min(); | 58 std::numeric_limits<NSTimeInterval>::min(); |
60 | 59 |
61 // How quickly the status bubble should expand. | 60 // How quickly the status bubble should expand. |
62 const CGFloat kExpansionDurationSeconds = 0.125; | 61 const CGFloat kExpansionDurationSeconds = 0.125; |
63 | 62 |
64 } // namespace | 63 } // namespace |
65 | 64 |
66 @interface StatusBubbleAnimationDelegate : NSObject { | 65 @interface StatusBubbleAnimationDelegate : NSObject { |
67 @private | 66 @private |
68 StatusBubbleMac* statusBubble_; // weak; owns us indirectly | 67 base::mac::ScopedBlock<void (^)(void)> completionHandler_; |
69 } | 68 } |
70 | 69 |
71 - (id)initWithStatusBubble:(StatusBubbleMac*)statusBubble; | 70 - (id)initWithCompletionHandler:(void (^)(void))completionHandler; |
72 | |
73 // Invalidates this object so that no further calls will be made to | |
74 // statusBubble_. This should be called when statusBubble_ is released, to | |
75 // prevent attempts to call into the released object. | |
76 - (void)invalidate; | |
77 | 71 |
78 // CAAnimation delegate method | 72 // CAAnimation delegate method |
79 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished; | 73 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished; |
80 @end | 74 @end |
81 | 75 |
82 @implementation StatusBubbleAnimationDelegate | 76 @implementation StatusBubbleAnimationDelegate |
83 | 77 |
84 - (id)initWithStatusBubble:(StatusBubbleMac*)statusBubble { | 78 - (id)initWithCompletionHandler:(void (^)(void))completionHandler { |
85 if ((self = [super init])) { | 79 if ((self = [super init])) { |
86 statusBubble_ = statusBubble; | 80 completionHandler_.reset(completionHandler, base::scoped_policy::RETAIN); |
87 } | 81 } |
88 | 82 |
89 return self; | 83 return self; |
90 } | 84 } |
91 | 85 |
92 - (void)invalidate { | |
93 statusBubble_ = NULL; | |
94 } | |
95 | |
96 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { | 86 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { |
97 if (statusBubble_) | 87 completionHandler_.get()(); |
98 statusBubble_->AnimationDidStop(animation, finished); | |
99 } | 88 } |
100 | 89 |
101 @end | 90 @end |
| 91 |
| 92 @interface StatusBubbleWindow : NSWindow { |
| 93 @private |
| 94 void (^completionHandler_)(void); |
| 95 } |
| 96 |
| 97 - (id)animationForKey:(NSString *)key; |
| 98 - (void)runAnimationGroup:(void (^)(NSAnimationContext *context))changes |
| 99 completionHandler:(void (^)(void))completionHandler; |
| 100 @end |
| 101 |
| 102 @implementation StatusBubbleWindow |
| 103 |
| 104 - (id)animationForKey:(NSString *)key { |
| 105 CAAnimation* animation = [super animationForKey:key]; |
| 106 // If completionHandler_ isn't nil, then this is the first of (potentially) |
| 107 // multiple animations in a grouping; give it the completion handler. If |
| 108 // completionHandler_ is nil, then some other animation was tagged with the |
| 109 // completion handler. |
| 110 if (completionHandler_) { |
| 111 DCHECK(![NSAnimationContext respondsToSelector: |
| 112 @selector(runAnimationGroup:completionHandler:)]); |
| 113 StatusBubbleAnimationDelegate* animation_delegate = |
| 114 [[StatusBubbleAnimationDelegate alloc] |
| 115 initWithCompletionHandler:completionHandler_]; |
| 116 [animation setDelegate:animation_delegate]; |
| 117 completionHandler_ = nil; |
| 118 } |
| 119 return animation; |
| 120 } |
| 121 |
| 122 - (void)runAnimationGroup:(void (^)(NSAnimationContext *context))changes |
| 123 completionHandler:(void (^)(void))completionHandler { |
| 124 if ([NSAnimationContext respondsToSelector: |
| 125 @selector(runAnimationGroup:completionHandler:)]) { |
| 126 [NSAnimationContext runAnimationGroup:changes |
| 127 completionHandler:completionHandler]; |
| 128 } else { |
| 129 // Mac OS 10.6 does not have completion handler callbacks at the Cocoa |
| 130 // level, only at the CoreAnimation level. So intercept calls made to |
| 131 // -animationForKey: and tag one of the animations with a delegate that will |
| 132 // execute the completion handler. |
| 133 completionHandler_ = completionHandler; |
| 134 [NSAnimationContext beginGrouping]; |
| 135 changes([NSAnimationContext currentContext]); |
| 136 // At this point, -animationForKey should have been called by CoreAnimation |
| 137 // to set up the animation to run. Verify this. |
| 138 DCHECK(completionHandler_ == nil); |
| 139 [NSAnimationContext endGrouping]; |
| 140 } |
| 141 } |
| 142 |
| 143 @end |
102 | 144 |
103 StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate) | 145 StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate) |
104 : timer_factory_(this), | 146 : timer_factory_(this), |
105 expand_timer_factory_(this), | 147 expand_timer_factory_(this), |
| 148 completion_handler_factory_(this), |
106 parent_(parent), | 149 parent_(parent), |
107 delegate_(delegate), | 150 delegate_(delegate), |
108 window_(nil), | 151 window_(nil), |
109 status_text_(nil), | 152 status_text_(nil), |
110 url_text_(nil), | 153 url_text_(nil), |
111 state_(kBubbleHidden), | 154 state_(kBubbleHidden), |
112 immediate_(false), | 155 immediate_(false), |
113 is_expanded_(false) { | 156 is_expanded_(false) { |
114 Create(); | 157 Create(); |
115 Attach(); | 158 Attach(); |
116 } | 159 } |
117 | 160 |
118 StatusBubbleMac::~StatusBubbleMac() { | 161 StatusBubbleMac::~StatusBubbleMac() { |
119 DCHECK(window_); | 162 DCHECK(window_); |
120 | 163 |
121 Hide(); | 164 Hide(); |
122 | 165 |
123 [[[window_ animationForKey:kFadeAnimationKey] delegate] invalidate]; | 166 completion_handler_factory_.InvalidateWeakPtrs(); |
124 Detach(); | 167 Detach(); |
125 [window_ release]; | 168 [window_ release]; |
126 window_ = nil; | 169 window_ = nil; |
127 } | 170 } |
128 | 171 |
129 void StatusBubbleMac::SetStatus(const base::string16& status) { | 172 void StatusBubbleMac::SetStatus(const base::string16& status) { |
130 SetText(status, false); | 173 SetText(status, false); |
131 } | 174 } |
132 | 175 |
133 void StatusBubbleMac::SetURL(const GURL& url, const std::string& languages) { | 176 void StatusBubbleMac::SetURL(const GURL& url, const std::string& languages) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 is_expanded_ = false; | 273 is_expanded_ = false; |
231 | 274 |
232 bool fade_out = false; | 275 bool fade_out = false; |
233 if (state_ == kBubbleHidingFadeOut || state_ == kBubbleShowingFadeIn) { | 276 if (state_ == kBubbleHidingFadeOut || state_ == kBubbleShowingFadeIn) { |
234 SetState(kBubbleHidingFadeOut); | 277 SetState(kBubbleHidingFadeOut); |
235 | 278 |
236 if (!immediate_) { | 279 if (!immediate_) { |
237 // An animation is in progress. Cancel it by starting a new animation. | 280 // An animation is in progress. Cancel it by starting a new animation. |
238 // Use kMinimumTimeInterval to set the opacity as rapidly as possible. | 281 // Use kMinimumTimeInterval to set the opacity as rapidly as possible. |
239 fade_out = true; | 282 fade_out = true; |
240 [NSAnimationContext beginGrouping]; | 283 AnimateWindowAlpha(0.0, kMinimumTimeInterval); |
241 [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval]; | |
242 [[window_ animator] setAlphaValue:0.0]; | |
243 [NSAnimationContext endGrouping]; | |
244 } | 284 } |
245 } | 285 } |
246 | 286 |
247 if (!fade_out) { | 287 if (!fade_out) { |
248 // No animation is in progress, so the opacity can be set directly. | 288 // No animation is in progress, so the opacity can be set directly. |
249 [window_ setAlphaValue:0.0]; | 289 [window_ setAlphaValue:0.0]; |
250 SetState(kBubbleHidden); | 290 SetState(kBubbleHidden); |
251 } | 291 } |
252 | 292 |
253 // Stop any width animation and reset the bubble size. | 293 // Stop any width animation and reset the bubble size. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 SetFrameAvoidingMouse([window_ frame], location); | 397 SetFrameAvoidingMouse([window_ frame], location); |
358 } | 398 } |
359 | 399 |
360 void StatusBubbleMac::UpdateDownloadShelfVisibility(bool visible) { | 400 void StatusBubbleMac::UpdateDownloadShelfVisibility(bool visible) { |
361 UpdateSizeAndPosition(); | 401 UpdateSizeAndPosition(); |
362 } | 402 } |
363 | 403 |
364 void StatusBubbleMac::Create() { | 404 void StatusBubbleMac::Create() { |
365 DCHECK(!window_); | 405 DCHECK(!window_); |
366 | 406 |
367 window_ = [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater | 407 window_ = [[StatusBubbleWindow alloc] |
368 styleMask:NSBorderlessWindowMask | 408 initWithContentRect:ui::kWindowSizeDeterminedLater |
369 backing:NSBackingStoreBuffered | 409 styleMask:NSBorderlessWindowMask |
370 defer:YES]; | 410 backing:NSBackingStoreBuffered |
| 411 defer:YES]; |
371 [window_ setMovableByWindowBackground:NO]; | 412 [window_ setMovableByWindowBackground:NO]; |
372 [window_ setBackgroundColor:[NSColor clearColor]]; | 413 [window_ setBackgroundColor:[NSColor clearColor]]; |
373 [window_ setLevel:NSNormalWindowLevel]; | 414 [window_ setLevel:NSNormalWindowLevel]; |
374 [window_ setOpaque:NO]; | 415 [window_ setOpaque:NO]; |
375 [window_ setHasShadow:NO]; | 416 [window_ setHasShadow:NO]; |
376 | 417 |
377 // We do not need to worry about the bubble outliving |parent_| because our | 418 // We do not need to worry about the bubble outliving |parent_| because our |
378 // teardown sequence in BWC guarantees that |parent_| outlives the status | 419 // teardown sequence in BWC guarantees that |parent_| outlives the status |
379 // bubble and that the StatusBubble is torn down completely prior to the | 420 // bubble and that the StatusBubble is torn down completely prior to the |
380 // window going away. | 421 // window going away. |
381 base::scoped_nsobject<BubbleView> view( | 422 base::scoped_nsobject<BubbleView> view( |
382 [[BubbleView alloc] initWithFrame:NSZeroRect themeProvider:parent_]); | 423 [[BubbleView alloc] initWithFrame:NSZeroRect themeProvider:parent_]); |
383 [window_ setContentView:view]; | 424 [window_ setContentView:view]; |
384 | 425 |
385 [window_ setAlphaValue:0.0]; | 426 [window_ setAlphaValue:0.0]; |
386 | 427 |
387 // TODO(dtseng): Ignore until we provide NSAccessibility support. | 428 // TODO(dtseng): Ignore until we provide NSAccessibility support. |
388 [window_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole | 429 [window_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole |
389 forAttribute:NSAccessibilityRoleAttribute]; | 430 forAttribute:NSAccessibilityRoleAttribute]; |
390 | 431 |
391 // Set a delegate for the fade-in and fade-out transitions to be notified | |
392 // when fades are complete. The ownership model is for window_ to own | |
393 // animation_dictionary, which owns animation, which owns | |
394 // animation_delegate. | |
395 CAAnimation* animation = [[window_ animationForKey:kFadeAnimationKey] copy]; | |
396 [animation autorelease]; | |
397 StatusBubbleAnimationDelegate* animation_delegate = | |
398 [[StatusBubbleAnimationDelegate alloc] initWithStatusBubble:this]; | |
399 [animation_delegate autorelease]; | |
400 [animation setDelegate:animation_delegate]; | |
401 NSMutableDictionary* animation_dictionary = | |
402 [NSMutableDictionary dictionaryWithDictionary:[window_ animations]]; | |
403 [animation_dictionary setObject:animation forKey:kFadeAnimationKey]; | |
404 [window_ setAnimations:animation_dictionary]; | |
405 | |
406 [view setCornerFlags:kRoundedTopRightCorner]; | 432 [view setCornerFlags:kRoundedTopRightCorner]; |
407 MouseMoved(gfx::Point(), false); | 433 MouseMoved(gfx::Point(), false); |
408 } | 434 } |
409 | 435 |
410 void StatusBubbleMac::Attach() { | 436 void StatusBubbleMac::Attach() { |
411 DCHECK(!is_attached()); | 437 DCHECK(!is_attached()); |
412 | 438 |
413 [window_ orderFront:nil]; | 439 [window_ orderFront:nil]; |
414 [parent_ addChildWindow:window_ ordered:NSWindowAbove]; | 440 [parent_ addChildWindow:window_ ordered:NSWindowAbove]; |
415 | 441 |
416 [[window_ contentView] setThemeProvider:parent_]; | 442 [[window_ contentView] setThemeProvider:parent_]; |
417 } | 443 } |
418 | 444 |
419 void StatusBubbleMac::Detach() { | 445 void StatusBubbleMac::Detach() { |
420 DCHECK(is_attached()); | 446 DCHECK(is_attached()); |
421 | 447 |
422 // Magic setFrame: See http://crbug.com/58506 and http://crrev.com/3564021 . | 448 // Magic setFrame: See http://crbug.com/58506 and http://crrev.com/3564021 . |
423 [window_ setFrame:CalculateWindowFrame(/*expand=*/false) display:NO]; | 449 [window_ setFrame:CalculateWindowFrame(/*expand=*/false) display:NO]; |
424 [parent_ removeChildWindow:window_]; // See crbug.com/28107 ... | 450 [parent_ removeChildWindow:window_]; // See crbug.com/28107 ... |
425 [window_ orderOut:nil]; // ... and crbug.com/29054. | 451 [window_ orderOut:nil]; // ... and crbug.com/29054. |
426 | 452 |
427 [[window_ contentView] setThemeProvider:nil]; | 453 [[window_ contentView] setThemeProvider:nil]; |
428 } | 454 } |
429 | 455 |
430 void StatusBubbleMac::AnimationDidStop(CAAnimation* animation, bool finished) { | 456 void StatusBubbleMac::AnimationDidStop() { |
431 DCHECK([NSThread isMainThread]); | 457 DCHECK([NSThread isMainThread]); |
432 DCHECK(state_ == kBubbleShowingFadeIn || state_ == kBubbleHidingFadeOut); | 458 DCHECK(state_ == kBubbleShowingFadeIn || state_ == kBubbleHidingFadeOut); |
433 DCHECK(is_attached()); | 459 DCHECK(is_attached()); |
434 | 460 |
435 if (finished) { | 461 if (state_ == kBubbleShowingFadeIn) { |
436 // Because of the mechanism used to interrupt animations, this is never | 462 DCHECK_EQ([[window_ animator] alphaValue], kBubbleOpacity); |
437 // actually called with finished set to false. If animations ever become | 463 SetState(kBubbleShown); |
438 // directly interruptible, the check will ensure that state_ remains | 464 } else { |
439 // properly synchronized. | 465 DCHECK_EQ([[window_ animator] alphaValue], 0.0); |
440 if (state_ == kBubbleShowingFadeIn) { | 466 SetState(kBubbleHidden); |
441 DCHECK_EQ([[window_ animator] alphaValue], kBubbleOpacity); | |
442 SetState(kBubbleShown); | |
443 } else { | |
444 DCHECK_EQ([[window_ animator] alphaValue], 0.0); | |
445 SetState(kBubbleHidden); | |
446 } | |
447 } | 467 } |
448 } | 468 } |
449 | 469 |
450 void StatusBubbleMac::SetState(StatusBubbleState state) { | 470 void StatusBubbleMac::SetState(StatusBubbleState state) { |
451 if (state == state_) | 471 if (state == state_) |
452 return; | 472 return; |
453 | 473 |
454 if (state == kBubbleHidden) { | 474 if (state == kBubbleHidden) { |
455 // When hidden (with alpha of 0), make the window have the minimum size, | 475 // When hidden (with alpha of 0), make the window have the minimum size, |
456 // while still keeping the same origin. It's important to not set the | 476 // while still keeping the same origin. It's important to not set the |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 // If an incomplete transition has left the opacity somewhere between 0 and | 519 // If an incomplete transition has left the opacity somewhere between 0 and |
500 // kBubbleOpacity, the fade rate is kept constant by shortening the duration. | 520 // kBubbleOpacity, the fade rate is kept constant by shortening the duration. |
501 NSTimeInterval duration = | 521 NSTimeInterval duration = |
502 full_duration * | 522 full_duration * |
503 fabs(opacity - [[window_ animator] alphaValue]) / kBubbleOpacity; | 523 fabs(opacity - [[window_ animator] alphaValue]) / kBubbleOpacity; |
504 | 524 |
505 // 0.0 will not cancel an in-progress animation. | 525 // 0.0 will not cancel an in-progress animation. |
506 if (duration == 0.0) | 526 if (duration == 0.0) |
507 duration = kMinimumTimeInterval; | 527 duration = kMinimumTimeInterval; |
508 | 528 |
509 // This will cancel an in-progress transition and replace it with this fade. | 529 // Cancel an in-progress transition and replace it with this fade. |
510 [NSAnimationContext beginGrouping]; | 530 AnimateWindowAlpha(opacity, duration); |
511 // Don't use the GTM additon for the "Steve" slowdown because this can happen | 531 } |
512 // async from user actions and the effects could be a surprise. | 532 |
513 [[NSAnimationContext currentContext] setDuration:duration]; | 533 void StatusBubbleMac::AnimateWindowAlpha(CGFloat alpha, |
514 [[window_ animator] setAlphaValue:opacity]; | 534 NSTimeInterval duration) { |
515 [NSAnimationContext endGrouping]; | 535 completion_handler_factory_.InvalidateWeakPtrs(); |
| 536 base::WeakPtr<StatusBubbleMac> weak_ptr( |
| 537 completion_handler_factory_.GetWeakPtr()); |
| 538 [window_ |
| 539 runAnimationGroup:^(NSAnimationContext* context) { |
| 540 [context setDuration:duration]; |
| 541 [[window_ animator] setAlphaValue:alpha]; |
| 542 } |
| 543 completionHandler:^{ |
| 544 if (weak_ptr) |
| 545 weak_ptr->AnimationDidStop(); |
| 546 }]; |
516 } | 547 } |
517 | 548 |
518 void StatusBubbleMac::StartTimer(int64 delay_ms) { | 549 void StatusBubbleMac::StartTimer(int64 delay_ms) { |
519 DCHECK([NSThread isMainThread]); | 550 DCHECK([NSThread isMainThread]); |
520 DCHECK(state_ == kBubbleShowingTimer || state_ == kBubbleHidingTimer); | 551 DCHECK(state_ == kBubbleShowingTimer || state_ == kBubbleHidingTimer); |
521 | 552 |
522 if (immediate_) { | 553 if (immediate_) { |
523 TimerFired(); | 554 TimerFired(); |
524 return; | 555 return; |
525 } | 556 } |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 } | 775 } |
745 | 776 |
746 // Round the top corners when the bubble is below the parent window. | 777 // Round the top corners when the bubble is below the parent window. |
747 if (NSMinY(window_frame) < NSMinY(parent_frame)) { | 778 if (NSMinY(window_frame) < NSMinY(parent_frame)) { |
748 corner_flags |= kRoundedTopLeftCorner | kRoundedTopRightCorner; | 779 corner_flags |= kRoundedTopLeftCorner | kRoundedTopRightCorner; |
749 } | 780 } |
750 } | 781 } |
751 | 782 |
752 return corner_flags; | 783 return corner_flags; |
753 } | 784 } |
OLD | NEW |