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

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

Issue 12453019: Copy remoting notification bar to chrome and use it for screen capture API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 #import "remoting/host/disconnect_window_mac.h" 7 #include "chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.h"
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/i18n/rtl.h"
11 #include "base/mac/bundle_locations.h"
10 #include "base/string_util.h" 12 #include "base/string_util.h"
11 #include "base/sys_string_conversions.h" 13 #include "base/sys_string_conversions.h"
12 #include "remoting/host/disconnect_window.h" 14 #include "grit/generated_resources.h"
13 #include "remoting/host/ui_strings.h" 15 #include "ui/base/l10n/l10n_util.h"
14 16
15 @interface DisconnectWindowController() 17 @interface ScreenCaptureNotificationController()
16 - (BOOL)isRToL;
17 - (void)Hide; 18 - (void)Hide;
18 @end 19 @end
19 20
20 namespace remoting { 21 class ScreenCaptureNotificationUICocoa : public ScreenCaptureNotificationUI {
22 public:
23 ScreenCaptureNotificationUICocoa();
24 virtual ~ScreenCaptureNotificationUICocoa();
21 25
22 class DisconnectWindowMac : public remoting::DisconnectWindow { 26 // ScreenCaptureNotificationUI interface.
23 public: 27 virtual bool Show(const base::Closure& stop_callback,
24 explicit DisconnectWindowMac(const UiStrings* ui_strings); 28 const string16& title) OVERRIDE;
25 virtual ~DisconnectWindowMac();
26
27 virtual bool Show(const base::Closure& disconnect_callback,
28 const std::string& username) OVERRIDE;
29 virtual void Hide() OVERRIDE;
30 29
31 private: 30 private:
32 DisconnectWindowController* window_controller_; 31 ScreenCaptureNotificationController* window_controller_;
33 32
34 // Points to the localized strings. 33 DISALLOW_COPY_AND_ASSIGN(ScreenCaptureNotificationUICocoa);
35 const UiStrings* ui_strings_;
36
37 DISALLOW_COPY_AND_ASSIGN(DisconnectWindowMac);
38 }; 34 };
39 35
40 DisconnectWindowMac::DisconnectWindowMac(const UiStrings* ui_strings) 36 ScreenCaptureNotificationUICocoa::ScreenCaptureNotificationUICocoa()
41 : window_controller_(nil), 37 : window_controller_(nil) {
42 ui_strings_(ui_strings) {
43 } 38 }
44 39
45 DisconnectWindowMac::~DisconnectWindowMac() { 40 ScreenCaptureNotificationUICocoa::~ScreenCaptureNotificationUICocoa() {
46 Hide(); 41 // ScreenCaptureNotificationController is responsible for releasing itself in
42 // its windowWillClose: method.
43 [window_controller_ Hide];
44 window_controller_ = nil;
47 } 45 }
48 46
49 bool DisconnectWindowMac::Show(const base::Closure& disconnect_callback, 47 bool ScreenCaptureNotificationUICocoa::Show(const base::Closure& stop_callback,
50 const std::string& username) { 48 const string16& title) {
51 DCHECK(!disconnect_callback.is_null()); 49 DCHECK(!stop_callback.is_null());
52 DCHECK(window_controller_ == nil); 50 DCHECK(window_controller_ == nil);
53 51
54 window_controller_ = 52 window_controller_ =
55 [[DisconnectWindowController alloc] initWithUiStrings:ui_strings_ 53 [[ScreenCaptureNotificationController alloc]
56 callback:disconnect_callback 54 initWithCallback:stop_callback
57 username:username]; 55 title:title];
58 [window_controller_ showWindow:nil]; 56 [window_controller_ showWindow:nil];
59 return true; 57 return true;
60 } 58 }
61 59
62 void DisconnectWindowMac::Hide() { 60 scoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create() {
63 // DisconnectWindowController is responsible for releasing itself in its 61 return scoped_ptr<ScreenCaptureNotificationUI>(
64 // windowWillClose: method. 62 new ScreenCaptureNotificationUICocoa());
65 [window_controller_ Hide];
66 window_controller_ = nil;
67 } 63 }
68 64
69 scoped_ptr<DisconnectWindow> DisconnectWindow::Create( 65 @implementation ScreenCaptureNotificationController
70 const UiStrings* ui_strings) { 66 - (id)initWithCallback:(const base::Closure&)stop_callback
71 return scoped_ptr<DisconnectWindow>(new DisconnectWindowMac(ui_strings)); 67 title:(const string16&)title {
72 } 68 NSString* nibpath =
73 69 [base::mac::FrameworkBundle() pathForResource:@"ScreenCaptureNotification"
74 } // namespace remoting 70 ofType:@"nib"];
75 71 self = [super initWithWindowNibPath:nibpath owner:self];
76 @implementation DisconnectWindowController
77 - (id)initWithUiStrings:(const remoting::UiStrings*)ui_strings
78 callback:(const base::Closure&)disconnect_callback
79 username:(const std::string&)username {
80 self = [super initWithWindowNibName:@"disconnect_window"];
81 if (self) { 72 if (self) {
82 ui_strings_ = ui_strings; 73 stop_callback_ = stop_callback;
83 disconnect_callback_ = disconnect_callback; 74 title_ = title;
84 username_ = UTF8ToUTF16(username);
85 } 75 }
86 return self; 76 return self;
87 } 77 }
88 78
89 - (void)dealloc { 79 - (void)dealloc {
90 [super dealloc]; 80 [super dealloc];
91 } 81 }
92 82
93 - (IBAction)stopSharing:(id)sender { 83 - (IBAction)stopSharing:(id)sender {
94 if (!disconnect_callback_.is_null()) { 84 if (!stop_callback_.is_null()) {
95 disconnect_callback_.Run(); 85 stop_callback_.Run();
96 } 86 }
97 } 87 }
98 88
99 - (BOOL)isRToL {
100 return ui_strings_->direction == remoting::UiStrings::RTL;
101 }
102
103 - (void)Hide { 89 - (void)Hide {
104 disconnect_callback_.Reset(); 90 stop_callback_.Reset();
105 [self close]; 91 [self close];
106 } 92 }
107 93
108 - (void)windowDidLoad { 94 - (void)windowDidLoad {
109 string16 text = ReplaceStringPlaceholders(ui_strings_->disconnect_message, 95 string16 text = l10n_util::GetStringFUTF16(
110 username_, NULL); 96 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, title_);
111 [connectedToField_ setStringValue:base::SysUTF16ToNSString(text)]; 97 [statusField_ setStringValue:base::SysUTF16ToNSString(text)];
112 98
113 [disconnectButton_ setTitle:base::SysUTF16ToNSString( 99 string16 button_label =
114 ui_strings_->disconnect_button_text)]; 100 l10n_util::GetStringUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP);
101 [stopButton_ setTitle:base::SysUTF16ToNSString(button_label)];
115 102
116 // Resize the window dynamically based on the content. 103 // Resize the window dynamically based on the content.
117 CGFloat oldConnectedWidth = NSWidth([connectedToField_ bounds]); 104 CGFloat oldConnectedWidth = NSWidth([statusField_ bounds]);
118 [connectedToField_ sizeToFit]; 105 [statusField_ sizeToFit];
119 NSRect connectedToFrame = [connectedToField_ frame]; 106 NSRect statusFrame = [statusField_ frame];
120 CGFloat newConnectedWidth = NSWidth(connectedToFrame); 107 CGFloat newConnectedWidth = NSWidth(statusFrame);
121 108
122 // Set a max width for the connected to text field. 109 // Set a max width for the connected to text field.
123 if (newConnectedWidth > 110 const int kMaximumStatusWidth = 400;
124 remoting::DisconnectWindow::kMaximumConnectedNameWidthInPixels) { 111 if (newConnectedWidth > kMaximumStatusWidth) {
125 newConnectedWidth 112 newConnectedWidth = kMaximumStatusWidth;
126 = remoting::DisconnectWindow::kMaximumConnectedNameWidthInPixels; 113 statusFrame.size.width = newConnectedWidth;
127 connectedToFrame.size.width = newConnectedWidth; 114 [statusField_ setFrame:statusFrame];
128 [connectedToField_ setFrame:connectedToFrame];
129 } 115 }
130 116
131 CGFloat oldDisconnectWidth = NSWidth([disconnectButton_ bounds]); 117 CGFloat oldstopWidth = NSWidth([stopButton_ bounds]);
132 [disconnectButton_ sizeToFit]; 118 [stopButton_ sizeToFit];
133 NSRect disconnectFrame = [disconnectButton_ frame]; 119 NSRect stopFrame = [stopButton_ frame];
134 CGFloat newDisconnectWidth = NSWidth(disconnectFrame); 120 CGFloat newStopWidth = NSWidth(stopFrame);
135 121
136 // Move the disconnect button appropriately. 122 // Move the stop button appropriately.
137 disconnectFrame.origin.x += newConnectedWidth - oldConnectedWidth; 123 stopFrame.origin.x += newConnectedWidth - oldConnectedWidth;
138 [disconnectButton_ setFrame:disconnectFrame]; 124 [stopButton_ setFrame:stopFrame];
139 125
140 // Then resize the window appropriately 126 // Then resize the window appropriately
Nico 2013/03/22 18:46:37 .
Sergey Ulanov 2013/03/22 19:39:09 Done.
141 NSWindow *window = [self window]; 127 NSWindow *window = [self window];
142 NSRect windowFrame = [window frame]; 128 NSRect windowFrame = [window frame];
143 windowFrame.size.width += (newConnectedWidth - oldConnectedWidth + 129 windowFrame.size.width += (newConnectedWidth - oldConnectedWidth +
144 newDisconnectWidth - oldDisconnectWidth); 130 newStopWidth - oldstopWidth);
145 [window setFrame:windowFrame display:NO]; 131 [window setFrame:windowFrame display:NO];
146 132
147 if ([self isRToL]) { 133 if (base::i18n::IsRTL()) {
148 // Handle right to left case 134 // Handle right to left case
149 CGFloat buttonInset = NSWidth(windowFrame) - NSMaxX(disconnectFrame); 135 CGFloat buttonInset = NSWidth(windowFrame) - NSMaxX(stopFrame);
150 CGFloat buttonTextSpacing 136 CGFloat buttonTextSpacing
151 = NSMinX(disconnectFrame) - NSMaxX(connectedToFrame); 137 = NSMinX(stopFrame) - NSMaxX(statusFrame);
152 disconnectFrame.origin.x = buttonInset; 138 stopFrame.origin.x = buttonInset;
153 connectedToFrame.origin.x = NSMaxX(disconnectFrame) + buttonTextSpacing; 139 statusFrame.origin.x = NSMaxX(stopFrame) + buttonTextSpacing;
154 [connectedToField_ setFrame:connectedToFrame]; 140 [statusField_ setFrame:statusFrame];
155 [disconnectButton_ setFrame:disconnectFrame]; 141 [stopButton_ setFrame:stopFrame];
156 } 142 }
157 143
158 // Center the window at the bottom of the screen, above the dock (if present). 144 // Center the window at the bottom of the screen, above the dock (if present).
159 NSRect desktopRect = [[NSScreen mainScreen] visibleFrame]; 145 NSRect desktopRect = [[NSScreen mainScreen] visibleFrame];
160 NSRect windowRect = [[self window] frame]; 146 NSRect windowRect = [[self window] frame];
161 CGFloat x = (NSWidth(desktopRect) - NSWidth(windowRect)) / 2; 147 CGFloat x = (NSWidth(desktopRect) - NSWidth(windowRect)) / 2;
162 CGFloat y = NSMinY(desktopRect); 148 CGFloat y = NSMinY(desktopRect);
163 [[self window] setFrameOrigin:NSMakePoint(x, y)]; 149 [[self window] setFrameOrigin:NSMakePoint(x, y)];
164 } 150 }
165 151
166 - (void)windowWillClose:(NSNotification*)notification { 152 - (void)windowWillClose:(NSNotification*)notification {
167 [self stopSharing:self]; 153 [self stopSharing:self];
168 [self autorelease]; 154 [self autorelease];
169 } 155 }
170 156
171 @end 157 @end
172 158
173 159
174 @interface DisconnectWindow() 160 @implementation ScreenCaptureNotificationWindow
175 - (BOOL)isRToL;
176 @end
177
178 @implementation DisconnectWindow
179
180 - (id)initWithContentRect:(NSRect)contentRect 161 - (id)initWithContentRect:(NSRect)contentRect
181 styleMask:(NSUInteger)aStyle 162 styleMask:(NSUInteger)aStyle
182 backing:(NSBackingStoreType)bufferingType 163 backing:(NSBackingStoreType)bufferingType
183 defer:(BOOL)flag { 164 defer:(BOOL)flag {
184 // Pass NSBorderlessWindowMask for the styleMask to remove the title bar. 165 // Pass NSBorderlessWindowMask for the styleMask to remove the title bar.
185 self = [super initWithContentRect:contentRect 166 self = [super initWithContentRect:contentRect
186 styleMask:NSBorderlessWindowMask 167 styleMask:NSBorderlessWindowMask
187 backing:bufferingType 168 backing:bufferingType
188 defer:flag]; 169 defer:flag];
189 170
190 if (self) { 171 if (self) {
191 // Set window to be clear and non-opaque so we can see through it. 172 // Set window to be clear and non-opaque so we can see through it.
192 [self setBackgroundColor:[NSColor clearColor]]; 173 [self setBackgroundColor:[NSColor clearColor]];
193 [self setOpaque:NO]; 174 [self setOpaque:NO];
194 [self setMovableByWindowBackground:YES]; 175 [self setMovableByWindowBackground:YES];
195 176
196 // Pull the window up to Status Level so that it always displays. 177 // Pull the window up to Status Level so that it always displays.
197 [self setLevel:NSStatusWindowLevel]; 178 [self setLevel:NSStatusWindowLevel];
198 } 179 }
199 return self; 180 return self;
200 } 181 }
201
202 - (BOOL)isRToL {
203 DCHECK([[self windowController] respondsToSelector:@selector(isRToL)]);
204 return [[self windowController] isRToL];
205 }
206
207 @end 182 @end
208 183
209 184 @implementation ScreenCaptureNotificationView
210 @interface DisconnectView()
211 - (BOOL)isRToL;
212 @end
213
214 @implementation DisconnectView
215
216 - (BOOL)isRToL {
217 DCHECK([[self window] isKindOfClass:[DisconnectWindow class]]);
218 return [static_cast<DisconnectWindow*>([self window]) isRToL];
219 }
220
221 - (void)drawRect:(NSRect)rect { 185 - (void)drawRect:(NSRect)rect {
222 // All magic numbers taken from screen shots provided by UX. 186 // All magic numbers taken from screen shots provided by UX.
223 NSRect bounds = NSInsetRect([self bounds], 1, 1); 187 NSRect bounds = NSInsetRect([self bounds], 1, 1);
224 188
225 NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:bounds 189 NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:bounds
226 xRadius:5 190 xRadius:5
227 yRadius:5]; 191 yRadius:5];
228 NSColor *gray = [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]; 192 NSColor *gray = [NSColor colorWithCalibratedWhite:0.91 alpha:1.0];
229 [gray setFill]; 193 [gray setFill];
230 [path fill]; 194 [path fill];
(...skipping 10 matching lines...) Expand all
241 const CGFloat kHeight = 21.0; 205 const CGFloat kHeight = 21.0;
242 const CGFloat kBaseInset = 12.0; 206 const CGFloat kBaseInset = 12.0;
243 const CGFloat kDragHandleWidth = 5.0; 207 const CGFloat kDragHandleWidth = 5.0;
244 208
245 NSColor *dark = [NSColor colorWithCalibratedWhite:0.70 alpha:1.0]; 209 NSColor *dark = [NSColor colorWithCalibratedWhite:0.70 alpha:1.0];
246 NSColor *light = [NSColor colorWithCalibratedWhite:0.97 alpha:1.0]; 210 NSColor *light = [NSColor colorWithCalibratedWhite:0.97 alpha:1.0];
247 211
248 // Turn off aliasing so it's nice and crisp. 212 // Turn off aliasing so it's nice and crisp.
249 NSGraphicsContext *context = [NSGraphicsContext currentContext]; 213 NSGraphicsContext *context = [NSGraphicsContext currentContext];
250 BOOL alias = [context shouldAntialias]; 214 BOOL alias = [context shouldAntialias];
251 [context setShouldAntialias:NO]; 215 [context setShouldAntialias:NO];
Nico 2013/03/22 18:46:37 Can you upload a screenshot for this please? Anti
Sergey Ulanov 2013/03/22 19:39:09 Here is a screenshot from mac: http://i.imgur.com/
252 216
253 // Handle bidirectional locales properly. 217 // Handle bidirectional locales properly.
Nico 2013/03/22 18:46:37 Chrome/Mac doesn't handle RTL as far as I know. (m
254 CGFloat inset = [self isRToL] ? NSMaxX(bounds) - kBaseInset - kDragHandleWidth 218 CGFloat inset = base::i18n::IsRTL() ?
255 : kBaseInset; 219 NSMaxX(bounds) - kBaseInset - kDragHandleWidth : kBaseInset;
256 220
257 NSPoint top = NSMakePoint(inset, NSMidY(bounds) - kHeight / 2.0); 221 NSPoint top = NSMakePoint(inset, NSMidY(bounds) - kHeight / 2.0);
258 NSPoint bottom = NSMakePoint(inset, top.y + kHeight); 222 NSPoint bottom = NSMakePoint(inset, top.y + kHeight);
259 223
260 path = [NSBezierPath bezierPath]; 224 path = [NSBezierPath bezierPath];
261 [path moveToPoint:top]; 225 [path moveToPoint:top];
262 [path lineToPoint:bottom]; 226 [path lineToPoint:bottom];
263 [dark setStroke]; 227 [dark setStroke];
264 [path stroke]; 228 [path stroke];
265 229
(...skipping 18 matching lines...) Expand all
284 path = [NSBezierPath bezierPath]; 248 path = [NSBezierPath bezierPath];
285 [path moveToPoint:top]; 249 [path moveToPoint:top];
286 [path lineToPoint:bottom]; 250 [path lineToPoint:bottom];
287 [light setStroke]; 251 [light setStroke];
288 [path stroke]; 252 [path stroke];
289 253
290 [context setShouldAntialias:alias]; 254 [context setShouldAntialias:alias];
291 } 255 }
292 256
293 @end 257 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698