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 |