diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 18:32:35 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 18:32:35 +0000 |
commit | 91ac92017430d4e2620c90df4db22a8f0b13517b (patch) | |
tree | 6609159f6c2fa4542c0825d6e80fab31c2a0fbcd /chrome | |
parent | b977787a65182c58cbaea80d4cd30856740a4cde (diff) | |
download | chromium_src-91ac92017430d4e2620c90df4db22a8f0b13517b.zip chromium_src-91ac92017430d4e2620c90df4db22a8f0b13517b.tar.gz chromium_src-91ac92017430d4e2620c90df4db22a8f0b13517b.tar.bz2 |
Mac: Add tabpose window
The window doesn't have any contents yet, which makes its appearance look a bit janky for now.
BUG=50307
TEST=
* All the following happens only if --enable-expose-for-tabs is passed in, else all of it should be disabled.
* In a browser window, hit cmd-f10 or three-finger-swipe down. A grey overlay with a gradient at the top should appear.
* The overlay should cover tab contents, eventual info bars, the bookmarks bar if it's detached (but not the bookmarks bar if it's not detached), and eventual attached inspector windows. It should not cover the download shelf if it's open.
* The window should block clicks on the tab strip and the download shelf for now.
* The overlay should close on three-finger-swipe up, click, esc, enter, and space.
* Every open browser window should have its own overlay, and they should be independent of each other.
* If a browser window with an overlay window is active, most menu items should be greyed out, and all browser-related keyboard shortcuts should be disabled.
* In particular, hitting cmd-f10 twice should open only one overlay per browser window
* The overlay should have the correct size with a UI scale factor > 1
Review URL: http://codereview.chromium.org/2819070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54349 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-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() {} |