Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Unified Diff: chrome/browser/ui/cocoa/download/download_shelf_controller.mm

Issue 13318002: [Mac] Fix handling of download shelf auto close. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use OCMock Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/download/download_shelf_controller.mm
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index 65c7409ffad8c9e68e444ba952e237477f5978bc..3e1a25649732c4c077d3635670891d411858d5d2 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -31,7 +31,7 @@ using content::DownloadItem;
// Download shelf autoclose behavior:
//
// The download shelf autocloses if all of this is true:
-// 1) An item on the shelf has just been opened.
+// 1) An item on the shelf has just been opened or removed.
// 2) All remaining items on the shelf have been opened in the past.
// 3) The mouse leaves the shelf and remains off the shelf for 5 seconds.
//
@@ -71,13 +71,17 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
} // namespace
@interface DownloadShelfController(Private)
+- (void)removeDownload:(DownloadItemController*)download
+ isShelfClosing:(BOOL)isShelfClosing;
- (void)layoutItems:(BOOL)skipFirst;
- (void)closed;
- (void)maybeAutoCloseAfterDelay;
+- (void)scheduleAutoClose;
+- (void)cancelAutoClose;
- (void)autoClose;
- (void)viewFrameDidChange:(NSNotification*)notification;
- (void)installTrackingArea;
-- (void)cancelAutoCloseAndRemoveTrackingArea;
+- (void)removeTrackingArea;
- (void)willEnterFullscreen;
- (void)willLeaveFullscreen;
- (void)updateCloseButton;
@@ -136,11 +140,12 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
selector:@selector(willLeaveFullscreen)
name:kWillLeaveFullscreenNotification
object:nil];
+ [self installTrackingArea];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [self cancelAutoCloseAndRemoveTrackingArea];
+ [self removeTrackingArea];
// The controllers will unregister themselves as observers when they are
// deallocated. No need to do that here.
@@ -177,6 +182,12 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
}
- (void)remove:(DownloadItemController*)download {
+ [self removeDownload:download
+ isShelfClosing:NO];
+}
+
+- (void)removeDownload:(DownloadItemController*)download
+ isShelfClosing:(BOOL)isShelfClosing {
// Look for the download in our controller array and remove it. This will
// explicity release it so that it removes itself as an Observer of the
// DownloadItem. We don't want to wait for autorelease since the DownloadItem
@@ -187,11 +198,14 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
[[download view] removeFromSuperview];
[downloadItemControllers_ removeObject:download];
- [self layoutItems];
- // If there are no more downloads or if all the remaining downloads have been
- // opened, we can close the shelf.
- [self maybeAutoCloseAfterDelay];
+ if (!isShelfClosing) {
+ [self layoutItems];
+
+ // If there are no more downloads or if all the remaining downloads have
+ // been opened, we can close the shelf.
+ [self maybeAutoCloseAfterDelay];
+ }
}
- (void)downloadWasOpened:(DownloadItemController*)item_controller {
@@ -204,17 +218,22 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
// to remove themselves as observers before the remaining shutdown happens.
- (void)exiting {
[[self animatableView] stopAnimation];
- [self cancelAutoCloseAndRemoveTrackingArea];
+ [self removeTrackingArea];
+ while ([downloadItemControllers_ count] > 0) {
+ [self removeDownload:[downloadItemControllers_ lastObject]
+ isShelfClosing:YES];
+ }
downloadItemControllers_.reset();
}
- (void)showDownloadShelf:(BOOL)show
isUserAction:(BOOL)isUserAction {
+ shouldCloseOnMouseExit_ = NO;
+
if ([self isVisible] == show)
return;
if (!show) {
- [self cancelAutoCloseAndRemoveTrackingArea];
int numInProgress = 0;
for (NSUInteger i = 0; i < [downloadItemControllers_ count]; ++i) {
if ([[downloadItemControllers_ objectAtIndex:i]download]->IsInProgress())
@@ -277,16 +296,20 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
- (void)addDownloadItem:(DownloadItem*)downloadItem {
DCHECK([NSThread isMainThread]);
- [self cancelAutoCloseAndRemoveTrackingArea];
-
- // Insert new item at the left.
scoped_nsobject<DownloadItemController> controller(
[[DownloadItemController alloc] initWithDownload:downloadItem
shelf:self
navigator:navigator_]);
+ [self add:controller.get()];
+}
+
+- (void)add:(DownloadItemController*)controller {
+ DCHECK([NSThread isMainThread]);
+ shouldCloseOnMouseExit_ = NO;
+ // Insert new item at the left.
// Adding at index 0 in NSMutableArrays is O(1).
- [downloadItemControllers_ insertObject:controller.get() atIndex:0];
+ [downloadItemControllers_ insertObject:controller atIndex:0];
[itemContainerView_ addSubview:[controller view]];
@@ -324,7 +347,8 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
// Since no user will ever see the item being removed (needs a horizontal
// screen resolution greater than 3200 at 16 items at 200 pixels each),
// there's no point in animating the removal.
- [self remove:[downloadItemControllers_ lastObject]];
+ [self removeDownload:[downloadItemControllers_ lastObject]
+ isShelfClosing:NO];
}
// Finally, move the remaining items to the right. Skip the first item when
@@ -347,7 +371,8 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
download->IsCancelled() ||
download->IsInterrupted();
if (isTransferDone && !download->IsDangerous()) {
- [self remove:itemController];
+ [self removeDownload:itemController
+ isShelfClosing:YES];
} else {
// Treat the item as opened when we close. This way if we get shown again
// the user need not open this item for the shelf to auto-close.
@@ -358,16 +383,24 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
}
- (void)mouseEntered:(NSEvent*)event {
+ isMouseInsideView_ = YES;
// If the mouse re-enters the download shelf, cancel the auto-close. Further
- // mouse exits should not trigger autoclose, so also remove the tracking area.
- [self cancelAutoCloseAndRemoveTrackingArea];
+ // mouse exits should not trigger autoclose.
+ if (shouldCloseOnMouseExit_) {
+ [self cancelAutoClose];
+ shouldCloseOnMouseExit_ = NO;
+ }
}
- (void)mouseExited:(NSEvent*)event {
+ isMouseInsideView_ = NO;
+ if (shouldCloseOnMouseExit_)
+ [self scheduleAutoClose];
+}
+
+- (void)scheduleAutoClose {
// Cancel any previous hide requests, just to be safe.
- [NSObject cancelPreviousPerformRequestsWithTarget:self
- selector:@selector(autoClose)
- object:nil];
+ [self cancelAutoClose];
// Schedule an autoclose after a delay. If the mouse is moved back into the
// view, or if an item is added to the shelf, the timer will be canceled.
@@ -376,6 +409,12 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
afterDelay:kAutoCloseDelaySeconds];
}
+- (void)cancelAutoClose {
+ [NSObject cancelPreviousPerformRequestsWithTarget:self
+ selector:@selector(autoClose)
+ object:nil];
+}
+
- (void)maybeAutoCloseAfterDelay {
// We can close the shelf automatically if all the downloads on the shelf have
// been opened.
@@ -386,14 +425,12 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
return;
}
- if ([self isVisible] && [downloadItemControllers_ count] > 0) {
- // If the shelf is visible and has download items remaining on it, close the
- // shelf after the user moves the mouse out of the download shelf. Note that
- // the mouse might not be over the shelf. In this case, the shelf will not
- // auto close.
- // TODO(asanka): Don't install a tracking area if the mouse isn't over the
- // shelf. Autoclose instead.
- [self installTrackingArea];
+ if ([self isVisible] && [downloadItemControllers_ count] > 0 &&
+ isMouseInsideView_) {
+ // If there are download items on the shelf and the user is potentially stil
+ // interacting with them, schedule an auto close after the user moves the
+ // mouse off the shelf.
+ shouldCloseOnMouseExit_ = YES;
} else {
// We notify the DownloadShelf of our intention to close even if the shelf
// is currently hidden. If the shelf was temporarily hidden (e.g. because
@@ -408,28 +445,23 @@ const NSSize kHoverCloseButtonDefaultSize = { 18, 18 };
}
- (void)installTrackingArea {
- // Install the tracking area to listen for mouseExited messages and trigger
- // the shelf autoclose.
- if (trackingArea_.get())
- return;
+ // Install the tracking area to listen for mouseEntered and mouseExited
+ // messages.
+ DCHECK(!trackingArea_.get());
- trackingArea_.reset([[NSTrackingArea alloc]
+ trackingArea_.reset([[CrTrackingArea alloc]
initWithRect:[[self view] bounds]
options:NSTrackingMouseEnteredAndExited |
NSTrackingActiveAlways |
NSTrackingInVisibleRect
owner:self
userInfo:nil]);
- [[self view] addTrackingArea:trackingArea_];
+ [[self view] addTrackingArea:trackingArea_.get()];
}
-- (void)cancelAutoCloseAndRemoveTrackingArea {
- [NSObject cancelPreviousPerformRequestsWithTarget:self
- selector:@selector(autoClose)
- object:nil];
-
+- (void)removeTrackingArea {
if (trackingArea_.get()) {
- [[self view] removeTrackingArea:trackingArea_];
+ [[self view] removeTrackingArea:trackingArea_.get()];
trackingArea_.reset(nil);
}
}

Powered by Google App Engine
This is Rietveld 408576698