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

Side by Side Diff: chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.mm

Issue 7740044: Implement fullscreen info bubble on Win and Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: win work Created 9 years, 2 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 | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698