diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 10 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_browser_window.h | 17 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_browser_window.mm | 53 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_browser_window_unittest.mm | 59 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_event_processing_window.h | 32 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_event_processing_window.mm | 69 | ||||
-rw-r--r-- | chrome/browser/cocoa/chrome_event_processing_window_unittest.mm | 111 | ||||
-rw-r--r-- | chrome/browser/cocoa/fullscreen_window.h | 5 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 3 |
9 files changed, 233 insertions, 126 deletions
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 030384d..d80e9f8 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -932,6 +932,12 @@ willPositionSheet:(NSWindow*)sheet [content removeFromSuperview]; [fullscreen_window_ setContentView:content]; [self setWindow:fullscreen_window_.get()]; + [window_ setWindowController:nil]; + [window_ setDelegate:nil]; + // Required for proper event dispatch. + [fullscreen_window_ setWindowController:self]; + [fullscreen_window_ setDelegate:self]; + // Minimize our UI. This call triggers a relayout, so it needs to come // after we move the contentview to the new window. [self adjustUIForFullscreen:fullscreen]; @@ -947,6 +953,10 @@ willPositionSheet:(NSWindow*)sheet [content setAutoresizesSubviews:NO]; [content removeFromSuperview]; [window_ setContentView:content]; + [fullscreen_window_ setDelegate:nil]; + [fullscreen_window_ setWindowController:nil]; + [window_ setWindowController:self]; + [window_ setDelegate:self]; [self setWindow:window_.get()]; // This call triggers a relayout, so it needs to come after we move the // contentview to the new window. diff --git a/chrome/browser/cocoa/chrome_browser_window.h b/chrome/browser/cocoa/chrome_browser_window.h index f69978c..19a846f 100644 --- a/chrome/browser/cocoa/chrome_browser_window.h +++ b/chrome/browser/cocoa/chrome_browser_window.h @@ -8,6 +8,7 @@ #import <Cocoa/Cocoa.h> #include "base/scoped_nsobject.h" +#include "chrome/browser/cocoa/chrome_event_processing_window.h" // Offset from the top of the window frame to the top of the window controls // (zoom, close, miniaturize) for a window with a tabstrip. @@ -28,7 +29,7 @@ const NSInteger kChromeWindowButtonsInterButtonSpacing = 7; // We need to override NSWindow with our own class since we need access to all // unhandled keyboard events and subclassing NSWindow is the only method to do // this. We also handle our own window controls and custom window frame drawing. -@interface ChromeBrowserWindow : NSWindow { +@interface ChromeBrowserWindow : ChromeEventProcessingWindow { @private BOOL shouldHideTitle_; NSButton* closeButton_; @@ -38,19 +39,6 @@ const NSInteger kChromeWindowButtonsInterButtonSpacing = 7; scoped_nsobject<NSTrackingArea> widgetTrackingArea_; } -// See global_keyboard_shortcuts_mac.h for details on the next two functions. - -// Checks if |event| is a window keyboard shortcut. If so, dispatches it to the -// window controller's |executeCommand:| and returns |YES|. -- (BOOL)handleExtraWindowKeyboardShortcut:(NSEvent*)event; - -// Checks if |event| is a browser keyboard shortcut. If so, dispatches it to the -// window controller's |executeCommand:| and returns |YES|. -- (BOOL)handleExtraBrowserKeyboardShortcut:(NSEvent*)event; - -// Override, so we can handle global keyboard events. -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent; - // Tells the window to suppress title drawing. - (void)setShouldHideTitle:(BOOL)flag; @@ -60,6 +48,7 @@ const NSInteger kChromeWindowButtonsInterButtonSpacing = 7; // Update the tracking areas for our window widgets as appropriate. - (void)updateTrackingAreas; + @end @interface ChromeBrowserWindow (UndocumentedAPI) diff --git a/chrome/browser/cocoa/chrome_browser_window.mm b/chrome/browser/cocoa/chrome_browser_window.mm index fdc34de..6ad0426 100644 --- a/chrome/browser/cocoa/chrome_browser_window.mm +++ b/chrome/browser/cocoa/chrome_browser_window.mm @@ -24,9 +24,8 @@ - (NSView*)frameView; @end -typedef int (*KeyToCommandMapper)(bool, bool, bool, int); - @implementation ChromeBrowserWindow + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; @@ -282,56 +281,6 @@ typedef int (*KeyToCommandMapper)(bool, bool, bool, int); return entered_; } -- (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event fromTable: - (KeyToCommandMapper)commandForKeyboardShortcut { - // Extract info from |event|. - NSUInteger modifers = [event modifierFlags]; - const bool cmdKey = modifers & NSCommandKeyMask; - const bool shiftKey = modifers & NSShiftKeyMask; - const bool cntrlKey = modifers & NSControlKeyMask; - const int keyCode = [event keyCode]; - - int cmdNum = commandForKeyboardShortcut(cmdKey, shiftKey, cntrlKey, - keyCode); - - BrowserWindowController* controller = - (BrowserWindowController*)[self delegate]; - // A bit of sanity. - DCHECK([controller isKindOfClass:[BrowserWindowController class]]); - DCHECK([controller respondsToSelector:@selector(executeCommand:)]); - - if (cmdNum != -1) { - [controller executeCommand:cmdNum]; - return YES; - } - return NO; -} - -- (BOOL)handleExtraWindowKeyboardShortcut:(NSEvent*)event { - return [self handleExtraKeyboardShortcut:event - fromTable:CommandForWindowKeyboardShortcut]; -} - -- (BOOL)handleExtraBrowserKeyboardShortcut:(NSEvent*)event { - return [self handleExtraKeyboardShortcut:event - fromTable:CommandForBrowserKeyboardShortcut]; -} - -- (BOOL)performKeyEquivalent:(NSEvent*)event { - // Give the web site a chance to handle the event. If it doesn't want to - // handle it, it will call us back with one of the |handle*| methods above. - NSResponder* r = [self firstResponder]; - if ([r isKindOfClass:[RenderWidgetHostViewCocoa class]]) - return [r performKeyEquivalent:event]; - - // Handle per-window shortcuts like cmd-1, but do not handle browser-level - // shortcuts like cmd-left (else, cmd-left would do history navigation even - // if e.g. the Omnibox has focus). - if ([self handleExtraWindowKeyboardShortcut:event]) - return YES; - return [super performKeyEquivalent:event]; -} - - (void)setShouldHideTitle:(BOOL)flag { shouldHideTitle_ = flag; } diff --git a/chrome/browser/cocoa/chrome_browser_window_unittest.mm b/chrome/browser/cocoa/chrome_browser_window_unittest.mm index be01bc6..4982918 100644 --- a/chrome/browser/cocoa/chrome_browser_window_unittest.mm +++ b/chrome/browser/cocoa/chrome_browser_window_unittest.mm @@ -12,22 +12,6 @@ #import "chrome/browser/cocoa/cocoa_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -#import "third_party/ocmock/OCMock/OCMock.h" - -namespace { - -NSEvent* KeyEvent(const NSUInteger flags, const NSUInteger keyCode) { - return [NSEvent keyEventWithType:NSKeyDown - location:NSZeroPoint - modifierFlags:flags - timestamp:0.0 - windowNumber:0 - context:nil - characters:@"" - charactersIgnoringModifiers:@"" - isARepeat:NO - keyCode:keyCode]; -} class ChromeBrowserWindowTest : public PlatformTest { public: @@ -70,48 +54,6 @@ TEST_F(ChromeBrowserWindowTest, ShowAndClose) { [window_ display]; } -// Verify that the window intercepts a particular key event and -// forwards it to [delegate executeCommand:]. Assume that other -// CommandForKeyboardShortcut() will work the same for the rest. -TEST_F(ChromeBrowserWindowTest, PerformKeyEquivalentForwardToExecuteCommand) { - NSEvent* event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1); - - id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; - // -stub to satisfy the DCHECK. - BOOL yes = YES; - [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)] - isKindOfClass:[BrowserWindowController class]]; - [[delegate expect] executeCommand:IDC_SELECT_TAB_0]; - - [window_ setDelegate:delegate]; - [window_ performKeyEquivalent:event]; - - // Don't wish to mock all the way down... - [window_ setDelegate:nil]; - [delegate verify]; -} - -// Verify that an unhandled shortcut does not get forwarded via -// -executeCommand:. -// TODO(shess) Think of a way to test that it is sent to the -// superclass. -TEST_F(ChromeBrowserWindowTest, PerformKeyEquivalentNoForward) { - NSEvent* event = KeyEvent(0, 0); - - id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; - // -stub to satisfy the DCHECK. - BOOL yes = YES; - [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)] - isKindOfClass:[BrowserWindowController class]]; - - [window_ setDelegate:delegate]; - [window_ performKeyEquivalent:event]; - - // Don't wish to mock all the way down... - [window_ setDelegate:nil]; - [delegate verify]; -} - // Test that undocumented title-hiding API we're using does the job. TEST_F(ChromeBrowserWindowTest, DoesHideTitle) { // The -display calls are not strictly necessary, but they do @@ -191,4 +133,3 @@ TEST_F(ChromeBrowserWindowTest, DISABLED_WindowWidgetTrackingArea) { EXPECT_TRUE(foundArea); } -} // namespace diff --git a/chrome/browser/cocoa/chrome_event_processing_window.h b/chrome/browser/cocoa/chrome_event_processing_window.h new file mode 100644 index 0000000..b3cc116 --- /dev/null +++ b/chrome/browser/cocoa/chrome_event_processing_window.h @@ -0,0 +1,32 @@ +// Copyright (c) 2009 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_CHROME_EVENT_PROCESSING_WINDOW_H_ +#define CHROME_BROWSER_COCOA_CHROME_EVENT_PROCESSING_WINDOW_H_ + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" + +// Override NSWindow to access unhandled keyboard events (for command +// processing); subclassing NSWindow is the only method to do +// this. +@interface ChromeEventProcessingWindow : NSWindow + +// See global_keyboard_shortcuts_mac.h for details on the next two functions. + +// Checks if |event| is a window keyboard shortcut. If so, dispatches it to the +// window controller's |executeCommand:| and returns |YES|. +- (BOOL)handleExtraWindowKeyboardShortcut:(NSEvent*)event; + +// Checks if |event| is a browser keyboard shortcut. If so, dispatches it to the +// window controller's |executeCommand:| and returns |YES|. +- (BOOL)handleExtraBrowserKeyboardShortcut:(NSEvent*)event; + +// Override, so we can handle global keyboard events. +- (BOOL)performKeyEquivalent:(NSEvent*)theEvent; + +@end + +#endif // CHROME_BROWSER_COCOA_CHROME_EVENT_PROCESSING_WINDOW_H_ diff --git a/chrome/browser/cocoa/chrome_event_processing_window.mm b/chrome/browser/cocoa/chrome_event_processing_window.mm new file mode 100644 index 0000000..7a82ab4 --- /dev/null +++ b/chrome/browser/cocoa/chrome_event_processing_window.mm @@ -0,0 +1,69 @@ +// Copyright (c) 2009 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/chrome_event_processing_window.h" + +#include "base/logging.h" +#import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/browser_frame_view.h" +#import "chrome/browser/cocoa/tab_strip_controller.h" +#import "chrome/browser/renderer_host/render_widget_host_view_mac.h" +#include "chrome/browser/global_keyboard_shortcuts_mac.h" + +typedef int (*KeyToCommandMapper)(bool, bool, bool, int); + +@implementation ChromeEventProcessingWindow + +- (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event fromTable: + (KeyToCommandMapper)commandForKeyboardShortcut { + // Extract info from |event|. + NSUInteger modifers = [event modifierFlags]; + const bool cmdKey = modifers & NSCommandKeyMask; + const bool shiftKey = modifers & NSShiftKeyMask; + const bool cntrlKey = modifers & NSControlKeyMask; + const int keyCode = [event keyCode]; + + int cmdNum = commandForKeyboardShortcut(cmdKey, shiftKey, cntrlKey, + keyCode); + + BrowserWindowController* controller = + (BrowserWindowController*)[self delegate]; + // A bit of sanity. + DCHECK([controller isKindOfClass:[BrowserWindowController class]]); + DCHECK([controller respondsToSelector:@selector(executeCommand:)]); + + if (cmdNum != -1) { + [controller executeCommand:cmdNum]; + return YES; + } + return NO; +} + +- (BOOL)handleExtraWindowKeyboardShortcut:(NSEvent*)event { + return [self handleExtraKeyboardShortcut:event + fromTable:CommandForWindowKeyboardShortcut]; +} + +- (BOOL)handleExtraBrowserKeyboardShortcut:(NSEvent*)event { + return [self handleExtraKeyboardShortcut:event + fromTable:CommandForBrowserKeyboardShortcut]; +} + +- (BOOL)performKeyEquivalent:(NSEvent*)event { + // Give the web site a chance to handle the event. If it doesn't want to + // handle it, it will call us back with one of the |handle*| methods above. + NSResponder* r = [self firstResponder]; + if ([r isKindOfClass:[RenderWidgetHostViewCocoa class]]) + return [r performKeyEquivalent:event]; + + // Handle per-window shortcuts like cmd-1, but do not handle browser-level + // shortcuts like cmd-left (else, cmd-left would do history navigation even + // if e.g. the Omnibox has focus). + if ([self handleExtraWindowKeyboardShortcut:event]) + return YES; + return [super performKeyEquivalent:event]; +} + +@end // ChromeEventProcessingWindow + diff --git a/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm b/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm new file mode 100644 index 0000000..817cf4c --- /dev/null +++ b/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm @@ -0,0 +1,111 @@ +// Copyright (c) 2009 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 <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#include "chrome/app/chrome_dll_resource.h" +#import "chrome/browser/cocoa/chrome_event_processing_window.h" +#import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/browser_frame_view.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +namespace { + +NSEvent* KeyEvent(const NSUInteger flags, const NSUInteger keyCode) { + return [NSEvent keyEventWithType:NSKeyDown + location:NSZeroPoint + modifierFlags:flags + timestamp:0.0 + windowNumber:0 + context:nil + characters:@"" + charactersIgnoringModifiers:@"" + isARepeat:NO + keyCode:keyCode]; +} + +class ChromeEventProcessingWindowTest : public PlatformTest { + public: + ChromeEventProcessingWindowTest() { + // Create a window. + const NSUInteger mask = NSTitledWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask; + window_.reset([[ChromeEventProcessingWindow alloc] + initWithContentRect:NSMakeRect(0, 0, 800, 600) + styleMask:mask + backing:NSBackingStoreBuffered + defer:NO]); + if (DebugUtil::BeingDebugged()) { + [window_ orderFront:nil]; + } else { + [window_ orderBack:nil]; + } + } + + // Returns a canonical snapshot of the window. + NSData* WindowContentsAsTIFF() { + NSRect frame([window_ frame]); + frame.origin = [window_ convertScreenToBase:frame.origin]; + + NSData* pdfData = [window_ dataWithPDFInsideRect:frame]; + + // |pdfData| can differ for windows which look the same, so make it + // canonical. + NSImage* image = [[[NSImage alloc] initWithData:pdfData] autorelease]; + return [image TIFFRepresentation]; + } + + CocoaNoWindowTestHelper cocoa_helper_; + scoped_nsobject<ChromeEventProcessingWindow> window_; +}; + +// Verify that the window intercepts a particular key event and +// forwards it to [delegate executeCommand:]. Assume that other +// CommandForKeyboardShortcut() will work the same for the rest. +TEST_F(ChromeEventProcessingWindowTest, + PerformKeyEquivalentForwardToExecuteCommand) { + NSEvent* event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1); + + id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; + // -stub to satisfy the DCHECK. + BOOL yes = YES; + [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)] + isKindOfClass:[BrowserWindowController class]]; + [[delegate expect] executeCommand:IDC_SELECT_TAB_0]; + + [window_ setDelegate:delegate]; + [window_ performKeyEquivalent:event]; + + // Don't wish to mock all the way down... + [window_ setDelegate:nil]; + [delegate verify]; +} + +// Verify that an unhandled shortcut does not get forwarded via +// -executeCommand:. +// TODO(shess) Think of a way to test that it is sent to the +// superclass. +TEST_F(ChromeEventProcessingWindowTest, PerformKeyEquivalentNoForward) { + NSEvent* event = KeyEvent(0, 0); + + id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; + // -stub to satisfy the DCHECK. + BOOL yes = YES; + [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)] + isKindOfClass:[BrowserWindowController class]]; + + [window_ setDelegate:delegate]; + [window_ performKeyEquivalent:event]; + + // Don't wish to mock all the way down... + [window_ setDelegate:nil]; + [delegate verify]; +} + + +} // namespace diff --git a/chrome/browser/cocoa/fullscreen_window.h b/chrome/browser/cocoa/fullscreen_window.h index 1f944e4..313c72a 100644 --- a/chrome/browser/cocoa/fullscreen_window.h +++ b/chrome/browser/cocoa/fullscreen_window.h @@ -3,11 +3,14 @@ // found in the LICENSE file. #include <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/chrome_event_processing_window.h" // A FullscreenWindow is a borderless window suitable for going // fullscreen. The returned window is NOT release when closed and is // not initially visible. -@interface FullscreenWindow : NSWindow +// FullscreenWindow derives from ChromeEventProcessingWindow to inherit +// special event handling (e.g. handleExtraKeyboardShortcut). +@interface FullscreenWindow : ChromeEventProcessingWindow // Initialize a FullscreenWindow for the given screen. // Designated initializer. diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 1f922cc..6bba4f0 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1049,6 +1049,8 @@ 'browser/cocoa/bubble_view.mm', 'browser/cocoa/chrome_browser_window.h', 'browser/cocoa/chrome_browser_window.mm', + 'browser/cocoa/chrome_event_processing_window.h', + 'browser/cocoa/chrome_event_processing_window.mm', 'browser/cocoa/clear_browsing_data_controller.h', 'browser/cocoa/clear_browsing_data_controller.mm', 'browser/cocoa/clickhold_button_cell.h', @@ -4376,6 +4378,7 @@ 'browser/cocoa/browser_window_controller_unittest.mm', 'browser/cocoa/bubble_view_unittest.mm', 'browser/cocoa/chrome_browser_window_unittest.mm', + 'browser/cocoa/chrome_event_processing_window_unittest.mm', 'browser/cocoa/clear_browsing_data_controller_unittest.mm', 'browser/cocoa/clickhold_button_cell_unittest.mm', 'browser/cocoa/cocoa_test_helper.h', |