Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 | 6 |
| 7 #include "base/logging.h" // for NOTREACHED() | 7 #include "base/logging.h" // for NOTREACHED() |
| 8 #include "base/mac/mac_util.h" | 8 #include "base/mac/mac_util.h" |
| 9 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 10 #include "base/utf_string_conversions.h" | |
| 10 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
| 11 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
| 12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 13 #import "chrome/browser/ui/cocoa/animatable_view.h" | 14 #import "chrome/browser/ui/cocoa/animatable_view.h" |
| 14 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 15 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 15 #include "chrome/browser/ui/cocoa/event_utils.h" | 16 #include "chrome/browser/ui/cocoa/event_utils.h" |
| 16 #import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h" | 17 #import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h" |
| 17 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" | 18 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" |
| 19 #import "chrome/browser/ui/cocoa/info_bubble_view.h" | |
| 18 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
| 19 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" | 21 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" |
| 20 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" | 22 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" |
| 21 #include "ui/base/models/accelerator_cocoa.h" | 23 #include "ui/base/models/accelerator_cocoa.h" |
| 22 #include "ui/base/l10n/l10n_util_mac.h" | 24 #include "ui/base/l10n/l10n_util_mac.h" |
| 23 | 25 |
| 24 const int kPaddingPx = 8; | 26 const int kPaddingPx = 8; |
| 25 const int kInitialDelayMs = 3800; | 27 const int kInitialDelayMs = 3800; |
| 26 const int kSlideOutDurationMs = 700; | 28 const int kSlideOutDurationMs = 700; |
| 27 | 29 |
| 28 @interface FullscreenExitBubbleController (PrivateMethods) | 30 @interface FullscreenExitBubbleController (PrivateMethods) |
| 29 // Sets |exitLabel_| based on |exitLabelPlaceholder_|, | 31 // Sets |exitLabel_| based on |exitLabelPlaceholder_|, |
| 30 // sets |exitLabelPlaceholder_| to nil. | 32 // sets |exitLabelPlaceholder_| to nil. |
| 31 - (void)initializeLabel; | 33 - (void)initializeLabel; |
| 32 | 34 |
| 33 - (void)hideSoon; | 35 - (void)hideSoon; |
| 34 | 36 |
| 35 // Returns the Accelerator for the Toggle Fullscreen menu item. | 37 // Returns the Accelerator for the Toggle Fullscreen menu item. |
| 36 + (ui::AcceleratorCocoa)acceleratorForToggleFullscreen; | 38 + (ui::AcceleratorCocoa)acceleratorForToggleFullscreen; |
| 37 | 39 |
| 38 // Returns a string representation fit for display of | 40 // Returns a string representation fit for display of |
| 39 // +acceleratorForToggleFullscreen. | 41 // +acceleratorForToggleFullscreen. |
| 40 + (NSString*)keyCommandString; | 42 + (NSString*)keyCommandString; |
| 41 | 43 |
| 42 + (NSString*)keyCombinationForAccelerator:(const ui::AcceleratorCocoa&)item; | 44 + (NSString*)keyCombinationForAccelerator:(const ui::AcceleratorCocoa&)item; |
| 43 @end | 45 @end |
| 44 | 46 |
| 45 @implementation FullscreenExitBubbleController | 47 @implementation FullscreenExitBubbleController |
| 46 | 48 |
| 47 - (id)initWithOwner:(BrowserWindowController*)owner browser:(Browser*)browser { | 49 - (id)initWithOwner:(BrowserWindowController*)owner |
| 48 if ((self = [super initWithNibName:@"FullscreenExitBubble" | 50 browser:(Browser*)browser |
| 49 bundle:base::mac::MainAppBundle()])) { | 51 forURL:(const GURL&)url |
| 52 showButtons:(BOOL)show_buttons { | |
| 53 NSString* nibPath = | |
| 54 [base::mac::MainAppBundle() pathForResource:@"FullscreenExitBubble" | |
| 55 ofType:@"nib"]; | |
| 56 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { | |
| 50 browser_ = browser; | 57 browser_ = browser; |
| 51 owner_ = owner; | 58 owner_ = owner; |
| 59 url_ = url; | |
| 60 show_buttons_ = show_buttons; | |
| 52 } | 61 } |
| 53 return self; | 62 return self; |
| 54 } | 63 } |
| 55 | 64 |
| 56 - (void)awakeFromNib { | 65 - (void)allow:(id)sender { |
| 57 [self initializeLabel]; | 66 [self hideButtons]; |
| 67 browser_->OnAcceptFullscreenPermission(url_); | |
| 58 [self hideSoon]; | 68 [self hideSoon]; |
| 59 } | 69 } |
| 60 | 70 |
| 71 - (void)deny:(id)sender { | |
| 72 browser_->ToggleFullscreenMode(false); | |
| 73 } | |
| 74 | |
| 75 - (void)hideButtons { | |
| 76 [allowButton_ setHidden:YES]; | |
| 77 [denyButton_ setHidden:YES]; | |
| 78 [exitLabel_ setHidden:NO]; | |
| 79 } | |
| 80 | |
| 81 // We want this to be a child of a browser window. addChildWindow: | |
| 82 // (called from this function) will bring the window on-screen; | |
| 83 // unfortunately, [NSWindowController showWindow:] will also bring it | |
| 84 // on-screen (but will cause unexpected changes to the window's | |
| 85 // position). We cannot have an addChildWindow: and a subsequent | |
| 86 // showWindow:. Thus, we have our own version. | |
| 87 - (void)showWindow { | |
| 88 BrowserWindowController* bwc = owner_; | |
| 89 NSWindow* window = [self window]; // completes nib load | |
| 90 [bubble_ setArrowLocation:info_bubble::kNoArrow]; | |
| 91 if (!show_buttons_) { | |
| 92 [self hideButtons]; | |
| 93 [self hideSoon]; | |
| 94 } | |
| 95 CGFloat maxWidth = NSWidth([bwc window].frame); | |
| 96 CGFloat maxY = NSHeight([bwc window].frame); | |
|
Scott Hess - ex-Googler
2011/10/10 23:19:50
Capture the frame once in an NSRect then use NSWid
jeremya
2011/10/11 05:28:48
Done.
| |
| 97 [tweaker_ tweakUI:[self window]]; | |
| 98 [self positionInWindowAtTop:maxY width:maxWidth]; | |
| 99 [[bwc window] addChildWindow:window ordered:NSWindowAbove]; | |
| 100 | |
| 101 [window orderFront:self]; | |
| 102 } | |
| 103 | |
| 104 - (void)awakeFromNib { | |
| 105 [self initializeLabel]; | |
| 106 NSString* title = | |
| 107 l10n_util::GetNSStringF(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMISSION, | |
| 108 UTF8ToUTF16(url_.host())); | |
| 109 [siteInfoLabel_ setStringValue:title]; | |
| 110 [super awakeFromNib]; | |
| 111 } | |
| 112 | |
| 61 - (void)positionInWindowAtTop:(CGFloat)maxY width:(CGFloat)maxWidth { | 113 - (void)positionInWindowAtTop:(CGFloat)maxY width:(CGFloat)maxWidth { |
| 62 NSRect bubbleFrame = [[self view] frame]; | 114 NSPoint origin = [[self window] frame].origin; |
| 63 bubbleFrame.origin.x = (int)(maxWidth/2 - NSWidth(bubbleFrame)/2); | 115 origin.x = (int)(maxWidth/2 - NSWidth([self window].frame)/2); |
| 64 bubbleFrame.origin.y = maxY - NSHeight(bubbleFrame); | 116 origin.y = maxY - NSHeight([self window].frame); |
|
Scott Hess - ex-Googler
2011/10/10 23:19:50
Likewise here, capture the frame once then work on
jeremya
2011/10/11 05:28:48
Done.
| |
| 65 [[self view] setFrame:bubbleFrame]; | 117 origin.y -= fullscreen_exit_bubble::kBubbleOffsetY; |
| 118 [[self window] setFrameOrigin:origin]; | |
| 66 } | 119 } |
| 67 | 120 |
| 68 // Called when someone clicks on the embedded link. | 121 // Called when someone clicks on the embedded link. |
| 69 - (BOOL) textView:(NSTextView*)textView | 122 - (BOOL) textView:(NSTextView*)textView |
| 70 clickedOnLink:(id)link | 123 clickedOnLink:(id)link |
| 71 atIndex:(NSUInteger)charIndex { | 124 atIndex:(NSUInteger)charIndex { |
| 72 browser_->ExecuteCommand(IDC_FULLSCREEN); | 125 browser_->ExecuteCommand(IDC_FULLSCREEN); |
| 73 return YES; | 126 return YES; |
| 74 } | 127 } |
| 75 | 128 |
| 76 - (void)hideTimerFired:(NSTimer*)timer { | 129 - (void)hideTimerFired:(NSTimer*)timer { |
| 77 NSRect endFrame = [[self view] frame]; | 130 [NSAnimationContext beginGrouping]; |
| 131 // The star currently triggers on mouse down, not mouse up. | |
| 132 [[NSAnimationContext currentContext] | |
| 133 gtm_setDuration:0.2 // TODO: Constantify. | |
| 134 eventMask:NSLeftMouseUpMask|NSLeftMouseDownMask]; | |
| 135 [[[self window] animator] setAlphaValue:0.0]; | |
| 136 [NSAnimationContext endGrouping]; | |
| 137 return; | |
| 138 NSRect endFrame = [[self window] frame]; | |
| 78 endFrame.origin.y += endFrame.size.height; | 139 endFrame.origin.y += endFrame.size.height; |
| 79 endFrame.size.height = 0; | |
| 80 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: | 140 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: |
| 81 [self view], NSViewAnimationTargetKey, | 141 [self window], NSViewAnimationTargetKey, |
| 82 [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil]; | 142 [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil]; |
| 83 | 143 |
| 84 NSViewAnimation* animation = | 144 NSViewAnimation* animation = |
| 85 [[NSViewAnimation alloc] | 145 [[NSViewAnimation alloc] |
| 86 initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; | 146 initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; |
| 87 [animation gtm_setDuration:kSlideOutDurationMs/1000.0 | 147 [animation gtm_setDuration:kSlideOutDurationMs/1000.0 |
| 88 eventMask:NSLeftMouseUpMask]; | 148 eventMask:NSLeftMouseUpMask]; |
| 89 [animation setDelegate:self]; | 149 [animation setDelegate:self]; |
| 90 [animation startAnimation]; | 150 [animation startAnimation]; |
| 91 hideAnimation_.reset(animation); | 151 hideAnimation_.reset(animation); |
| 92 } | 152 } |
| 93 | 153 |
| 94 - (void)animationDidEnd:(NSAnimation*)animation { | 154 - (void)animationDidEnd:(NSAnimation*)animation { |
| 95 if (animation == hideAnimation_.get()) { | 155 if (animation == hideAnimation_.get()) { |
| 96 hideAnimation_.reset(); | 156 hideAnimation_.reset(); |
| 97 } | 157 } |
| 98 } | 158 } |
| 99 | 159 |
| 100 - (AnimatableView*)animatableView { | 160 - (AnimatableView*)animatableView { |
| 101 return static_cast<AnimatableView*>([self view]); | 161 return static_cast<AnimatableView*>([self window]); |
|
Scott Hess - ex-Googler
2011/10/10 23:19:50
Is this still a valid conversion?
jeremya
2011/10/11 05:28:48
Nope :) Removed.
| |
| 102 } | 162 } |
| 103 | 163 |
| 104 - (void)dealloc { | 164 - (void)dealloc { |
| 105 [hideAnimation_.get() stopAnimation]; | 165 [hideAnimation_.get() stopAnimation]; |
| 106 [hideTimer_ invalidate]; | 166 [hideTimer_ invalidate]; |
| 107 [super dealloc]; | 167 [super dealloc]; |
| 108 } | 168 } |
| 109 | 169 |
| 110 @end | 170 @end |
| 111 | 171 |
| 112 @implementation FullscreenExitBubbleController (PrivateMethods) | 172 @implementation FullscreenExitBubbleController (PrivateMethods) |
| 113 | 173 |
| 114 - (void)initializeLabel { | 174 - (void)initializeLabel { |
| 115 // Replace the label placeholder NSTextField with the real label NSTextView. | 175 // Replace the label placeholder NSTextField with the real label NSTextView. |
| 116 // The former doesn't show links in a nice way, but the latter can't be added | 176 // The former doesn't show links in a nice way, but the latter can't be added |
| 117 // in IB without a containing scroll view, so create the NSTextView | 177 // in IB without a containing scroll view, so create the NSTextView |
| 118 // programmatically. | 178 // programmatically. |
| 119 exitLabel_.reset([[HyperlinkTextView alloc] | 179 exitLabel_.reset([[HyperlinkTextView alloc] |
| 120 initWithFrame:[exitLabelPlaceholder_ frame]]); | 180 initWithFrame:[exitLabelPlaceholder_ frame]]); |
| 121 [exitLabel_.get() setAutoresizingMask: | 181 [exitLabel_.get() setAutoresizingMask: |
| 122 [exitLabelPlaceholder_ autoresizingMask]]; | 182 [exitLabelPlaceholder_ autoresizingMask]]; |
| 183 [exitLabel_.get() setHidden:[exitLabelPlaceholder_ isHidden]]; | |
| 123 [[exitLabelPlaceholder_ superview] | 184 [[exitLabelPlaceholder_ superview] |
| 124 replaceSubview:exitLabelPlaceholder_ with:exitLabel_.get()]; | 185 replaceSubview:exitLabelPlaceholder_ with:exitLabel_.get()]; |
| 125 exitLabelPlaceholder_ = nil; // Now released. | 186 exitLabelPlaceholder_ = nil; // Now released. |
| 126 [exitLabel_.get() setDelegate:self]; | 187 [exitLabel_.get() setDelegate:self]; |
| 127 | 188 |
| 128 NSString *message = l10n_util::GetNSStringF(IDS_EXIT_FULLSCREEN_MODE, | 189 NSString *message = l10n_util::GetNSStringF(IDS_EXIT_FULLSCREEN_MODE, |
| 129 base::SysNSStringToUTF16([[self class] keyCommandString])); | 190 base::SysNSStringToUTF16([[self class] keyCommandString])); |
| 130 | 191 |
| 192 NSFont* font = [NSFont systemFontOfSize: | |
| 193 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]; | |
|
Scott Hess - ex-Googler
2011/10/10 23:19:50
Merge error?
jeremya
2011/10/11 05:28:48
I don't think so... what makes you say that?
Scott Hess - ex-Googler
2011/10/11 05:32:30
Sorry, brace-counting fail across the lines, compo
| |
| 131 [(HyperlinkTextView*)exitLabel_.get() | 194 [(HyperlinkTextView*)exitLabel_.get() |
| 132 setMessageAndLink:@"" | 195 setMessageAndLink:@"" |
| 133 withLink:message | 196 withLink:message |
| 134 atOffset:0 | 197 atOffset:0 |
| 135 font:[NSFont systemFontOfSize:18] | 198 font:font |
| 136 messageColor:[NSColor whiteColor] | 199 messageColor:[NSColor blackColor] |
| 137 linkColor:[NSColor whiteColor]]; | 200 linkColor:[NSColor blueColor]]; |
| 138 | 201 [exitLabel_.get() setAlignment:NSRightTextAlignment]; |
| 202 // TODO: sizeToFit doesn't seem to get quite the right size. | |
| 203 [exitLabel_.get() setVerticallyResizable:NO]; | |
| 204 [exitLabel_.get() setHorizontallyResizable:YES]; | |
| 139 [exitLabel_.get() sizeToFit]; | 205 [exitLabel_.get() sizeToFit]; |
| 140 NSLayoutManager* layoutManager = [exitLabel_.get() layoutManager]; | 206 NSSize frameSize = [exitLabel_ frame].size; |
| 141 NSTextContainer* textContainer = [exitLabel_.get() textContainer]; | 207 frameSize.width += 30; |
| 142 [layoutManager ensureLayoutForTextContainer:textContainer]; | 208 [exitLabel_.get() setFrameSize:frameSize]; |
| 143 NSRect textFrame = [layoutManager usedRectForTextContainer:textContainer]; | |
| 144 NSRect frame = [[self view] frame]; | |
| 145 NSSize textSize = textFrame.size; | |
| 146 frame.size.width = textSize.width + 2 * kPaddingPx; | |
| 147 [[self view] setFrame:frame]; | |
| 148 textFrame.origin.x = textFrame.origin.y = kPaddingPx; | |
| 149 [exitLabel_.get() setFrame:textFrame]; | |
| 150 } | 209 } |
| 151 | 210 |
| 152 // This looks at the Main Menu and determines what the user has set as the | 211 // This looks at the Main Menu and determines what the user has set as the |
| 153 // key combination for quit. It then gets the modifiers and builds an object | 212 // key combination for quit. It then gets the modifiers and builds an object |
| 154 // to hold the data. | 213 // to hold the data. |
| 155 + (ui::AcceleratorCocoa)acceleratorForToggleFullscreen { | 214 + (ui::AcceleratorCocoa)acceleratorForToggleFullscreen { |
| 156 NSMenu* mainMenu = [NSApp mainMenu]; | 215 NSMenu* mainMenu = [NSApp mainMenu]; |
| 157 // Get the application menu (i.e. Chromium). | 216 // Get the application menu (i.e. Chromium). |
| 158 for (NSMenuItem* menu in [mainMenu itemArray]) { | 217 for (NSMenuItem* menu in [mainMenu itemArray]) { |
| 159 for (NSMenuItem* item in [[menu submenu] itemArray]) { | 218 for (NSMenuItem* item in [[menu submenu] itemArray]) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 - (void)hideSoon { | 258 - (void)hideSoon { |
| 200 hideTimer_.reset( | 259 hideTimer_.reset( |
| 201 [[NSTimer scheduledTimerWithTimeInterval:kInitialDelayMs/1000.0 | 260 [[NSTimer scheduledTimerWithTimeInterval:kInitialDelayMs/1000.0 |
| 202 target:self | 261 target:self |
| 203 selector:@selector(hideTimerFired:) | 262 selector:@selector(hideTimerFired:) |
| 204 userInfo:nil | 263 userInfo:nil |
| 205 repeats:NO] retain]); | 264 repeats:NO] retain]); |
| 206 } | 265 } |
| 207 | 266 |
| 208 @end | 267 @end |
| OLD | NEW |