| 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/mac_util.h" | 9 #include "base/mac/mac_util.h" |
| 10 #include "base/mac/scoped_nsobject.h" | 10 #include "base/mac/scoped_nsobject.h" |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 [self closeCleanup]; | 234 [self closeCleanup]; |
| 235 [super close]; | 235 [super close]; |
| 236 } | 236 } |
| 237 | 237 |
| 238 // The controller is the delegate of the window so it receives did resign key | 238 // The controller is the delegate of the window so it receives did resign key |
| 239 // notifications. When key is resigned mirror Windows behavior and close the | 239 // notifications. When key is resigned mirror Windows behavior and close the |
| 240 // window. | 240 // window. |
| 241 - (void)windowDidResignKey:(NSNotification*)notification { | 241 - (void)windowDidResignKey:(NSNotification*)notification { |
| 242 NSWindow* window = [self window]; | 242 NSWindow* window = [self window]; |
| 243 DCHECK_EQ([notification object], window); | 243 DCHECK_EQ([notification object], window); |
| 244 if ([window isVisible] && [self shouldCloseOnResignKey]) { | 244 |
| 245 // If the window isn't visible, it is already closed, and this notification | 245 // If the window isn't visible, it is already closed, and this notification |
| 246 // has been sent as part of the closing operation, so no need to close. | 246 // has been sent as part of the closing operation, so no need to close. |
| 247 if (![window isVisible]) |
| 248 return; |
| 249 |
| 250 // Don't close when explicily disabled, or if there's an attached sheet (e.g. |
| 251 // Open File dialog). |
| 252 if ([self shouldCloseOnResignKey] && ![window attachedSheet]) { |
| 247 [self close]; | 253 [self close]; |
| 248 } else if ([window isVisible]) { | 254 return; |
| 249 // The bubble should not receive key events when it is no longer key window, | |
| 250 // so disable sharing parent key state. Share parent key state is only used | |
| 251 // to enable the close/minimize/maximize buttons of the parent window when | |
| 252 // the bubble has key state, so disabling it here is safe. | |
| 253 InfoBubbleWindow* bubbleWindow = | |
| 254 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); | |
| 255 [bubbleWindow setAllowShareParentKeyState:NO]; | |
| 256 } | 255 } |
| 256 |
| 257 // The bubble should not receive key events when it is no longer key window, |
| 258 // so disable sharing parent key state. Share parent key state is only used |
| 259 // to enable the close/minimize/maximize buttons of the parent window when |
| 260 // the bubble has key state, so disabling it here is safe. |
| 261 InfoBubbleWindow* bubbleWindow = |
| 262 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); |
| 263 [bubbleWindow setAllowShareParentKeyState:NO]; |
| 257 } | 264 } |
| 258 | 265 |
| 259 - (void)windowDidBecomeKey:(NSNotification*)notification { | 266 - (void)windowDidBecomeKey:(NSNotification*)notification { |
| 260 // Re-enable share parent key state to make sure the close/minimize/maximize | 267 // Re-enable share parent key state to make sure the close/minimize/maximize |
| 261 // buttons of the parent window are active. | 268 // buttons of the parent window are active. |
| 262 InfoBubbleWindow* bubbleWindow = | 269 InfoBubbleWindow* bubbleWindow = |
| 263 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); | 270 base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); |
| 264 [bubbleWindow setAllowShareParentKeyState:YES]; | 271 [bubbleWindow setAllowShareParentKeyState:YES]; |
| 265 } | 272 } |
| 266 | 273 |
| 267 // Since the bubble shares first responder with its parent window, set | 274 // Since the bubble shares first responder with its parent window, set event |
| 268 // event handlers to dismiss the bubble when it would normally lose key | 275 // handlers to dismiss the bubble when it would normally lose key state. |
| 269 // state. | 276 // Events on sheets are ignored: this assumes the sheet belongs to the bubble |
| 277 // since, to affect a sheet on a different window, the bubble would also lose |
| 278 // key status in -[NSWindowDelegate windowDidResignKey:]. This keeps the logic |
| 279 // simple, since -[NSWindow attachedSheet] returns nil while the sheet is still |
| 280 // closing. |
| 270 - (void)registerKeyStateEventTap { | 281 - (void)registerKeyStateEventTap { |
| 271 // Parent key state sharing is only avaiable on 10.7+. | 282 // Parent key state sharing is only avaiable on 10.7+. |
| 272 if (!base::mac::IsOSLionOrLater()) | 283 if (!base::mac::IsOSLionOrLater()) |
| 273 return; | 284 return; |
| 274 | 285 |
| 275 NSWindow* window = self.window; | 286 NSWindow* window = self.window; |
| 276 NSNotification* note = | 287 NSNotification* note = |
| 277 [NSNotification notificationWithName:NSWindowDidResignKeyNotification | 288 [NSNotification notificationWithName:NSWindowDidResignKeyNotification |
| 278 object:window]; | 289 object:window]; |
| 279 | 290 |
| 280 // The eventTap_ catches clicks within the application that are outside the | 291 // The eventTap_ catches clicks within the application that are outside the |
| 281 // window. | 292 // window. |
| 282 eventTap_ = [NSEvent | 293 eventTap_ = [NSEvent |
| 283 addLocalMonitorForEventsMatchingMask:NSLeftMouseDownMask | | 294 addLocalMonitorForEventsMatchingMask:NSLeftMouseDownMask | |
| 284 NSRightMouseDownMask | 295 NSRightMouseDownMask |
| 285 handler:^NSEvent* (NSEvent* event) { | 296 handler:^NSEvent* (NSEvent* event) { |
| 286 if (event.window != window) { | 297 if ([event window] != window && ![[event window] isSheet]) { |
| 287 // Do it right now, because if this event is right mouse event, | 298 // Do it right now, because if this event is right mouse event, |
| 288 // it may pop up a menu. windowDidResignKey: will not run until | 299 // it may pop up a menu. windowDidResignKey: will not run until |
| 289 // the menu is closed. | 300 // the menu is closed. |
| 290 if ([self respondsToSelector:@selector(windowDidResignKey:)]) { | 301 if ([self respondsToSelector:@selector(windowDidResignKey:)]) { |
| 291 [self windowDidResignKey:note]; | 302 [self windowDidResignKey:note]; |
| 292 } | 303 } |
| 293 } | 304 } |
| 294 return event; | 305 return event; |
| 295 }]; | 306 }]; |
| 296 | 307 |
| 297 // The resignationObserver_ watches for when a window resigns key state, | 308 // The resignationObserver_ watches for when a window resigns key state, |
| 298 // meaning the key window has changed and the bubble should be dismissed. | 309 // meaning the key window has changed and the bubble should be dismissed. |
| 299 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; | 310 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; |
| 300 resignationObserver_ = | 311 resignationObserver_ = |
| 301 [center addObserverForName:NSWindowDidResignKeyNotification | 312 [center addObserverForName:NSWindowDidResignKeyNotification |
| 302 object:nil | 313 object:nil |
| 303 queue:[NSOperationQueue mainQueue] | 314 queue:[NSOperationQueue mainQueue] |
| 304 usingBlock:^(NSNotification* notif) { | 315 usingBlock:^(NSNotification* notif) { |
| 305 [self windowDidResignKey:note]; | 316 if (![[notif object] isSheet]) |
| 317 [self windowDidResignKey:note]; |
| 306 }]; | 318 }]; |
| 307 } | 319 } |
| 308 | 320 |
| 309 // By implementing this, ESC causes the window to go away. | 321 // By implementing this, ESC causes the window to go away. |
| 310 - (IBAction)cancel:(id)sender { | 322 - (IBAction)cancel:(id)sender { |
| 311 // This is not a "real" cancel as potential changes to the radio group are not | 323 // This is not a "real" cancel as potential changes to the radio group are not |
| 312 // undone. That's ok. | 324 // undone. That's ok. |
| 313 [self close]; | 325 [self close]; |
| 314 } | 326 } |
| 315 | 327 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 | 380 |
| 369 - (void)activateTabWithContents:(content::WebContents*)newContents | 381 - (void)activateTabWithContents:(content::WebContents*)newContents |
| 370 previousContents:(content::WebContents*)oldContents | 382 previousContents:(content::WebContents*)oldContents |
| 371 atIndex:(NSInteger)index | 383 atIndex:(NSInteger)index |
| 372 reason:(int)reason { | 384 reason:(int)reason { |
| 373 // The user switched tabs; close. | 385 // The user switched tabs; close. |
| 374 [self close]; | 386 [self close]; |
| 375 } | 387 } |
| 376 | 388 |
| 377 @end // BaseBubbleController | 389 @end // BaseBubbleController |
| OLD | NEW |