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

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

Issue 2976008: Bar (Closed)
Patch Set: '' Created 10 years, 4 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 unified diff | Download patch
« no previous file with comments | « chrome/browser/cocoa/tabpose_window.h ('k') | chrome/browser/cocoa/tabpose_window_unittest.mm » ('j') | 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 "base/mac_util.h"
10 #include "base/scoped_cftyperef.h"
11 #include "base/task.h"
12 #include "chrome/browser/browser_process.h"
13 #import "chrome/browser/cocoa/browser_window_controller.h"
14 #import "chrome/browser/cocoa/fast_resize_view.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_widget_host_view.h"
18 #include "chrome/browser/renderer_host/render_view_host.h"
19 #include "chrome/browser/tab_contents/tab_contents.h"
20 #include "chrome/browser/tab_contents/thumbnail_generator.h"
21 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
22
23 // FIXME: Need to listen for tab creation / destruction and react to that
24 // FIXME: would be nice if at least the selected tab would be "live" (i.e.
25 // videos play etc)
26 // FIXME (related?): crashes if invoked while stuff is still loading
27
28 const float S = 1.03;
29
9 const int kTopGradientHeight = 15; 30 const int kTopGradientHeight = 15;
10 31
11 // CAGradientLayer is 10.6-only -- roll our own. 32 // CAGradientLayer is 10.6-only -- roll our own.
12 @interface DarkGradientLayer : CALayer 33 @interface DarkGradientLayer : CALayer
13 - (void)drawInContext:(CGContextRef)context; 34 - (void)drawInContext:(CGContextRef)context;
14 @end 35 @end
15 36
37 // CAGradientLayer is 10.6-only -- roll our own
38 @interface GradientLayer : CALayer
39 - (void)drawInContext:(CGContextRef)context;
40 @end
41
42 @implementation GradientLayer
43 - (void)drawInContext:(CGContextRef)context {
44 scoped_cftyperef<CGColorSpaceRef> grayColorspace(
45 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray));
46 NSLog(@"count: %d", CGColorSpaceGetNumberOfComponents(grayColorspace));
47 CGFloat grays[] = { 0.1, 0.39 };
48 CGFloat locations[] = { 0, 1 };
49 scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents(
50 grayColorspace, grays, locations, arraysize(grays)));
51
52 CGPoint midY = CGPointMake(0.0, 15);
53 CGContextDrawLinearGradient(context, gradient, midY, CGPointZero, 0);
54 }
55 @end
56
57 // A CALayer that draws a CGLayerRef (or a CGBitmap).
58 @interface BackingStoreLayer : CALayer {
59 BackingStoreMac* backing_store_;
60 }
61 - (id)initWithBackingStore:(BackingStoreMac*)store;
62 - (void)drawInContext:(CGContextRef)context;
63 @end
64
16 @implementation DarkGradientLayer 65 @implementation DarkGradientLayer
17 - (void)drawInContext:(CGContextRef)context { 66 - (void)drawInContext:(CGContextRef)context {
18 scoped_cftyperef<CGColorSpaceRef> grayColorSpace( 67 scoped_cftyperef<CGColorSpaceRef> grayColorSpace(
19 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray)); 68 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray));
20 CGFloat grays[] = { 0.277, 1.0, 0.39, 1.0 }; 69 CGFloat grays[] = { 0.277, 1.0, 0.39, 1.0 };
21 CGFloat locations[] = { 0, 1 }; 70 CGFloat locations[] = { 0, 1 };
22 scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents( 71 scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents(
23 grayColorSpace.get(), grays, locations, arraysize(locations))); 72 grayColorSpace.get(), grays, locations, arraysize(locations)));
24 CGPoint topLeft = CGPointMake(0.0, kTopGradientHeight); 73 CGPoint topLeft = CGPointMake(0.0, kTopGradientHeight);
25 CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0); 74 CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0);
26 } 75 }
27 @end 76 @end
28 77
78 @implementation BackingStoreLayer
79 - (id)initWithBackingStore:(BackingStoreMac*)store {
80 CHECK(store);
81 if ((self = [super init])) {
82 backing_store_ = store;
83 }
84 return self;
85 }
86
87 - (void)drawInContext:(CGContextRef)context {
88 // Hrm, looks like I need to use the drawing delegate functionality of
89 // a layer here
90 if (backing_store_->cg_layer()) {
91 // TODO: add clipping to dirtyRect if it improves drawing performance.
92 CGContextDrawLayerInRect(context, [self bounds],
93 backing_store_->cg_layer());
94 } else {
95 NSLog(@"no layer!");
96 // if we haven't created a layer yet, draw the cached bitmap into
97 // the window. The CGLayer will be created the next time the renderer
98 // paints.
99 scoped_cftyperef<CGImageRef> image(
100 CGBitmapContextCreateImage(backing_store_->cg_bitmap()));
101 CGContextDrawImage(context, [self bounds], image);
102 }
103 }
104 @end
105
106 // FIXME comment
107 class TabposeCallback {
108 public:
109 TabposeCallback(CALayer* layer)
110 : layer_(layer) {}
111
112 void DidReceiveBitmap(const SkBitmap& bitmap) {
113 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
114 NSLog(@"receiving bitmap %d %d", bitmap.width(), bitmap.height());
115 // FIXME: too many conversions
116 scoped_cftyperef<CGImageRef> cgimage(SkCreateCGImageRef(bitmap));
117 layer_.contents = (id)cgimage.get();
118 layer_.backgroundColor = nil; // clear out bg color to default value
119 }
120 private:
121 CALayer* layer_;
122 };
123
124 // FIXME: look at DISABLE_RUNNABLE_METHOD_REFCOUNT
125 // FIXME: look at URLFetcher's inner class for thread switching
126
127 // FIMXE comment is wrong
128 // A helper class used to interface with chrome's c++ code. Used to dispatch
129 // stuff to threads; to listen for things; etc.
130 class TabposeHelper : public base::RefCountedThreadSafe<TabposeHelper> {
131 public:
132 TabposeHelper(TabposeWindow* window)
133 : window_(window)/*, factory_(this)*/ {}
134
135 void LoadThumbnail(RenderWidgetHost* rwh, CALayer* layer2, const gfx::Size& s) ;
136 private:
137 friend class base::RefCountedThreadSafe<TabposeHelper>;
138 ~TabposeHelper() {}
139 void LoadThumbnailIO(RenderWidgetHost* rwh, CALayer* layer2, const gfx::Size& s, const gfx::Size& fullSize);
140
141 TabposeWindow* window_;
142 // ScopedRunnableMethodFactory<TabposeHelper> factory_;
143 };
144
145 void TabposeHelper::LoadThumbnail(RenderWidgetHost* rwh, CALayer* layer2, const gfx::Size& s) {
146 // rwh->set_painting_observer(NULL); // FIXME
147
148 NSSize nsFullSize = [[window_->browser_ tabContentArea] frame].size;
149 gfx::Size fullSize(NSSizeToCGSize(nsFullSize));
150
151 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
152 // FIXME: is the hop to the IO thread really necessary?
153 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
154 NewRunnableMethod(this, &TabposeHelper::LoadThumbnailIO, rwh, layer2, s, f ullSize));
155 }
156
157 void TabposeHelper::LoadThumbnailIO(RenderWidgetHost* rwh, CALayer* layer2, cons t gfx::Size& s, const gfx::Size& fullSize) {
158 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
159 ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
160
161 // FIXME: Internally, this allocs memory for both transport dib and then
162 // an SkBitmap (which _then_ needs to be converted to a CGImageRef).
163 // Reduce the amount of copying; possibly by sidestepping
164 // ThumbnailGenerator.
165 TabposeCallback* callback = new TabposeCallback(layer2);
166 window_->callbacks_.push_back(callback); // takes ownership
167
168 // |fullSize| is slightly larger (view bounds doesn't include scroll bars?)
169 // gfx::Size page_size(rwh->view()->GetViewBounds().size()); // Logical size t he renderer renders at
170 gfx::Size page_size(fullSize); // Logical size the renderer renders at
171
172 // This is a bit tricky: We really only need a bitmap at size |s|, but when
173 // the user clicks a thumbnail and it zooms large, this single thumbnail
174 // should have a pixel size close to the view bounds, so that the image doesnt
175 // get blurry. One possible idea would be to get all thumbs at size |s| and
176 // request the one currently below the mouse at full size, but then it might
177 // not be ready when the click happens. For now, KISS, and request everything
178 // at the full resolution.
179 // gfx::Size desired_size(s); // physical pixel size the image is rendered at
180 gfx::Size desired_size(page_size); // physical pixel size the image is render ed at
181 NSLog(@"scheduling snapshot request");
182
183 // FIXME: check that observer is currently NULL
184 // FIXME: this lets us receive straggling requests from an old tabpose window. leads to crashes.
185 rwh->set_painting_observer(generator);
186 generator->AskForSnapshot(rwh, /*prefer_backing_store=*/false,
187 NewCallback(callback, &TabposeCallback::DidReceiveBi tmap),
188 page_size, desired_size);
189 // FIXME: needs to be cancelled somehow if we die before renderer returns
190 }
191
29 @interface TabposeWindow (Private) 192 @interface TabposeWindow (Private)
30 - (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo; 193 - (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo
194 tempBWC:(BrowserWindowController*)bwc;
31 - (void)setUpLayers:(NSRect)bgLayerRect; 195 - (void)setUpLayers:(NSRect)bgLayerRect;
196 - (void)fadeAway:(BOOL)slomo;
32 @end 197 @end
33 198
34 @implementation TabposeWindow 199 @implementation TabposeWindow
35 200
36 + (id)openTabposeFor:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo { 201 + (id)openTabposeFor:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo
202 tempBWC:(BrowserWindowController*)bwc {
37 // Releases itself when closed. 203 // Releases itself when closed.
38 return [[TabposeWindow alloc] initForWindow:parent rect:rect slomo:slomo]; 204 return [[TabposeWindow alloc] initForWindow:parent rect:rect slomo:slomo tempB WC:bwc];
39 } 205 }
40 206
41 - (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo { 207 - (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo
208 tempBWC:(BrowserWindowController*)bwc {
42 NSRect frame = [parent frame]; 209 NSRect frame = [parent frame];
43 if ((self = [super initWithContentRect:frame 210 if ((self = [super initWithContentRect:frame
44 styleMask:NSBorderlessWindowMask 211 styleMask:NSBorderlessWindowMask
45 backing:NSBackingStoreBuffered 212 backing:NSBackingStoreBuffered
46 defer:NO])) { 213 defer:NO])) {
47 [self setReleasedWhenClosed:YES]; 214 [self setReleasedWhenClosed:YES];
48 [self setOpaque:NO]; 215 [self setOpaque:NO];
49 [self setBackgroundColor:[NSColor clearColor]]; 216 [self setBackgroundColor:[NSColor clearColor]];
50 [self setUpLayers:rect];
51 [parent addChildWindow:self ordered:NSWindowAbove]; 217 [parent addChildWindow:self ordered:NSWindowAbove];
52 [self makeKeyAndOrderFront:self]; 218 [self makeKeyAndOrderFront:self];
219
220 //NSImage* img = [NSImage imageNamed:@"contents1"];
221
222 // [self makeFirstResponder:self];
223
224 helper_ = new TabposeHelper(self);
225
226 state_ = kFadingIn;
227
228 browser_ = bwc;
229
230 NSView* contentArea = [browser_ tabContentArea] ; // FIXME
231 NSRect areaFrame = [contentArea frame];
232
233 [self setUpLayers:rect];
234
235 // Configure hand cursor
236 NSTrackingArea* trackingArea = [[NSTrackingArea alloc]
237 initWithRect:[[self contentView] frame]
238 options:NSTrackingCursorUpdate|NSTrackingActiveInKeyWindow
239 owner:self
240 userInfo:nil];
241 [[self contentView] addTrackingArea:[trackingArea autorelease]];
242
243 [self disableCursorRects];
244 if (NSPointInRect([NSEvent mouseLocation], [self frame]))
245 [[NSCursor pointingHandCursor] set];
246
247 // Needs to be called after -disableCursorRects.
248 [self setAcceptsMouseMovedEvents:YES];
249
250
251 // set up perspective
252 CATransform3D t = CATransform3DIdentity;
253 t.m34 = 1.0 / 1850;
254 bgLayer_.sublayerTransform = t;
255
256 #if 0
257 // Animate in.
258 // FIXME: probably want to use a CABasicAnimation instead
259 CATransition* animation = [CATransition animation];
260 //animation.type = kCATransitionPush;
261 //animation.type = kCATransitionMoveIn;
262 //animation.type = kCATransitionFade;
263 animation.type = kCATransitionReveal;
264 //animation.subtype = kCATransitionFromTop;
265 //animation.delegate = self;
266 animation.duration = 1.f * (slomo ? 4 : 1); // half for in, half for out
267 //[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMe diaTimingFunctionEaseInEaseOut]];
268 [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMedi aTimingFunctionEaseOut]];
269 [bgLayer_ addAnimation:animation forKey:nil];
270 #endif
271
272 // Count tabs.
273 // Browser* browser = browserController->browser_.get();
274 TabStripController* tabStripController = browser_->tabStripController_.get() ;
275 TabStripModel* tabStripModel = tabStripController->tabStripModel_;
276 NSArray* arrays = tabStripController->tabArray_.get();
277 NSSet* closing = tabStripController->closingControllers_.get();
278
279 selectedLayer_ = nil;
280 initiallySelectedIndex_ = selectedIndex_ = tabStripModel->selected_index();
281
282
283 int n = [arrays count] - [closing count];
284
285 // We want to have the small rects have the same aspect ratio a as a full
286 // tab. Let w, h be the size of a small rect, and w_c, h_c the size of the
287 // container. dx, dy are the distances between small rects in x, y direction .
288
289 // Geometry yields:
290 // w_c = nx * (w + dx) - dx <=> w = (w_c + d_x) / nx - d_x
291 // h_c = ny * (h + dy) - dy <=> h = (h_c + d_y) / ny - d_t
292 // Plugging this into
293 // a := tab_width / tab_height = w / h
294 // yields
295 // a = ((w_c - (nx - 1)*d_x)*ny) / (nx*(h_c - (ny - 1)*d_y))
296 // Plugging in nx = n/ny and pen and paper (or wolfram alpha:
297 // http://www.wolframalpha.com/input/?i=(-sqrt((d+n-a+f+n)^2-4+(a+f%2Ba+h)+( -d+n-n+w))%2Ba+f+n-d+n)/(2+a+(f%2Bh)) , (solution for nx)
298 // http://www.wolframalpha.com/input/?i=+(-sqrt((a+f+n-d+n)^2-4+(d%2Bw)+(-a+ f+n-a+h+n))-a+f+n%2Bd+n)/(2+(d%2Bw)) , (solution for ny)
299 // ) gives us nx and ny (but the wrong root -- s/-sqrt(FOO)/sqrt(FOO)/.
300
301 int row = 0, col = 0, i = 0;
302
303 CGFloat a = NSWidth([contentArea frame]) / NSHeight([contentArea frame]);
304
305 // FIXME: need to audit everything to check where i want rects with and with out bookmarks bar
306 // (right now, detached bookmark bar screws this up a bit)
307 int kOffsetTop = 30 + NSHeight([[browser_ window] frame]) - NSHeight([[brows er_ tabContentArea] frame]);
308 // if (browser_->bookmarkBarController_.get()->visualState_ == bookmarks::kDe tachedState) // FIXME: check for NULL?
309 // kOffsetTop -= NSHeight([[browser_->bookmarkBarController_ view] frame]);
310 int kOffsetLeft = 30;
311 int kOffsetRight = 30;
312 int kOffsetBottom = 30;
313 int kPaddingX = 15;
314 int kPaddingY = 10;
315
316 int extraOffsetX = 0;
317 int extraOffsetY = 0;
318 double w_c = NSWidth(frame) - kOffsetLeft - kOffsetRight;
319 double h_c = NSHeight(frame) - kOffsetTop - kOffsetBottom;
320 dx = kPaddingX;
321 dy = kPaddingY;
322 double fny = (sqrt(pow(n*(a*dy - dx), 2) + 4*n*a*(dx + w_c)*(dy + h_c)) - n* (a*dy - dx)) / (2*(dx + w_c));
323 ny = int(roundf(fny));
324 nx = int(ceilf(n / float(ny)));
325 last_nx = n - nx * (ny - 1);
326 w = floor((w_c + dx)/float(nx) - dx);
327 h = floor((h_c + dy)/float(ny) - dy);
328 if (a > w/float(h)) {
329 h = w / a;
330 extraOffsetY = (h_c - ((h + dy)*ny - dy))/2;
331 } else {
332 w = h * a;
333 extraOffsetX = (w_c - ((w + dx)*nx - dx))/2;
334 }
335
336 NSMutableArray* allLayers = [[NSMutableArray alloc] initWithCapacity:n];
337 allLayers_.reset(allLayers);
338 // for (TabController* tab in arrays) {
339 for (int ci = 0; ci < n; ++ci) {
340 #if 0
341 if ([closing containsObject:tab])
342 continue;
343
344 NSView* tabView = [tab view];
345
346 CALayer* layer = [CALayer layer];
347 layer.backgroundColor = blue;
348 layer.frame = NSRectToCGRect([[self contentView] convertRect:[tabView boun ds] fromView:tabView]);
349 #endif
350 #if 0
351 // Get tab image. FIXME: on bg thread?
352 #if 0
353 // XXX: Doesn't work?!
354 NSBitmapImageRep* imageRep =
355 [tabView bitmapImageRepForCachingDisplayInRect:[tabView bounds]];
356 if ([imageRep bitmapData])
357 bzero([imageRep bitmapData],
358 [imageRep bytesPerRow] * [imageRep pixelsHigh]);
359 [tabView cacheDisplayInRect:[tabView bounds] toBitmapImageRep:imageRep];
360 CGImageRef image = CGImageCreateCopy([imageRep CGImage]);
361 layer.contents = (id)image;
362 #elif 0
363 [tabView lockFocus];
364 NSBitmapImageRep* imageRep =
365 [[[NSBitmapImageRep alloc] initWithFocusedViewRect:[tabView bounds]] a utorelease];
366 [tabView unlockFocus];
367 CGImageRef image = CGImageCreateCopy([imageRep CGImage]);
368 layer.contents = (id)image;
369 #else
370 NSImage* nsi = [NSImage imageNamed:@"NSUserGroup"];
371 layer.contents = nsi;
372 #endif
373 // CFRelease(image);
374 // layer.contents = imageRep;
375
376 // NSImage *image = [[[NSImage alloc] initWithSize:[imageRep size]] autorel ease];
377 // [image addRepresentation:imageRep];
378 // layer.contents = image;
379 #endif
380
381 // [rootLayer addSublayer:layer];
382
383 CALayer* layer2;
384 // FIXME: on bg thread; also call the other method; ; also do
385 // CGLayer->CGImage conversion directly without going through skia, etc.
386 TabContents* contents = tabStripModel->GetTabContentsAt(i);
387 DCHECK(contents);
388 RenderViewHost* rvh = contents->render_view_host();
389 RenderWidgetHost* rwh = rvh;
390 DCHECK(rwh);
391
392 BackingStoreMac* backing_store = (BackingStoreMac*)rwh->GetBackingStore(fa lse);
393 if (backing_store) {
394 // FIXME: looks like the backing store can go away while we're running : -/
395 layer2 = [[[BackingStoreLayer alloc] initWithBackingStore:backing_store] autorelease];
396 [layer2 setNeedsDisplay];
397 } else {
398 layer2 = [CALayer layer];
399 // Set placeholder
400 #if 0
401 // Icon as placeholder (FIXME: load only once)
402 int m = MIN(w, h);
403 // Can't use nsimage_cache::ImageNamed(), because that uses
404 // initWithContentsOfFile, which creates a cached representation at
405 // 16x16 and then throws away the vector data.
406 NSString* path = [mac_util::MainAppBundle() pathForImageResource:@"nav.p df"];
407 NSPDFImageRep* pdfRep = [NSPDFImageRep imageRepWithContentsOfFile:path];
408 NSImage* pdfImage = [[[NSImage alloc] initWithSize:NSMakeSize(m, m)] aut orelease];
409 [pdfImage addRepresentation:pdfRep];
410 // FIXME: if we don't leak this, the image rep frees its cgimage soon
411 // and the CALayer crashes when it wants to draw.
412 NSBitmapImageRep* bitmap = [[NSBitmapImageRep imageRepWithData:[pdfImage TIFFRepresentation]] retain]; // XXX
413 layer2.contents = (id)[bitmap CGImage];
414 #else
415 // background color as placeholder
416 layer2.backgroundColor = CGColorGetConstantColor(kCGColorWhite);
417 #endif
418 helper_->LoadThumbnail(rwh, layer2, gfx::Size(w, h));
419 }
420 layer2.contentsGravity = kCAGravityResizeAspect; // for placeholder
421
422 // layer2.backgroundColor = blue;
423 int x = kOffsetLeft + col*(w + kPaddingX) + extraOffsetX;
424 if (row == ny - 1) {
425 // last row
426 x += (nx - last_nx) * (w + kPaddingX) / 2;
427 }
428 int y = kOffsetTop + row*(h + kPaddingY) + extraOffsetY;
429 layer2.anchorPoint = CGPointMake(0.5, 0.5);
430
431 // NSBitmapImageRep* rep = (NSBitmapImageRep*)[img bestRepresentationForDev ice:nil];
432 // layer2.contents = (id)[rep CGImage];
433 // layer2.contentsGravity = kCAGravityResizeAspect;
434
435 // layer2.shadowOpacity = 0.5; // FIXME: Slows things down, even if disabl ed before animation runs
436 layer2.shadowRadius = 10;
437 layer2.shadowOffset = CGSizeMake(0, -10);
438 // layer2.borderColor = blue;
439
440
441 if (i == selectedIndex_) {
442 // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html
443 // Prepare the animation from the old size to the new size
444 CGRect oldBounds = NSRectToCGRect([contentArea frame]);
445 CGRect newBounds = oldBounds;
446 newBounds.size = CGSizeMake(w, h);
447 CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"b ounds"];
448 animation.fromValue = [NSValue valueWithRect:NSRectFromCGRect(oldBounds) ];
449 animation.toValue = [NSValue valueWithRect:NSRectFromCGRect(newBounds)];
450 animation.duration = .25f * (slomo ? 4 : 1);
451 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMe diaTimingFunctionEaseOut];
452
453 // Update the layer's bounds so the layer doesn't snap back when the ani mation completes.
454 layer2.bounds = newBounds;
455
456 // Add the animation, overriding the implicit animation.
457 [layer2 addAnimation:animation forKey:@"bounds"];
458
459 // Prepare the animation from the current position to the new position
460 NSPoint t = areaFrame.origin;
461
462 CGPoint opoint = CGPointMake(t.x + NSWidth(areaFrame)/2, t.y + NSHeight( areaFrame)/2);
463 CGPoint point = CGPointMake(x + w/2, NSHeight(frame) - y - h + h/2);
464 animation = [CABasicAnimation animationWithKeyPath:@"position"];
465 animation.fromValue = [NSValue valueWithPoint:NSPointFromCGPoint(opoint) ];
466 animation.toValue = [NSValue valueWithPoint:NSPointFromCGPoint(point)];
467 animation.duration = .25f * (slomo ? 4 : 1);
468 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMe diaTimingFunctionEaseOut];
469
470 // Update the layer's position so that the layer doesn't snap back when the animation completes.
471 layer2.position = point;
472
473 // Add the animation, overriding the implicit animation.
474 [layer2 addAnimation:animation forKey:@"position"];
475
476 [rootLayer_ insertSublayer:layer2 above:bgLayer_];
477 selectedLayer_ = layer2;
478
479 // selectedLayer_.borderWidth = 5;
480 // [selectedLayer_ setValue:[NSNumber numberWithFloat:S] forKey:@"transfo rm.scale"];
481 [CATransaction begin];
482 [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActio ns];
483 selectedLayer_.transform = CATransform3DMakeScale(S, S, 1);
484 [CATransaction commit];
485 } else {
486 #if 0
487 CABasicAnimation* zoom = [CABasicAnimation animationWithKeyPath:@"transfo rm.translation.z"];
488 [layer2 setValue:[NSNumber numberWithFloat:0] forKey:@"transform.translat ion.z"];
489 zoom.fromValue = [NSNumber numberWithFloat:1000];
490 zoom.toValue = [NSNumber numberWithFloat:0];
491 zoom.duration = .25f * (slomo ? 4 : 1);
492 zoom.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTim ingFunctionLinear];
493 [layer2 addAnimation:zoom forKey:@"transform"];
494 #else
495 int sel_col = selectedIndex_ % nx;
496 int sel_row = selectedIndex_ / nx;
497 CGFloat r = NSWidth([contentArea frame]) / float(w);
498 int ox = (NSWidth([contentArea frame]) + dx*r) * (col - sel_col);
499 if (row == ny - 1) {
500 // last row
501 ox += (nx - last_nx) * (NSWidth([contentArea frame]) + dx*r) / 2;
502 }
503 if (sel_row == ny - 1) {
504 // last row
505 ox -= (nx - last_nx) * (NSWidth([contentArea frame]) + dx*r) / 2;
506 }
507 int oy = (NSHeight([contentArea frame]) + dy*r) * (row - sel_row);
508
509 CGRect oldBounds = NSRectToCGRect([contentArea frame]);
510 CGRect newBounds = oldBounds;
511 newBounds.size = CGSizeMake(w, h);
512 CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"bo unds"];
513 animation.fromValue = [NSValue valueWithRect:NSRectFromCGRect(oldBounds)] ;
514 animation.toValue = [NSValue valueWithRect:NSRectFromCGRect(newBounds)];
515 animation.duration = .25f * (slomo ? 4 : 1);
516 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMed iaTimingFunctionEaseOut];
517
518 // Update the layer's bounds so the layer doesn't snap back when the anim ation completes.
519 layer2.bounds = newBounds;
520
521 // Add the animation, overriding the implicit animation.
522 [layer2 addAnimation:animation forKey:@"bounds"];
523
524 // Prepare the animation from the current position to the new position
525 NSPoint t = [contentArea frame].origin;
526 CGPoint opoint = CGPointMake(ox + t.x + NSWidth(areaFrame)/2, /*NSHeight( frame) - h*/- oy + t.y + NSHeight(areaFrame)/2);
527
528 CGPoint point = CGPointMake(x + w/2, NSHeight(frame) - y - h + h/2);
529 animation = [CABasicAnimation animationWithKeyPath:@"position"];
530 animation.fromValue = [NSValue valueWithPoint:NSPointFromCGPoint(opoint)] ;
531 animation.toValue = [NSValue valueWithPoint:NSPointFromCGPoint(point)];
532 animation.duration = .25f * (slomo ? 4 : 1);
533 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMed iaTimingFunctionEaseOut];
534
535 // Update the layer's position so that the layer doesn't snap back when t he animation completes.
536 layer2.position = point;
537
538 // Add the animation, overriding the implicit animation.
539 [layer2 addAnimation:animation forKey:@"position"];
540 #endif
541
542 [bgLayer_ addSublayer:layer2];
543 }
544 [allLayers addObject:layer2];
545
546
547 ++col;
548 if (col == nx) {
549 col = 0;
550 ++row;
551 }
552 ++i;
553 }
53 } 554 }
54 return self; 555 return self;
55 } 556 }
56 557
57 - (void)setUpLayers:(NSRect)bgLayerRect { 558 - (void)setUpLayers:(NSRect)bgLayerRect {
58 // Root layer -- covers whole window. 559 // Root layer -- covers whole window.
59 rootLayer_ = [CALayer layer]; 560 rootLayer_ = [CALayer layer];
60 [[self contentView] setLayer:rootLayer_]; 561 [[self contentView] setLayer:rootLayer_];
61 [[self contentView] setWantsLayer:YES]; 562 [[self contentView] setWantsLayer:YES];
62 563
(...skipping 18 matching lines...) Expand all
81 582
82 - (BOOL)canBecomeKeyWindow { 583 - (BOOL)canBecomeKeyWindow {
83 return YES; 584 return YES;
84 } 585 }
85 586
86 - (void)keyDown:(NSEvent*)event { 587 - (void)keyDown:(NSEvent*)event {
87 // Overridden to prevent beeps. 588 // Overridden to prevent beeps.
88 } 589 }
89 590
90 - (void)keyUp:(NSEvent*)event { 591 - (void)keyUp:(NSEvent*)event {
592 if (state_ == kFadingOut)
593 return;
594
91 NSString* characters = [event characters]; 595 NSString* characters = [event characters];
92 if ([characters length] < 1) 596 if ([characters length] < 1)
93 return; 597 return;
94 598
95 unichar character = [characters characterAtIndex:0]; 599 unichar character = [characters characterAtIndex:0];
96 switch (character) { 600 switch (character) {
97 case NSEnterCharacter: 601 case NSEnterCharacter:
98 case NSNewlineCharacter: 602 case NSNewlineCharacter:
99 case NSCarriageReturnCharacter: 603 case NSCarriageReturnCharacter:
100 case ' ': 604 case ' ':
605 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
606 break;
101 case '\e': // Escape 607 case '\e': // Escape
102 [self close]; 608 selectedIndex_ = initiallySelectedIndex_;
609 selectedLayer_ = [allLayers_ objectAtIndex:selectedIndex_];
610 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
103 break; 611 break;
104 } 612 }
105 } 613 }
106 614
615 - (void)mouseMoved:(NSEvent*)event {
616 int i = 0;
617 CALayer* newSelectedLayer = nil;
618 int newIndex = -1;
619 CGPoint p = NSPointToCGPoint([event locationInWindow]);
620 for (CALayer* layer in allLayers_.get()) {
621 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_];
622 if ([layer containsPoint:lp]) {
623 newSelectedLayer = layer;
624 newIndex = i;
625 }
626 ++i;
627 }
628
629 if (newSelectedLayer && newSelectedLayer != selectedLayer_) {
630 CALayer* oldSelectedLayer = selectedLayer_;
631
632 [CATransaction begin];
633 [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActio ns];
634 if (selectedLayer_)
635 [bgLayer_ addSublayer:selectedLayer_];
636 selectedLayer_ = newSelectedLayer;
637 [selectedLayer_ removeFromSuperlayer];
638 [rootLayer_ insertSublayer:selectedLayer_ above:bgLayer_];
639 selectedIndex_ = newIndex;
640 [CATransaction commit];
641
642 if (oldSelectedLayer)
643 oldSelectedLayer.transform = CATransform3DIdentity;
644 if (newSelectedLayer)
645 newSelectedLayer.transform = CATransform3DMakeScale(S, S, 1);
646 }
647 }
648
649 // FIXME: do this on long hover, too
107 - (void)mouseDown:(NSEvent*)event { 650 - (void)mouseDown:(NSEvent*)event {
108 [self close]; 651 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
109 } 652 }
110 653
111 - (void)swipeWithEvent:(NSEvent*)event { 654 - (void)swipeWithEvent:(NSEvent*)event {
112 if ([event deltaY] > 0.5) // Swipe up 655 if ([event deltaY] > 0.5) // Swipe up
113 [self close]; 656 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0];
114 } 657 }
115 658
116 - (void)close { 659 - (void)close {
117 // Prevent parent window from disappearing. 660 // Prevent parent window from disappearing.
118 [[self parentWindow] removeChildWindow:self]; 661 [[self parentWindow] removeChildWindow:self];
119 [super close]; 662 [super close];
120 } 663 }
121 664
122 - (void)commandDispatch:(id)sender { 665 - (void)commandDispatch:(id)sender {
123 // Without this, -validateUserInterfaceItem: is not called. 666 // Without this, -validateUserInterfaceItem: is not called.
124 } 667 }
125 668
126 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { 669 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
127 // Disable all browser-related menu items. 670 // Disable all browser-related menu items.
128 return NO; 671 return NO;
129 } 672 }
130 673
674
675 - (void)cursorUpdate:(NSEvent*)event {
676 [[NSCursor pointingHandCursor] set];
677 }
678
679 - (void)fadeAway:(BOOL)slomo {
680 if (state_ == kFadingOut)
681 return;
682
683 [[NSCursor arrowCursor] set];
684
685 state_ = kFadingOut;
686 [self setAcceptsMouseMovedEvents:NO];
687
688 // Clean out observers, so that eventual pending thumbnail requests don't
689 // resolve against dead objects.
690 TabStripController* tabStripController = browser_->tabStripController_.get();
691 TabStripModel* tabStripModel = tabStripController->tabStripModel_;
692 for (int i = 0; i < tabStripModel->count(); ++i) {
693 TabContents* contents = tabStripModel->GetTabContentsAt(i);
694 contents->render_view_host()->set_painting_observer(NULL);
695 }
696
697 // Select chosen tab (FIXME: don't on ESC)
698 if (selectedIndex_ >= 0)
699 tabStripModel->SelectTabContentsAt(selectedIndex_, /*user_gesture=*/true);
700
701 #if 1
702 // FIXME: this is only here so that we get a notification after 4 / 1 seconds.
703 // Do that in a simpler way.
704 CABasicAnimation* fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
705 bgLayer_.opacity = 0.99; // make it stick, change model value
706 fade.fromValue = [NSNumber numberWithFloat:1];
707 fade.toValue = [NSNumber numberWithFloat:0.99];
708 fade.duration = .5f * (slomo ? 4 : 1);
709 fade.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFu nctionEaseOut];
710 fade.delegate = self;
711 #endif
712
713 if (selectedIndex_ >= 0) {
714 CALayer* layer = selectedLayer_; //[[bgLayer_ sublayers] objectAtIndex:selec tedIndex_];
715
716 [CATransaction begin];
717 [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActio ns];
718 // layer.contentsGravity = kCAGravityResize;
719 // layer.opaque = YES;
720 // layer.compositingFilter = [CIFilter filterWithName:@"CISourceInCompositing "];
721 selectedLayer_.borderWidth = 0;
722
723 // Animating large shadows is slow -- don't.
724 layer.shadowOpacity = 0;
725 layer.transform = CATransform3DIdentity;
726
727 [layer removeFromSuperlayer];
728 // [rootLayer_ insertSublayer:layer above:bgLayer_];
729 [bgLayer_ addSublayer:layer]; // move on top of all other layers
730
731 [CATransaction commit];
732
733
734
735 [CATransaction begin];
736 if (slomo) {
737 CGFloat f = [[CATransaction valueForKey:kCATransactionAnimationDuration] f loatValue];
738 f = 0.5; // the above returns 0 :-P
739 [CATransaction setValue:[NSNumber numberWithFloat:4*f] forKey:kCATransacti onAnimationDuration];
740 }
741 layer.frame = NSRectToCGRect([[browser_ tabContentArea] frame]);
742 if ([layer isKindOfClass:[BackingStoreLayer class]])
743 [layer setNeedsDisplay]; // Redraw layer at big resolution, so that zoom- in isn't blocky.
744 // layer.opacity = 0;
745 [CATransaction commit];
746 }
747
748 int i = 0, col = 0, row = 0;
749 for (CALayer* layer in allLayers_.get()) {
750 // DCHECK_NE(layer, selectedLayer_);
751 // if (layer == selectedLayer_) continue;
752 if (i == selectedIndex_) {
753 ++i;
754 ++col;
755 if (col == nx) {
756 col = 0;
757 ++row;
758 }
759 continue;
760 }
761
762 // Animating large shadows is slow -- don't.
763 [CATransaction begin];
764 [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActio ns];
765 layer.shadowOpacity = 0;
766 [CATransaction commit];
767
768 #if 0
769 CABasicAnimation* zoom = [CABasicAnimation animationWithKeyPath:@"transform. translation.z"];
770 // [layer setValue:[NSNumber numberWithFloat:1000] forKey:@"transform.transla tion.z"];
771 zoom.fromValue = [NSNumber numberWithFloat:0];
772 zoom.toValue = [NSNumber numberWithFloat:-1000]; // negative Z to keep them behind the selected layer
773 zoom.duration = .5f * (slomo ? 4 : 1);
774 zoom.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTiming FunctionLinear];
775 [layer addAnimation:zoom forKey:@"transform"];
776 #else
777 int sel_col = selectedIndex_ % nx;
778 int sel_row = selectedIndex_ / nx;
779 NSLog(@"%d %d %d %d %d", col, row, sel_col, sel_row, selectedIndex_);
780 CGFloat r = NSWidth([[browser_ tabContentArea] frame]) / float(w);
781 int ox = (NSWidth([[browser_ tabContentArea] frame]) + dx*r) * (col - sel_c ol);
782 if (row == ny - 1) {
783 // last row
784 ox += (nx - last_nx) * (NSWidth([[browser_ tabContentArea] frame]) + dx*r ) / 2;
785 }
786 if (sel_row == ny - 1) {
787 // last row
788 ox -= (nx - last_nx) * (NSWidth([[browser_ tabContentArea] frame]) + dx*r ) / 2;
789 }
790 int oy = (NSHeight([[browser_ tabContentArea] frame]) + dy*r) * (row - sel_ row);
791
792 CGRect newFrame = NSRectToCGRect([[browser_ tabContentArea] frame]);
793 newFrame.origin.x += ox;
794 newFrame.origin.y -= oy;
795
796 [CATransaction begin];
797 if (slomo) {
798 CGFloat f = 0.5;
799 [CATransaction setValue:[NSNumber numberWithFloat:4*f] forKey:kCATransact ionAnimationDuration];
800 }
801 layer.frame = newFrame;
802 [CATransaction commit];
803
804 ++col;
805 if (col == nx) {
806 col = 0;
807 ++row;
808 }
809 #endif
810 ++i;
811 }
812
813 [bgLayer_ addAnimation:fade forKey:@"opacity"]; // override any implicit anim ation
814 }
815
816 - (BOOL)windowShouldClose:(id)window {
817 [self fadeAway:NO];
818 return NO;
819 }
820
821 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag {
822 [self close];
823 }
824
131 @end 825 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/tabpose_window.h ('k') | chrome/browser/cocoa/tabpose_window_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698