OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/base_bubble_controller.h" | 5 #import "chrome/browser/ui/cocoa/base_bubble_controller.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/mac/bundle_locations.h" | 8 #include "base/mac/bundle_locations.h" |
9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
11 #include "base/mac/scoped_nsobject.h" | 11 #include "base/mac/scoped_nsobject.h" |
12 #include "base/mac/sdk_forward_declarations.h" | 12 #include "base/mac/sdk_forward_declarations.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 14 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
15 #import "chrome/browser/ui/cocoa/info_bubble_view.h" | 15 #import "chrome/browser/ui/cocoa/info_bubble_view.h" |
16 #import "chrome/browser/ui/cocoa/info_bubble_window.h" | 16 #import "chrome/browser/ui/cocoa/info_bubble_window.h" |
17 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" | 17 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" |
| 18 #include "components/bubble/bubble_controller.h" |
18 | 19 |
19 @interface BaseBubbleController (Private) | 20 @interface BaseBubbleController (Private) |
20 - (void)registerForNotifications; | 21 - (void)registerForNotifications; |
21 - (void)updateOriginFromAnchor; | 22 - (void)updateOriginFromAnchor; |
22 - (void)activateTabWithContents:(content::WebContents*)newContents | 23 - (void)activateTabWithContents:(content::WebContents*)newContents |
23 previousContents:(content::WebContents*)oldContents | 24 previousContents:(content::WebContents*)oldContents |
24 atIndex:(NSInteger)index | 25 atIndex:(NSInteger)index |
25 reason:(int)reason; | 26 reason:(int)reason; |
26 - (void)recordAnchorOffset; | 27 - (void)recordAnchorOffset; |
27 - (void)parentWindowDidResize:(NSNotification*)notification; | 28 - (void)parentWindowDidResize:(NSNotification*)notification; |
28 - (void)parentWindowWillClose:(NSNotification*)notification; | 29 - (void)parentWindowWillClose:(NSNotification*)notification; |
29 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification; | 30 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification; |
30 - (void)closeCleanup; | 31 - (void)closeCleanup; |
| 32 |
| 33 // Temporary methods to decide how to close the bubble controller. |
| 34 // TODO(hcarmona): remove these methods when all bubbles use the BubbleManager. |
| 35 // Notify BubbleManager to close a bubble. |
| 36 - (void)closeBubbleWithReason:(BubbleCloseReason)reason; |
| 37 // Will be a no-op in bubble API because this is handled by the BubbleManager. |
| 38 - (void)closeBubble; |
31 @end | 39 @end |
32 | 40 |
33 @implementation BaseBubbleController | 41 @implementation BaseBubbleController |
34 | 42 |
35 @synthesize anchorPoint = anchor_; | 43 @synthesize anchorPoint = anchor_; |
36 @synthesize bubble = bubble_; | 44 @synthesize bubble = bubble_; |
37 @synthesize shouldOpenAsKeyWindow = shouldOpenAsKeyWindow_; | 45 @synthesize shouldOpenAsKeyWindow = shouldOpenAsKeyWindow_; |
38 @synthesize shouldCloseOnResignKey = shouldCloseOnResignKey_; | 46 @synthesize shouldCloseOnResignKey = shouldCloseOnResignKey_; |
| 47 @synthesize bubbleReference = bubbleReference_; |
39 | 48 |
40 - (id)initWithWindowNibPath:(NSString*)nibPath | 49 - (id)initWithWindowNibPath:(NSString*)nibPath |
41 parentWindow:(NSWindow*)parentWindow | 50 parentWindow:(NSWindow*)parentWindow |
42 anchoredAt:(NSPoint)anchoredAt { | 51 anchoredAt:(NSPoint)anchoredAt { |
43 nibPath = [base::mac::FrameworkBundle() pathForResource:nibPath | 52 nibPath = [base::mac::FrameworkBundle() pathForResource:nibPath |
44 ofType:@"nib"]; | 53 ofType:@"nib"]; |
45 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { | 54 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { |
46 [self setParentWindow:parentWindow]; | 55 [self setParentWindow:parentWindow]; |
47 anchor_ = anchoredAt; | 56 anchor_ = anchoredAt; |
48 shouldOpenAsKeyWindow_ = YES; | 57 shouldOpenAsKeyWindow_ = YES; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 DCHECK_EQ(parentWindow_, [notification object]); | 230 DCHECK_EQ(parentWindow_, [notification object]); |
222 NSPoint newOrigin = NSMakePoint(NSMinX([parentWindow_ frame]), | 231 NSPoint newOrigin = NSMakePoint(NSMinX([parentWindow_ frame]), |
223 NSMaxY([parentWindow_ frame])); | 232 NSMaxY([parentWindow_ frame])); |
224 newOrigin.x -= anchorOffset_.x; | 233 newOrigin.x -= anchorOffset_.x; |
225 newOrigin.y -= anchorOffset_.y; | 234 newOrigin.y -= anchorOffset_.y; |
226 [self setAnchorPoint:newOrigin]; | 235 [self setAnchorPoint:newOrigin]; |
227 } | 236 } |
228 | 237 |
229 - (void)parentWindowWillClose:(NSNotification*)notification { | 238 - (void)parentWindowWillClose:(NSNotification*)notification { |
230 [self setParentWindow:nil]; | 239 [self setParentWindow:nil]; |
231 [self close]; | 240 [self closeBubble]; |
232 } | 241 } |
233 | 242 |
234 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification { | 243 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification { |
235 [self setParentWindow:nil]; | 244 [self setParentWindow:nil]; |
236 [self close]; | 245 [self closeBubble]; |
237 } | 246 } |
238 | 247 |
239 - (void)closeCleanup { | 248 - (void)closeCleanup { |
240 if (eventTap_) { | 249 if (eventTap_) { |
241 [NSEvent removeMonitor:eventTap_]; | 250 [NSEvent removeMonitor:eventTap_]; |
242 eventTap_ = nil; | 251 eventTap_ = nil; |
243 } | 252 } |
244 if (resignationObserver_) { | 253 if (resignationObserver_) { |
245 [[NSNotificationCenter defaultCenter] | 254 [[NSNotificationCenter defaultCenter] |
246 removeObserver:resignationObserver_ | 255 removeObserver:resignationObserver_ |
247 name:NSWindowDidResignKeyNotification | 256 name:NSWindowDidResignKeyNotification |
248 object:nil]; | 257 object:nil]; |
249 resignationObserver_ = nil; | 258 resignationObserver_ = nil; |
250 } | 259 } |
251 | 260 |
252 tabStripObserverBridge_.reset(); | 261 tabStripObserverBridge_.reset(); |
253 } | 262 } |
254 | 263 |
| 264 - (void)closeBubbleWithReason:(BubbleCloseReason)reason { |
| 265 if ([self bubbleReference]) |
| 266 [self bubbleReference]->CloseBubble(reason); |
| 267 else |
| 268 [self close]; |
| 269 } |
| 270 |
| 271 - (void)closeBubble { |
| 272 if (![self bubbleReference]) |
| 273 [self close]; |
| 274 } |
| 275 |
255 - (void)windowWillClose:(NSNotification*)notification { | 276 - (void)windowWillClose:(NSNotification*)notification { |
256 [self closeCleanup]; | 277 [self closeCleanup]; |
257 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 278 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
258 [self autorelease]; | 279 [self autorelease]; |
259 } | 280 } |
260 | 281 |
261 // We want this to be a child of a browser window. addChildWindow: | 282 // We want this to be a child of a browser window. addChildWindow: |
262 // (called from this function) will bring the window on-screen; | 283 // (called from this function) will bring the window on-screen; |
263 // unfortunately, [NSWindowController showWindow:] will also bring it | 284 // unfortunately, [NSWindowController showWindow:] will also bring it |
264 // on-screen (but will cause unexpected changes to the window's | 285 // on-screen (but will cause unexpected changes to the window's |
(...skipping 24 matching lines...) Expand all Loading... |
289 DCHECK_EQ([notification object], window); | 310 DCHECK_EQ([notification object], window); |
290 | 311 |
291 // If the window isn't visible, it is already closed, and this notification | 312 // If the window isn't visible, it is already closed, and this notification |
292 // has been sent as part of the closing operation, so no need to close. | 313 // has been sent as part of the closing operation, so no need to close. |
293 if (![window isVisible]) | 314 if (![window isVisible]) |
294 return; | 315 return; |
295 | 316 |
296 // Don't close when explicily disabled, or if there's an attached sheet (e.g. | 317 // Don't close when explicily disabled, or if there's an attached sheet (e.g. |
297 // Open File dialog). | 318 // Open File dialog). |
298 if ([self shouldCloseOnResignKey] && ![window attachedSheet]) { | 319 if ([self shouldCloseOnResignKey] && ![window attachedSheet]) { |
299 [self close]; | 320 [self closeBubbleWithReason:BUBBLE_CLOSE_FOCUS_LOST]; |
300 return; | 321 return; |
301 } | 322 } |
302 | 323 |
303 // The bubble should not receive key events when it is no longer key window, | 324 // The bubble should not receive key events when it is no longer key window, |
304 // so disable sharing parent key state. Share parent key state is only used | 325 // so disable sharing parent key state. Share parent key state is only used |
305 // to enable the close/minimize/maximize buttons of the parent window when | 326 // to enable the close/minimize/maximize buttons of the parent window when |
306 // the bubble has key state, so disabling it here is safe. | 327 // the bubble has key state, so disabling it here is safe. |
307 InfoBubbleWindow* bubbleWindow = | 328 InfoBubbleWindow* bubbleWindow = |
308 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); | 329 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); |
309 [bubbleWindow setAllowShareParentKeyState:NO]; | 330 [bubbleWindow setAllowShareParentKeyState:NO]; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 if (![[notif object] isSheet] && | 383 if (![[notif object] isSheet] && |
363 [NSApp keyWindow] != [self window]) | 384 [NSApp keyWindow] != [self window]) |
364 [self windowDidResignKey:note]; | 385 [self windowDidResignKey:note]; |
365 }]; | 386 }]; |
366 } | 387 } |
367 | 388 |
368 // By implementing this, ESC causes the window to go away. | 389 // By implementing this, ESC causes the window to go away. |
369 - (IBAction)cancel:(id)sender { | 390 - (IBAction)cancel:(id)sender { |
370 // This is not a "real" cancel as potential changes to the radio group are not | 391 // This is not a "real" cancel as potential changes to the radio group are not |
371 // undone. That's ok. | 392 // undone. That's ok. |
372 [self close]; | 393 [self closeBubbleWithReason:BUBBLE_CLOSE_CANCELED]; |
373 } | 394 } |
374 | 395 |
375 // Takes the |anchor_| point and adjusts the window's origin accordingly. | 396 // Takes the |anchor_| point and adjusts the window's origin accordingly. |
376 - (void)updateOriginFromAnchor { | 397 - (void)updateOriginFromAnchor { |
377 NSWindow* window = [self window]; | 398 NSWindow* window = [self window]; |
378 NSPoint origin = anchor_; | 399 NSPoint origin = anchor_; |
379 | 400 |
380 switch ([bubble_ alignment]) { | 401 switch ([bubble_ alignment]) { |
381 case info_bubble::kAlignArrowToAnchor: { | 402 case info_bubble::kAlignArrowToAnchor: { |
382 NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + | 403 NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 443 |
423 origin.y -= NSHeight([window frame]); | 444 origin.y -= NSHeight([window frame]); |
424 [window setFrameOrigin:origin]; | 445 [window setFrameOrigin:origin]; |
425 } | 446 } |
426 | 447 |
427 - (void)activateTabWithContents:(content::WebContents*)newContents | 448 - (void)activateTabWithContents:(content::WebContents*)newContents |
428 previousContents:(content::WebContents*)oldContents | 449 previousContents:(content::WebContents*)oldContents |
429 atIndex:(NSInteger)index | 450 atIndex:(NSInteger)index |
430 reason:(int)reason { | 451 reason:(int)reason { |
431 // The user switched tabs; close. | 452 // The user switched tabs; close. |
432 [self close]; | 453 [self closeBubble]; |
433 } | 454 } |
434 | 455 |
435 @end // BaseBubbleController | 456 @end // BaseBubbleController |
OLD | NEW |