diff options
-rw-r--r-- | chrome/browser/browser.cc | 15 | ||||
-rw-r--r-- | chrome/browser/browser.h | 1 | ||||
-rw-r--r-- | chrome/browser/browser_window.h | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.h | 1 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.mm | 4 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 19 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller_private.mm | 1 | ||||
-rw-r--r-- | chrome/browser/cocoa/tabpose_window.h | 36 | ||||
-rw-r--r-- | chrome/browser/cocoa/tabpose_window.mm | 131 | ||||
-rw-r--r-- | chrome/browser/cocoa/tabpose_window_unittest.mm | 35 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/test/test_browser_window.h | 1 |
14 files changed, 254 insertions, 1 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 13f6b54..cdd32ae 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -1340,6 +1340,20 @@ void Browser::SelectPreviousTab() { tabstrip_model_.SelectPreviousTab(); } +void Browser::OpenTabpose() { +#if defined(OS_MACOSX) + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExposeForTabs)) { + return; + } + + UserMetrics::RecordAction(UserMetricsAction("OpenTabpose"), profile_); + window()->OpenTabpose(); +#else + NOTREACHED(); +#endif +} + void Browser::MoveTabNext() { UserMetrics::RecordAction(UserMetricsAction("MoveTabNext"), profile_); tabstrip_model_.MoveTabNext(); @@ -1978,6 +1992,7 @@ void Browser::ExecuteCommandWithDisposition( case IDC_CLOSE_TAB: CloseTab(); break; case IDC_SELECT_NEXT_TAB: SelectNextTab(); break; case IDC_SELECT_PREVIOUS_TAB: SelectPreviousTab(); break; + case IDC_TABPOSE: OpenTabpose(); break; case IDC_MOVE_TAB_NEXT: MoveTabNext(); break; case IDC_MOVE_TAB_PREVIOUS: MoveTabPrevious(); break; case IDC_SELECT_TAB_0: diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index 7938bc1..87456fb 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -433,6 +433,7 @@ class Browser : public TabStripModelDelegate, void CloseTab(); void SelectNextTab(); void SelectPreviousTab(); + void OpenTabpose(); void MoveTabNext(); void MoveTabPrevious(); void SelectNumberedTab(int index); diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h index b02ffea..444796e 100644 --- a/chrome/browser/browser_window.h +++ b/chrome/browser/browser_window.h @@ -310,6 +310,11 @@ class BrowserWindow { // Switches between available tabstrip display modes. virtual void ToggleTabStripMode() = 0; +#if defined(OS_MACOSX) + // Opens the tabpose view. + virtual void OpenTabpose() = 0; +#endif + // Construct a BrowserWindow implementation for the specified |browser|. static BrowserWindow* CreateBrowserWindow(Browser* browser); diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index 47e32b2..4559567 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -106,6 +106,7 @@ class BrowserWindowCocoa : public BrowserWindow, virtual void Copy(); virtual void Paste(); virtual void ToggleTabStripMode(); + virtual void OpenTabpose(); // Overridden from NotificationObserver virtual void Observe(NotificationType type, diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 8b16348..2b12cda 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -553,6 +553,10 @@ void BrowserWindowCocoa::ToggleTabStripMode() { [controller_ toggleTabStripDisplayMode]; } +void BrowserWindowCocoa::OpenTabpose() { + [controller_ toggleTabStripDisplayMode]; +} + void BrowserWindowCocoa::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index 816feb2..274e23b 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -337,6 +337,9 @@ class TabStripModelObserverBridge; // Returns YES if any of the views in the floating bar currently has focus. - (BOOL)floatingBarHasFocus; +// Opens the tabpose window. +- (void)openTabpose; + @end // @interface BrowserWindowController(Fullscreen) diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 61741e99..d31659b0 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -44,6 +44,7 @@ #import "chrome/browser/cocoa/tab_strip_controller.h" #import "chrome/browser/cocoa/tab_strip_view.h" #import "chrome/browser/cocoa/tab_view.h" +#import "chrome/browser/cocoa/tabpose_window.h" #import "chrome/browser/cocoa/toolbar_controller.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/sync/profile_sync_service.h" @@ -1473,6 +1474,7 @@ // TODO(pinkerton): figure out page-up, http://crbug.com/16305 } else if ([event deltaY] < -0.5) { // TODO(pinkerton): figure out page-down, http://crbug.com/16305 + browser_->ExecuteCommand(IDC_TABPOSE); } // Ensure the command is valid first (ExecuteCommand() won't do that) and @@ -1841,6 +1843,23 @@ willAnimateFromState:(bookmarks::VisualState)oldState return [focused isKindOfClass:[AutocompleteTextFieldEditor class]]; } +- (void)openTabpose { + NSUInteger modifierFlags = [[NSApp currentEvent] modifierFlags]; + BOOL slomo = (modifierFlags & NSShiftKeyMask) != 0; + + // Cover info bars, inspector window, and detached bookmark bar on NTP. + // Do not cover download shelf. + NSRect activeArea = [[self tabContentArea] frame]; + activeArea.size.height += + NSHeight([[infoBarContainerController_ view] frame]); + if ([self isBookmarkBarVisible] && [self placeBookmarkBarBelowInfoBar]) { + NSView* bookmarkBarView = [bookmarkBarController_ view]; + activeArea.size.height += NSHeight([bookmarkBarView frame]); + } + + [TabposeWindow openTabposeFor:[self window] rect:activeArea slomo:slomo]; +} + @end // @implementation BrowserWindowController(Fullscreen) diff --git a/chrome/browser/cocoa/browser_window_controller_private.mm b/chrome/browser/cocoa/browser_window_controller_private.mm index 9f14c2e..21d6f2b 100644 --- a/chrome/browser/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/cocoa/browser_window_controller_private.mm @@ -26,7 +26,6 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/common/pref_names.h" - namespace { // Space between the incognito badge and the right edge of the window. diff --git a/chrome/browser/cocoa/tabpose_window.h b/chrome/browser/cocoa/tabpose_window.h new file mode 100644 index 0000000..0efb90c --- /dev/null +++ b/chrome/browser/cocoa/tabpose_window.h @@ -0,0 +1,36 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_TABPOSE_WINDOW_H_ +#define CHROME_BROWSER_COCOA_TABPOSE_WINDOW_H_ +#pragma once + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_cftyperef.h" + +// A TabposeWindow shows an overview of open tabs and lets the user select a new +// active tab. The window blocks clicks on the tab strip and the download +// shelf. Every open browser window has its own overlay, and they are +// independent of each other. +@interface TabposeWindow : NSWindow { + @private + // The root layer added to the content view. Covers the whole window. + CALayer* rootLayer_; // weak + + // The layer showing the background layer. Covers the whole visible area. + CALayer* bgLayer_; // weak + + scoped_cftyperef<CGColorRef> gray_; +} + +// Shows a TabposeWindow on top of |parent|, with |rect| being the active area. +// If |slomo| is YES, then the appearance animation is shown in slow motion. +// The window blocks all keyboard and mouse events and releases itself when +// closed. ++ (id)openTabposeFor:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo; +@end + +#endif // CHROME_BROWSER_COCOA_TABPOSE_WINDOW_H_ + diff --git a/chrome/browser/cocoa/tabpose_window.mm b/chrome/browser/cocoa/tabpose_window.mm new file mode 100644 index 0000000..c69c5c1 --- /dev/null +++ b/chrome/browser/cocoa/tabpose_window.mm @@ -0,0 +1,131 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/tabpose_window.h" + +#import <QuartzCore/QuartzCore.h> + +const int kTopGradientHeight = 15; + +// CAGradientLayer is 10.6-only -- roll our own. +@interface DarkGradientLayer : CALayer +- (void)drawInContext:(CGContextRef)context; +@end + +@implementation DarkGradientLayer +- (void)drawInContext:(CGContextRef)context { + scoped_cftyperef<CGColorSpaceRef> grayColorSpace( + CGColorSpaceCreateWithName(kCGColorSpaceGenericGray)); + CGFloat grays[] = { 0.277, 1.0, 0.39, 1.0 }; + CGFloat locations[] = { 0, 1 }; + scoped_cftyperef<CGGradientRef> gradient(CGGradientCreateWithColorComponents( + grayColorSpace.get(), grays, locations, arraysize(locations))); + CGPoint topLeft = CGPointMake(0.0, kTopGradientHeight); + CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0); +} +@end + +@interface TabposeWindow (Private) +- (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo; +- (void)setUpLayers:(NSRect)bgLayerRect; +@end + +@implementation TabposeWindow + ++ (id)openTabposeFor:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo { + // Releases itself when closed. + return [[TabposeWindow alloc] initForWindow:parent rect:rect slomo:slomo]; +} + +- (id)initForWindow:(NSWindow*)parent rect:(NSRect)rect slomo:(BOOL)slomo { + NSRect frame = [parent frame]; + if ((self = [super initWithContentRect:frame + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO])) { + [self setReleasedWhenClosed:YES]; + [self setOpaque:NO]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setUpLayers:rect]; + [parent addChildWindow:self ordered:NSWindowAbove]; + [self makeKeyAndOrderFront:self]; + } + return self; +} + +- (void)setUpLayers:(NSRect)bgLayerRect { + // Root layer -- covers whole window. + rootLayer_ = [CALayer layer]; + [[self contentView] setLayer:rootLayer_]; + [[self contentView] setWantsLayer:YES]; + + // Background layer -- the visible part of the window. + gray_.reset(CGColorCreateGenericGray(0.39, 1.0)); + bgLayer_ = [CALayer layer]; + bgLayer_.backgroundColor = gray_; + bgLayer_.frame = NSRectToCGRect(bgLayerRect); + bgLayer_.masksToBounds = YES; + [rootLayer_ addSublayer:bgLayer_]; + + // Top gradient. + CALayer* gradientLayer = [DarkGradientLayer layer]; + gradientLayer.frame = CGRectMake( + 0, + NSHeight(bgLayerRect) - kTopGradientHeight, + NSWidth(bgLayerRect), + kTopGradientHeight); + [gradientLayer setNeedsDisplay]; // Draw once. + [bgLayer_ addSublayer:gradientLayer]; +} + +- (BOOL)canBecomeKeyWindow { + return YES; +} + +- (void)keyDown:(NSEvent*)event { + // Overridden to prevent beeps. +} + +- (void)keyUp:(NSEvent*)event { + NSString* characters = [event characters]; + if ([characters length] < 1) + return; + + unichar character = [characters characterAtIndex:0]; + switch (character) { + case NSEnterCharacter: + case NSNewlineCharacter: + case NSCarriageReturnCharacter: + case ' ': + case '\e': // Escape + [self close]; + break; + } +} + +- (void)mouseDown:(NSEvent*)event { + [self close]; +} + +- (void)swipeWithEvent:(NSEvent*)event { + if ([event deltaY] > 0.5) // Swipe up + [self close]; +} + +- (void)close { + // Prevent parent window from disappearing. + [[self parentWindow] removeChildWindow:self]; + [super close]; +} + +- (void)commandDispatch:(id)sender { + // Without this, -validateUserInterfaceItem: is not called. +} + +- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { + // Disable all browser-related menu items. + return NO; +} + +@end diff --git a/chrome/browser/cocoa/tabpose_window_unittest.mm b/chrome/browser/cocoa/tabpose_window_unittest.mm new file mode 100644 index 0000000..8f6f239 --- /dev/null +++ b/chrome/browser/cocoa/tabpose_window_unittest.mm @@ -0,0 +1,35 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/tabpose_window.h" + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" + +class TabposeWindowTest : public CocoaTest { + public: + BrowserTestHelper browser_helper_; +}; + +// Check that this doesn't leak. +TEST_F(TabposeWindowTest, TestShow) { + scoped_nsobject<NSWindow> parent([[NSWindow alloc] + initWithContentRect:NSMakeRect(100, 200, 300, 200) + styleMask:NSTitledWindowMask + backing:NSBackingStoreBuffered + defer:NO]); + [parent orderFront:nil]; + EXPECT_TRUE([parent isVisible]); + + base::ScopedNSAutoreleasePool pool; + TabposeWindow* window = + [TabposeWindow openTabposeFor:parent.get() + rect:NSMakeRect(10, 20, 50, 60) + slomo:NO]; + + // Should release the window. + [window mouseDown:nil]; +} diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 887fa5e..1b5ea58 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -999,6 +999,8 @@ 'browser/cocoa/tab_window_controller.mm', 'browser/cocoa/table_row_nsimage_cache.h', 'browser/cocoa/table_row_nsimage_cache.mm', + 'browser/cocoa/tabpose_window.h', + 'browser/cocoa/tabpose_window.mm', 'browser/cocoa/task_manager_mac.h', 'browser/cocoa/task_manager_mac.mm', 'browser/cocoa/themed_window.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 8ad0be2..0ffbb01 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -884,6 +884,7 @@ 'browser/cocoa/tab_view_unittest.mm', 'browser/cocoa/tab_view_picker_table_unittest.mm', 'browser/cocoa/table_row_nsimage_cache_unittest.mm', + 'browser/cocoa/tabpose_window_unittest.mm', 'browser/cocoa/task_manager_mac_unittest.mm', 'browser/cocoa/test_event_utils.h', 'browser/cocoa/test_event_utils.mm', diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index 4ac3d1c..5cfbd0b 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -103,6 +103,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void Copy() { } virtual void Paste() { } virtual void ToggleTabStripMode() {} + virtual void OpenTabpose() {} protected: virtual void DestroyBrowser() {} |