Chromium Code Reviews
Help | Chromium Project | Sign in
(36)

Side by Side Diff: chrome/browser/cocoa/tabpose_window.mm

Issue 3163003: Mac tabpose: Add thumbnails (Closed)
Patch Set: observer stuff Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/cocoa/tabpose_window.h" 5 #import "chrome/browser/cocoa/tabpose_window.h"
6 6
7 #import <QuartzCore/QuartzCore.h> 7 #import <QuartzCore/QuartzCore.h>
8 8
9 #include "app/resource_bundle.h" 9 #include "app/resource_bundle.h"
10 #include "base/mac_util.h" 10 #include "base/mac_util.h"
11 #include "base/scoped_callback_factory.h"
11 #include "base/sys_string_conversions.h" 12 #include "base/sys_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
12 #import "chrome/browser/cocoa/browser_window_controller.h" 14 #import "chrome/browser/cocoa/browser_window_controller.h"
13 #import "chrome/browser/cocoa/tab_strip_controller.h" 15 #import "chrome/browser/cocoa/tab_strip_controller.h"
16 #include "chrome/browser/renderer_host/backing_store_mac.h"
17 #include "chrome/browser/renderer_host/render_view_host.h"
14 #include "chrome/browser/tab_contents/tab_contents.h" 18 #include "chrome/browser/tab_contents/tab_contents.h"
19 #include "chrome/browser/tab_contents/thumbnail_generator.h"
15 #include "grit/app_resources.h" 20 #include "grit/app_resources.h"
16 #include "skia/ext/skia_utils_mac.h" 21 #include "skia/ext/skia_utils_mac.h"
22 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
17 23
18 const int kTopGradientHeight = 15; 24 const int kTopGradientHeight = 15;
19 25
20 NSString* const kAnimationIdKey = @"AnimationId"; 26 NSString* const kAnimationIdKey = @"AnimationId";
21 NSString* const kAnimationIdFadeIn = @"FadeIn"; 27 NSString* const kAnimationIdFadeIn = @"FadeIn";
22 NSString* const kAnimationIdFadeOut = @"FadeOut"; 28 NSString* const kAnimationIdFadeOut = @"FadeOut";
23 29
24 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds. 30 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds.
25 const CGFloat kSlomoFactor = 4; 31 const CGFloat kSlomoFactor = 4;
26 32
27 // CAGradientLayer is 10.6-only -- roll our own. 33 // CAGradientLayer is 10.6-only -- roll our own.
28 @interface DarkGradientLayer : CALayer 34 @interface DarkGradientLayer : CALayer
29 - (void)drawInContext:(CGContextRef)context; 35 - (void)drawInContext:(CGContextRef)context;
30 @end 36 @end
31 37
32 @implementation DarkGradientLayer 38 @implementation DarkGradientLayer
33 - (void)drawInContext:(CGContextRef)context { 39 - (void)drawInContext:(CGContextRef)context {
34 scoped_cftyperef<CGColorSpaceRef> grayColorSpace( 40 scoped_cftyperef<CGColorSpaceRef> grayColorSpace(
35 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray)); 41 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray));
36 CGFloat grays[] = { 0.277, 1.0, 0.39, 1.0 }; 42 CGFloat grays[] = { 0.277, 1.0, 0.39, 1.0 };
37 CGFloat locations[] = { 0, 1 }; 43 CGFloat locations[] = { 0, 1 };
38 scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents( 44 scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents(
39 grayColorSpace.get(), grays, locations, arraysize(locations))); 45 grayColorSpace.get(), grays, locations, arraysize(locations)));
40 CGPoint topLeft = CGPointMake(0.0, kTopGradientHeight); 46 CGPoint topLeft = CGPointMake(0.0, kTopGradientHeight);
41 CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0); 47 CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0);
42 } 48 }
43 @end 49 @end
44 50
51 // FIXME: this needs to be cleaned up a lot
52
53 // FIXME: look at URLFetcher's inner class for thread switching
54
55 // FIMXE comment is wrong
56 // A helper class used to interface with chrome's c++ code. Used to dispatch
57 // stuff to threads; to listen for things; etc.
58 class TabposeHelper : public base::RefCountedThreadSafe<TabposeHelper> {
59 public:
60 TabposeHelper(/*TabposeWindow* window*/NSSize fullS)
61 : nsFullSize(fullS) /*window_(window)*//*, factory_(this)*/ , layer_(nil), factory_(this) {}
62
63 void LoadThumbnail(RenderWidgetHost* rwh, CALayer* layer2, const gfx::Size& s) ;
64 private:
65 friend class base::RefCountedThreadSafe<TabposeHelper>;
66 ~TabposeHelper() {}
67
68 void DidReceiveBitmap(const SkBitmap& bitmap) {
69 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
70 NSLog(@"receiving bitmap %d %d", bitmap.width(), bitmap.height());
71 // FIXME: too many conversions (SkCreateCGImageRef() actually shares memory,
72 // so it's not too bad)
73 cgimage.reset(SkCreateCGImageRef(bitmap));
74 layer_.contents = (id)cgimage.get();
75 }
76
77 scoped_cftyperef<CGImageRef> cgimage;
78 NSSize nsFullSize;
79 CALayer* layer_;
80 base::ScopedCallbackFactory<TabposeHelper> factory_;
81 };
82
83 void TabposeHelper::LoadThumbnail(RenderWidgetHost* rwh, CALayer* layer2, const
84 gfx::Size& s) {
85 gfx::Size fullSize(NSSizeToCGSize(nsFullSize));
86
87 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
88
89 // Don't need to go on IO thread, as this just sends an IPC anyway
90 // (and ScopedCallbackFactory isn't threadsafe :-P)
91 ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
92
93 // FIXME: Internally, this allocs memory for both transport dib and then
94 // an SkBitmap (which _then_ needs to be converted to a CGImageRef).
95 // Reduce the amount of copying; possibly by sidestepping
96 // ThumbnailGenerator.
97 CHECK(!layer_);
98 layer_ = layer2;
99
100 // |fullSize| is slightly larger (view bounds doesn't include scroll bars?)
101 gfx::Size page_size(fullSize); // Logical size the renderer renders at
102
103 // This is a bit tricky: We really only need a bitmap at size |s|, but when
104 // the user clicks a thumbnail and it zooms large, this single thumbnail
105 // should have a pixel size close to the view bounds, so that the image doesnt
106 // get blurry. One possible idea would be to get all thumbs at size |s| and
107 // request the one currently below the mouse at full size, but then it might
108 // not be ready when the click happens. For now, KISS, and request everything
109 // at the full resolution.
110 // FIXME: even better plan: call model->selectTab before starting the bg anima tion.
111 // that makes sure the target tab has a backing store. then call setNeedsDispl ay on the
112 // layer, and it'll be redrawn from the backing store -- and all bg thumbs can stay small.
113 // yay! (is this true?) => no :-/, it takes too long for the backing store to load.
114 //gfx::Size desired_size(s); // physical pixel size the image is rendered at
115 gfx::Size desired_size(fullSize); // physical pixel size the image is rendere d at
116 NSLog(@"scheduling snapshot request");
117
118 // FIXME: check that observer is currently NULL
119 // FIXME: set observer back to NULL at some point
120 rwh->set_painting_observer(generator);
121 generator->AskForSnapshot(rwh, /*prefer_backing_store=*/false,
122 factory_.NewCallback(&TabposeHelper::DidReceiveBitma p),
123 page_size, desired_size);
124 }
125
126
127
128 // A CALayer that draws a CGLayerRef (or a CGBitmap).
129 @interface BackingStoreLayer : CALayer {
130 TabContents* contents_; // should really have a tabpose::Tile*?
131 NSSize smallSize;
132 NSSize fullSize;
133 scoped_refptr<TabposeHelper> helper_;
134 BOOL didSendLoad_;
135 }
136 - (id)initWithTabContents:(TabContents*)contents smallSize:(NSSize)s fullSize:(N SSize)s2;
137 - (void)drawInContext:(CGContextRef)context;
138 @end
139
140 @implementation BackingStoreLayer
141 - (id)initWithTabContents:(TabContents*)contents smallSize:(NSSize)s fullSize:(N SSize)s2 {
142 CHECK(contents);
143 if ((self = [super init])) {
144 contents_ = contents;
145 smallSize = s;
146 fullSize = s2;
147 }
148 return self;
149 }
150
151 - (void)drawInContext:(CGContextRef)context {
152 RenderWidgetHost* rwh = contents_->render_view_host();
153 BackingStoreMac* backing_store_ = (BackingStoreMac*)rwh->GetBackingStore(false );
154 if (!backing_store_) {
155 // Either the tab was never visible, or its backing store got evicted.
156
157 NSLog(@"drawing layer without backingstore %d %@", didSendLoad_, self.contents);
158 // do this only if we haven't already sent a thumbnail request before
159 // else this is done on hide and way too much in general
160 if (!didSendLoad_) {
161 helper_ = new TabposeHelper(NSSizeFromCGSize(NSSizeToCGSize(fullSize)));
162 helper_->LoadThumbnail(rwh, self, gfx::Size(NSSizeToCGSize(smallSize)));
163 didSendLoad_ = YES;
164
165 // Overwrites |contents|, so do this only once, to fill with bg color.
166 [super drawInContext:context];
167 }
168
169 if ([self contents]) {
170 CGContextDrawImage(context, [self bounds], (CGImageRef)[self contents]);
171 }
172
173 return;
174 }
175
176 // TODO(thakis): re-send PaintAt ipc when tabstripmodelobserver informs us
177 // that a tab has changed (reload favicon & title, too)
178
179 // TODO(thakis): backing store might have wrong size (?)
180
181 // TODO(thakis): composited tabs might not be rendered correctly by this
182 // (once this is in BWC, let it add a sublayer for all IOSurfaces)
183
184 // TODO(thakis): Draw only into rect not occupied by info bars, detached
185 // bookmarks bar, devtool
186 if (backing_store_->cg_layer()) {
187 CGContextDrawLayerInRect(context, [self bounds],
188 backing_store_->cg_layer());
189 } else {
190 NSLog(@"no layer!");
191 scoped_cftyperef<CGImageRef> image(
192 CGBitmapContextCreateImage(backing_store_->cg_bitmap()));
193 CGContextDrawImage(context, [self bounds], image);
194 }
195 }
196 @end
197
198
199
45 namespace { 200 namespace {
46 201
47 class ScopedCAActionDisabler { 202 class ScopedCAActionDisabler {
48 public: 203 public:
49 ScopedCAActionDisabler() { 204 ScopedCAActionDisabler() {
50 [CATransaction begin]; 205 [CATransaction begin];
51 [CATransaction setValue:[NSNumber numberWithBool:YES] 206 [CATransaction setValue:[NSNumber numberWithBool:YES]
52 forKey:kCATransactionDisableActions]; 207 forKey:kCATransactionDisableActions];
53 } 208 }
54 209
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 // 2. loads that font 281 // 2. loads that font
127 // 3. calls |set_font_metrics()| which updates the title rect 282 // 3. calls |set_font_metrics()| which updates the title rect
128 // 4. receives the title rect and puts the title on it with the font from 2. 283 // 4. receives the title rect and puts the title on it with the font from 2.
129 void set_font_metrics(CGFloat ascender, CGFloat descender); 284 void set_font_metrics(CGFloat ascender, CGFloat descender);
130 CGFloat title_font_size() const { return title_font_size_; } 285 CGFloat title_font_size() const { return title_font_size_; }
131 286
132 NSRect title_rect() const { return title_rect_; } 287 NSRect title_rect() const { return title_rect_; }
133 288
134 // Returns an unelided title. The view logic is responsible for eliding. 289 // Returns an unelided title. The view logic is responsible for eliding.
135 const string16& title() const { return contents_->GetTitle(); } 290 const string16& title() const { return contents_->GetTitle(); }
291
292 TabContents* tab_contents() const { return contents_; }
136 private: 293 private:
137 friend class TileSet; 294 friend class TileSet;
138 295
139 // The thumb rect includes infobars, detached thumbnail bar, web contents, 296 // The thumb rect includes infobars, detached thumbnail bar, web contents,
140 // and devtools. 297 // and devtools.
141 NSRect thumb_rect_; 298 NSRect thumb_rect_;
142 NSRect start_thumb_rect_; 299 NSRect start_thumb_rect_;
143 300
144 NSRect favicon_rect_; 301 NSRect favicon_rect_;
145 302
(...skipping 30 matching lines...) Expand all
176 // Move favicon down. 333 // Move favicon down.
177 favicon_rect_.origin.y = title_rect_.origin.y + descender; 334 favicon_rect_.origin.y = title_rect_.origin.y + descender;
178 } else { 335 } else {
179 // Move title down. 336 // Move title down.
180 title_rect_.origin.y = favicon_rect_.origin.y - descender; 337 title_rect_.origin.y = favicon_rect_.origin.y - descender;
181 } 338 }
182 } 339 }
183 340
184 // A tileset is responsible for owning and laying out all |Tile|s shown in a 341 // A tileset is responsible for owning and laying out all |Tile|s shown in a
185 // tabpose window. 342 // tabpose window.
186 class TileSet { 343 class TileSet : public TabStripModelObserver {
187 public: 344 public:
345 virtual ~TileSet() { source_model_->RemoveObserver(this); } // FIXME: crashes if Build() wasn't called.
188 // Fills in |tiles_|. 346 // Fills in |tiles_|.
189 void Build(TabStripModel* source_model); 347 void Build(TabStripModel* source_model);
190 348
191 // Computes coordinates for |tiles_|. 349 // Computes coordinates for |tiles_|.
192 void Layout(NSRect containing_rect); 350 void Layout(NSRect containing_rect);
193 351
194 int selected_index() const { return selected_index_; } 352 int selected_index() const { return selected_index_; }
195 void set_selected_index(int index); 353 void set_selected_index(int index);
196 void ResetSelectedIndex() { selected_index_ = initial_index_; } 354 void ResetSelectedIndex() { selected_index_ = initial_index_; }
197 355
198 const Tile& selected_tile() const { return *tiles_[selected_index()]; } 356 const Tile& selected_tile() const { return *tiles_[selected_index()]; }
199 Tile& tile_at(int index) { return *tiles_[index]; } 357 Tile& tile_at(int index) { return *tiles_[index]; }
200 const Tile& tile_at(int index) const { return *tiles_[index]; } 358 const Tile& tile_at(int index) const { return *tiles_[index]; }
201 359
360 // TabStripModelObserver
361 virtual void TabInsertedAt(TabContents* contents,
362 int index,
363 bool foreground) { CHECK(false); }
364 virtual void TabClosingAt(TabContents* contents, int index) { CHECK(false); }
365 virtual void TabDetachedAt(TabContents* contents, int index) { CHECK(false); }
366 virtual void TabMoved(TabContents* contents,
367 int from_index,
368 int to_index) { CHECK(false); }
369 virtual void TabStripModelDeleted() { CHECK(false); }
370 virtual void TabChangedAt(TabContents* contents, int index,
371 TabChangeType change_type) {
372 // FIXME: update tile with |contents|, reload title, favicon, thumb
373 // depending on |change_type|.
374 }
375
202 private: 376 private:
203 ScopedVector<Tile> tiles_; 377 ScopedVector<Tile> tiles_;
204 378
205 int selected_index_; 379 int selected_index_;
206 int initial_index_; 380 int initial_index_;
381
382 TabStripModel* source_model_;
207 }; 383 };
208 384
209 void TileSet::Build(TabStripModel* source_model) { 385 void TileSet::Build(TabStripModel* source_model) {
210 selected_index_ = initial_index_ = source_model->selected_index(); 386 selected_index_ = initial_index_ = source_model->selected_index();
211 tiles_.resize(source_model->count()); 387 tiles_.resize(source_model->count());
212 for (size_t i = 0; i < tiles_.size(); ++i) { 388 for (size_t i = 0; i < tiles_.size(); ++i) {
213 tiles_[i] = new Tile; 389 tiles_[i] = new Tile;
214 tiles_[i]->contents_ = source_model->GetTabContentsAt(i); 390 tiles_[i]->contents_ = source_model->GetTabContentsAt(i);
215 } 391 }
392
393 source_model->AddObserver(this);
394 source_model_ = source_model;
216 } 395 }
217 396
218 void TileSet::Layout(NSRect containing_rect) { 397 void TileSet::Layout(NSRect containing_rect) {
219 int tile_count = tiles_.size(); 398 int tile_count = tiles_.size();
220 399
221 // Room around the tiles insde of |containing_rect|. 400 // Room around the tiles insde of |containing_rect|.
222 const int kSmallPaddingTop = 30; 401 const int kSmallPaddingTop = 30;
223 const int kSmallPaddingLeft = 30; 402 const int kSmallPaddingLeft = 30;
224 const int kSmallPaddingRight = 30; 403 const int kSmallPaddingRight = 30;
225 const int kSmallPaddingBottom = 30; 404 const int kSmallPaddingBottom = 30;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 const tabpose::Tile& tile = tileSet_->tile_at(newIndex); 651 const tabpose::Tile& tile = tileSet_->tile_at(newIndex);
473 selectionHighlight_.frame = 652 selectionHighlight_.frame =
474 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -5, -5)); 653 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -5, -5));
475 654
476 tileSet_->set_selected_index(newIndex); 655 tileSet_->set_selected_index(newIndex);
477 } 656 }
478 657
479 - (void)setUpLayers:(NSRect)bgLayerRect slomo:(BOOL)slomo { 658 - (void)setUpLayers:(NSRect)bgLayerRect slomo:(BOOL)slomo {
480 // Root layer -- covers whole window. 659 // Root layer -- covers whole window.
481 rootLayer_ = [CALayer layer]; 660 rootLayer_ = [CALayer layer];
482 [[self contentView] setLayer:rootLayer_];
483 [[self contentView] setWantsLayer:YES];
484 661
485 // Background layer -- the visible part of the window. 662 // In a block so that the layers don't fade in.
486 gray_.reset(CGColorCreateGenericGray(0.39, 1.0)); 663 {
487 bgLayer_ = [CALayer layer]; 664 ScopedCAActionDisabler disabler;
488 bgLayer_.backgroundColor = gray_; 665 // Background layer -- the visible part of the window.
489 bgLayer_.frame = NSRectToCGRect(bgLayerRect); 666 gray_.reset(CGColorCreateGenericGray(0.39, 1.0));
490 bgLayer_.masksToBounds = YES; 667 bgLayer_ = [CALayer layer];
491 [rootLayer_ addSublayer:bgLayer_]; 668 bgLayer_.backgroundColor = gray_;
669 bgLayer_.frame = NSRectToCGRect(bgLayerRect);
670 bgLayer_.masksToBounds = YES;
671 [rootLayer_ addSublayer:bgLayer_];
492 672
493 // Selection highlight layer. 673 // Selection highlight layer.
494 darkBlue_.reset(CGColorCreateGenericRGB(0.25, 0.34, 0.86, 1.0)); 674 darkBlue_.reset(CGColorCreateGenericRGB(0.25, 0.34, 0.86, 1.0));
495 selectionHighlight_ = [CALayer layer]; 675 selectionHighlight_ = [CALayer layer];
496 selectionHighlight_.backgroundColor = darkBlue_; 676 selectionHighlight_.backgroundColor = darkBlue_;
497 selectionHighlight_.cornerRadius = 5.0; 677 selectionHighlight_.cornerRadius = 5.0;
498 selectionHighlight_.zPosition = -1; // Behind other layers. 678 selectionHighlight_.zPosition = -1; // Behind other layers.
499 selectionHighlight_.hidden = YES; 679 selectionHighlight_.hidden = YES;
500 [bgLayer_ addSublayer:selectionHighlight_]; 680 [bgLayer_ addSublayer:selectionHighlight_];
501 681
502 // Top gradient. 682 // Top gradient.
503 CALayer* gradientLayer = [DarkGradientLayer layer]; 683 CALayer* gradientLayer = [DarkGradientLayer layer];
504 gradientLayer.frame = CGRectMake( 684 gradientLayer.frame = CGRectMake(
505 0, 685 0,
506 NSHeight(bgLayerRect) - kTopGradientHeight, 686 NSHeight(bgLayerRect) - kTopGradientHeight,
507 NSWidth(bgLayerRect), 687 NSWidth(bgLayerRect),
508 kTopGradientHeight); 688 kTopGradientHeight);
509 [gradientLayer setNeedsDisplay]; // Draw once. 689 [gradientLayer setNeedsDisplay]; // Draw once.
510 [bgLayer_ addSublayer:gradientLayer]; 690 [bgLayer_ addSublayer:gradientLayer];
511 691 }
512 // Layers for the tab thumbnails. 692 // Layers for the tab thumbnails.
513 tileSet_->Build(tabStripModel_); 693 tileSet_->Build(tabStripModel_);
514 tileSet_->Layout(bgLayerRect); 694 tileSet_->Layout(bgLayerRect);
515 695
516 NSImage* defaultFavIcon = ResourceBundle::GetSharedInstance().GetNSImageNamed( 696 NSImage* defaultFavIcon = ResourceBundle::GetSharedInstance().GetNSImageNamed(
517 IDR_DEFAULT_FAVICON); 697 IDR_DEFAULT_FAVICON);
518 698
519 allThumbnailLayers_.reset( 699 allThumbnailLayers_.reset(
520 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]); 700 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
521 allFaviconLayers_.reset( 701 allFaviconLayers_.reset(
522 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]); 702 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
523 allTitleLayers_.reset( 703 allTitleLayers_.reset(
524 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]); 704 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
525 for (int i = 0; i < tabStripModel_->count(); ++i) { 705 for (int i = 0; i < tabStripModel_->count(); ++i) {
526 const tabpose::Tile& tile = tileSet_->tile_at(i); 706 const tabpose::Tile& tile = tileSet_->tile_at(i);
527 CALayer* layer = [CALayer layer]; 707
708
709 // FIXME: BrowserWindowController should create this layer
710 CALayer* layer = [[[BackingStoreLayer alloc] initWithTabContents:tile.tab_co ntents() smallSize:tile.thumb_rect().size fullSize:tile.GetStartRectRelativeTo(t ileSet_->selected_tile()).size] autorelease];
711 [layer setNeedsDisplay];
528 712
529 // Background color as placeholder for now. 713 // Background color as placeholder for now.
530 layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); 714 layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite);
531 715
532 AnimateCALayerFrameFromTo( 716 AnimateCALayerFrameFromTo(
533 layer, 717 layer,
534 tile.GetStartRectRelativeTo(tileSet_->selected_tile()), 718 tile.GetStartRectRelativeTo(tileSet_->selected_tile()),
535 tile.thumb_rect(), 719 tile.thumb_rect(),
536 kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1), 720 kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1),
537 i == tileSet_->selected_index() ? self : nil); 721 i == tileSet_->selected_index() ? self : nil);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 titleLayer.string = base::SysUTF16ToNSString(tile.title()); 759 titleLayer.string = base::SysUTF16ToNSString(tile.title());
576 titleLayer.fontSize = [font pointSize]; 760 titleLayer.fontSize = [font pointSize];
577 titleLayer.truncationMode = kCATruncationEnd; 761 titleLayer.truncationMode = kCATruncationEnd;
578 titleLayer.font = font; 762 titleLayer.font = font;
579 titleLayer.zPosition = 1; // On top of the thumb shadow. 763 titleLayer.zPosition = 1; // On top of the thumb shadow.
580 titleLayer.hidden = YES; 764 titleLayer.hidden = YES;
581 [bgLayer_ addSublayer:titleLayer]; 765 [bgLayer_ addSublayer:titleLayer];
582 [allTitleLayers_ addObject:titleLayer]; 766 [allTitleLayers_ addObject:titleLayer];
583 } 767 }
584 [self selectTileAtIndex:tileSet_->selected_index()]; 768 [self selectTileAtIndex:tileSet_->selected_index()];
769
770 // Needs to happen after all layers have been added to |rootLayer_|, else
771 // there's a one frame flash of grey at the beginning of the animation
772 // (|bgLayer_| showing through with none of its children visible yet).
773 [[self contentView] setLayer:rootLayer_];
774 [[self contentView] setWantsLayer:YES];
585 } 775 }
586 776
587 - (BOOL)canBecomeKeyWindow { 777 - (BOOL)canBecomeKeyWindow {
588 return YES; 778 return YES;
589 } 779 }
590 780
591 - (void)keyDown:(NSEvent*)event { 781 - (void)keyDown:(NSEvent*)event {
592 // Overridden to prevent beeps. 782 // Overridden to prevent beeps.
593 } 783 }
594 784
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 for (CALayer* layer in allTitleLayers_.get()) 866 for (CALayer* layer in allTitleLayers_.get())
677 layer.hidden = YES; 867 layer.hidden = YES;
678 868
679 // Running animations with shadows is slow, so turn shadows off before 869 // Running animations with shadows is slow, so turn shadows off before
680 // running the exit animation. 870 // running the exit animation.
681 for (CALayer* layer in allThumbnailLayers_.get()) 871 for (CALayer* layer in allThumbnailLayers_.get())
682 layer.shadowOpacity = 0.0; 872 layer.shadowOpacity = 0.0;
683 } 873 }
684 874
685 // Animate layers out, all in one transaction. 875 // Animate layers out, all in one transaction.
686 CGFloat duration = kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); 876 CGFloat duration = 2 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1);
687 ScopedCAActionSetDuration durationSetter(duration); 877 ScopedCAActionSetDuration durationSetter(duration);
688 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { 878 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
689 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; 879 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i];
690 // |start_thumb_rect_| was relative to |initial_index_|, now this needs to 880 // |start_thumb_rect_| was relative to |initial_index_|, now this needs to
691 // be relative to |selectedIndex_| (whose start rect was relative to 881 // be relative to |selectedIndex_| (whose start rect was relative to
692 // |initial_index_| too) 882 // |initial_index_| too)
693 CGRect newFrame = NSRectToCGRect( 883 CGRect newFrame = NSRectToCGRect(
694 tileSet_->tile_at(i).GetStartRectRelativeTo(tileSet_->selected_tile())); 884 tileSet_->tile_at(i).GetStartRectRelativeTo(tileSet_->selected_tile()));
695 885
696 // Add a delegate to one of the implicit animations to get a notification 886 // Add a delegate to one of the implicit animations to get a notification
697 // once the animations are done. 887 // once the animations are done.
698 if (static_cast<int>(i) == tileSet_->selected_index()) { 888 if (static_cast<int>(i) == tileSet_->selected_index()) {
699 CAAnimation* animation = [CAAnimation animation]; 889 CAAnimation* animation = [CAAnimation animation];
700 animation.delegate = self; 890 animation.delegate = self;
701 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey]; 891 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey];
702 [layer addAnimation:animation forKey:@"frame"]; 892 [layer addAnimation:animation forKey:@"frame"];
703 } 893 }
704 894
705 layer.frame = newFrame; 895 layer.frame = newFrame;
896
897 if (static_cast<int>(i) == tileSet_->selected_index()) {
898 // FIXME: only do this if the layer has a backing store (?)
899 [layer setNeedsDisplay]; // Redraw layer at big resolution, so that zoom- in isn't blocky.
900 }
706 } 901 }
707 } 902 }
708 903
709 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { 904 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
710 NSString* animationId = [animation valueForKey:kAnimationIdKey]; 905 NSString* animationId = [animation valueForKey:kAnimationIdKey];
711 if ([animationId isEqualToString:kAnimationIdFadeIn]) { 906 if ([animationId isEqualToString:kAnimationIdFadeIn]) {
712 if (finished) { 907 if (finished) {
713 // If the user clicks while the fade in animation is still running, 908 // If the user clicks while the fade in animation is still running,
714 // |state_| is already kFadingOut. In that case, don't do anything. 909 // |state_| is already kFadingOut. In that case, don't do anything.
715 DCHECK_EQ(tabpose::kFadingIn, state_); 910 DCHECK_EQ(tabpose::kFadingIn, state_);
(...skipping 11 matching lines...) Expand all
727 for (CALayer* layer in allThumbnailLayers_.get()) 922 for (CALayer* layer in allThumbnailLayers_.get())
728 layer.shadowOpacity = 0.5; 923 layer.shadowOpacity = 0.5;
729 } 924 }
730 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) { 925 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) {
731 DCHECK_EQ(tabpose::kFadingOut, state_); 926 DCHECK_EQ(tabpose::kFadingOut, state_);
732 [self close]; 927 [self close];
733 } 928 }
734 } 929 }
735 930
736 @end 931 @end
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld ec887be