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/app_controller_mac.h" | 5 #import "chrome/browser/app_controller_mac.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // the 10.5 SDK. | 82 // the 10.5 SDK. |
83 #if !defined(MAC_OS_X_VERSION_10_6) || \ | 83 #if !defined(MAC_OS_X_VERSION_10_6) || \ |
84 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 | 84 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 |
85 @interface NSApplication (SnowLeopardSDKDeclarations) | 85 @interface NSApplication (SnowLeopardSDKDeclarations) |
86 - (void)setHelpMenu:(NSMenu*)helpMenu; | 86 - (void)setHelpMenu:(NSMenu*)helpMenu; |
87 @end | 87 @end |
88 #endif | 88 #endif |
89 | 89 |
90 namespace { | 90 namespace { |
91 | 91 |
| 92 // Declare notification names from the 10.7 SDK. |
| 93 #if !defined(MAC_OS_X_VERSION_10_7) || \ |
| 94 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
| 95 NSString* NSPopoverDidShowNotification = @"NSPopoverDidShowNotification"; |
| 96 NSString* NSPopoverDidCloseNotification = @"NSPopoverDidCloseNotification"; |
| 97 #endif |
| 98 |
92 // True while AppController is calling Browser::OpenEmptyWindow(). We need a | 99 // True while AppController is calling Browser::OpenEmptyWindow(). We need a |
93 // global flag here, analogue to BrowserInit::InProcessStartup() because | 100 // global flag here, analogue to BrowserInit::InProcessStartup() because |
94 // otherwise the SessionService will try to restore sessions when we make a new | 101 // otherwise the SessionService will try to restore sessions when we make a new |
95 // window while there are no other active windows. | 102 // window while there are no other active windows. |
96 bool g_is_opening_new_window = false; | 103 bool g_is_opening_new_window = false; |
97 | 104 |
98 // Activates a browser window having the given profile (the last one active) if | 105 // Activates a browser window having the given profile (the last one active) if |
99 // possible and returns a pointer to the activate |Browser| or NULL if this was | 106 // possible and returns a pointer to the activate |Browser| or NULL if this was |
100 // not possible. If the last active browser is minimized (in particular, if | 107 // not possible. If the last active browser is minimized (in particular, if |
101 // there are only minimized windows), it will unminimize it. | 108 // there are only minimized windows), it will unminimize it. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 @end | 192 @end |
186 | 193 |
187 @implementation AppController | 194 @implementation AppController |
188 | 195 |
189 @synthesize startupComplete = startupComplete_; | 196 @synthesize startupComplete = startupComplete_; |
190 | 197 |
191 // This method is called very early in application startup (ie, before | 198 // This method is called very early in application startup (ie, before |
192 // the profile is loaded or any preferences have been registered). Defer any | 199 // the profile is loaded or any preferences have been registered). Defer any |
193 // user-data initialization until -applicationDidFinishLaunching:. | 200 // user-data initialization until -applicationDidFinishLaunching:. |
194 - (void)awakeFromNib { | 201 - (void)awakeFromNib { |
195 } | |
196 | |
197 // This method is called very early in application startup (ie, before | |
198 // the profile is loaded or any preferences have been registered), just | |
199 // after -awakeFromNib. This is separate from -awakeFromNib: so that | |
200 // test code can load nibs without these side effects. | |
201 - (void)registerEventHandlersAndInitialize { | |
202 // We need to register the handlers early to catch events fired on launch. | 202 // We need to register the handlers early to catch events fired on launch. |
203 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 203 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
204 [em setEventHandler:self | 204 [em setEventHandler:self |
205 andSelector:@selector(getUrl:withReply:) | 205 andSelector:@selector(getUrl:withReply:) |
206 forEventClass:kInternetEventClass | 206 forEventClass:kInternetEventClass |
207 andEventID:kAEGetURL]; | 207 andEventID:kAEGetURL]; |
208 [em setEventHandler:self | 208 [em setEventHandler:self |
209 andSelector:@selector(submitCloudPrintJob:) | 209 andSelector:@selector(submitCloudPrintJob:) |
210 forEventClass:cloud_print::kAECloudPrintClass | 210 forEventClass:cloud_print::kAECloudPrintClass |
211 andEventID:cloud_print::kAECloudPrintClass]; | 211 andEventID:cloud_print::kAECloudPrintClass]; |
(...skipping 30 matching lines...) Expand all Loading... |
242 addObserver:self | 242 addObserver:self |
243 selector:@selector(windowLayeringDidChange:) | 243 selector:@selector(windowLayeringDidChange:) |
244 name:NSWindowDidBecomeMainNotification | 244 name:NSWindowDidBecomeMainNotification |
245 object:nil]; | 245 object:nil]; |
246 [notificationCenter | 246 [notificationCenter |
247 addObserver:self | 247 addObserver:self |
248 selector:@selector(windowLayeringDidChange:) | 248 selector:@selector(windowLayeringDidChange:) |
249 name:NSWindowDidResignMainNotification | 249 name:NSWindowDidResignMainNotification |
250 object:nil]; | 250 object:nil]; |
251 | 251 |
| 252 if (base::mac::IsOSLionOrLater()) { |
| 253 [notificationCenter |
| 254 addObserver:self |
| 255 selector:@selector(popoverDidShow:) |
| 256 name:NSPopoverDidShowNotification |
| 257 object:nil]; |
| 258 [notificationCenter |
| 259 addObserver:self |
| 260 selector:@selector(popoverDidClose:) |
| 261 name:NSPopoverDidCloseNotification |
| 262 object:nil]; |
| 263 } |
| 264 |
252 // Set up the command updater for when there are no windows open | 265 // Set up the command updater for when there are no windows open |
253 [self initMenuState]; | 266 [self initMenuState]; |
254 | 267 |
255 // Initialize the Profile menu. | 268 // Initialize the Profile menu. |
256 [self initProfileMenu]; | 269 [self initProfileMenu]; |
257 } | 270 } |
258 | 271 |
259 - (void)unregisterEventHandlers { | 272 - (void)unregisterEventHandlers { |
260 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; | 273 NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
261 [em removeEventHandlerForEventClass:kInternetEventClass | 274 [em removeEventHandlerForEventClass:kInternetEventClass |
262 andEventID:kAEGetURL]; | 275 andEventID:kAEGetURL]; |
263 [em removeEventHandlerForEventClass:cloud_print::kAECloudPrintClass | 276 [em removeEventHandlerForEventClass:cloud_print::kAECloudPrintClass |
264 andEventID:cloud_print::kAECloudPrintClass]; | 277 andEventID:cloud_print::kAECloudPrintClass]; |
265 [em removeEventHandlerForEventClass:kAECloudPrintInstallClass | 278 [em removeEventHandlerForEventClass:kAECloudPrintInstallClass |
266 andEventID:kAECloudPrintInstallClass]; | 279 andEventID:kAECloudPrintInstallClass]; |
267 [em removeEventHandlerForEventClass:kAECloudPrintUninstallClass | 280 [em removeEventHandlerForEventClass:kAECloudPrintUninstallClass |
268 andEventID:kAECloudPrintUninstallClass]; | 281 andEventID:kAECloudPrintUninstallClass]; |
269 [em removeEventHandlerForEventClass:'WWW!' | 282 [em removeEventHandlerForEventClass:'WWW!' |
270 andEventID:'OURL']; | 283 andEventID:'OURL']; |
271 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 284 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
272 } | 285 } |
273 | 286 |
274 - (void)dealloc { | |
275 if ([NSApp delegate] == self) | |
276 [NSApp setDelegate:nil]; | |
277 [super dealloc]; | |
278 } | |
279 | |
280 // (NSApplicationDelegate protocol) This is the Apple-approved place to override | 287 // (NSApplicationDelegate protocol) This is the Apple-approved place to override |
281 // the default handlers. | 288 // the default handlers. |
282 - (void)applicationWillFinishLaunching:(NSNotification*)notification { | 289 - (void)applicationWillFinishLaunching:(NSNotification*)notification { |
283 // Nothing here right now. | 290 // Nothing here right now. |
284 } | 291 } |
285 | 292 |
286 - (BOOL)tryToTerminateApplication:(NSApplication*)app { | 293 - (BOOL)tryToTerminateApplication:(NSApplication*)app { |
287 // Check for in-process downloads, and prompt the user if they really want | 294 // Check for in-process downloads, and prompt the user if they really want |
288 // to quit (and thus cancel downloads). Only check if we're not already | 295 // to quit (and thus cancel downloads). Only check if we're not already |
289 // shutting down, else the user might be prompted multiple times if the | 296 // shutting down, else the user might be prompted multiple times if the |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 // proper shutdown. If we don't do this, Chrome won't shut down cleanly, | 377 // proper shutdown. If we don't do this, Chrome won't shut down cleanly, |
371 // and may end up crashing when some thread tries to use the IO thread (or | 378 // and may end up crashing when some thread tries to use the IO thread (or |
372 // another thread) that is no longer valid. | 379 // another thread) that is no longer valid. |
373 TabRestoreServiceFactory::ResetForProfile([self lastProfile]); | 380 TabRestoreServiceFactory::ResetForProfile([self lastProfile]); |
374 } | 381 } |
375 } | 382 } |
376 | 383 |
377 // If the window has a tab controller, make "close window" be cmd-shift-w, | 384 // If the window has a tab controller, make "close window" be cmd-shift-w, |
378 // otherwise leave it as the normal cmd-w. Capitalization of the key equivalent | 385 // otherwise leave it as the normal cmd-w. Capitalization of the key equivalent |
379 // affects whether the shift modifer is used. | 386 // affects whether the shift modifer is used. |
380 - (void)adjustCloseWindowMenuItemKeyEquivalent:(BOOL)hasTabs { | 387 - (void)adjustCloseWindowMenuItemKeyEquivalent:(BOOL)enableCloseTabShortcut { |
381 [closeWindowMenuItem_ setKeyEquivalent:(hasTabs ? @"W" : @"w")]; | 388 [closeWindowMenuItem_ setKeyEquivalent:(enableCloseTabShortcut ? @"W" : |
| 389 @"w")]; |
382 [closeWindowMenuItem_ setKeyEquivalentModifierMask:NSCommandKeyMask]; | 390 [closeWindowMenuItem_ setKeyEquivalentModifierMask:NSCommandKeyMask]; |
383 } | 391 } |
384 | 392 |
385 // If the window has a tab controller, make "close tab" take over cmd-w, | 393 // If the window has a tab controller, make "close tab" take over cmd-w, |
386 // otherwise it shouldn't have any key-equivalent because it should be disabled. | 394 // otherwise it shouldn't have any key-equivalent because it should be disabled. |
387 - (void)adjustCloseTabMenuItemKeyEquivalent:(BOOL)hasTabs { | 395 - (void)adjustCloseTabMenuItemKeyEquivalent:(BOOL)enableCloseTabShortcut { |
388 if (hasTabs) { | 396 if (enableCloseTabShortcut) { |
389 [closeTabMenuItem_ setKeyEquivalent:@"w"]; | 397 [closeTabMenuItem_ setKeyEquivalent:@"w"]; |
390 [closeTabMenuItem_ setKeyEquivalentModifierMask:NSCommandKeyMask]; | 398 [closeTabMenuItem_ setKeyEquivalentModifierMask:NSCommandKeyMask]; |
391 } else { | 399 } else { |
392 [closeTabMenuItem_ setKeyEquivalent:@""]; | 400 [closeTabMenuItem_ setKeyEquivalent:@""]; |
393 [closeTabMenuItem_ setKeyEquivalentModifierMask:0]; | 401 [closeTabMenuItem_ setKeyEquivalentModifierMask:0]; |
394 } | 402 } |
395 } | 403 } |
396 | 404 |
397 // Explicitly remove any command-key equivalents from the close tab/window | 405 // Explicitly remove any command-key equivalents from the close tab/window |
398 // menus so that nothing can go haywire if we get a user action during pending | 406 // menus so that nothing can go haywire if we get a user action during pending |
(...skipping 17 matching lines...) Expand all Loading... |
416 // window should be the one that handles the close menu item action. | 424 // window should be the one that handles the close menu item action. |
417 // Also, there might be a small amount of time where there is no key window; | 425 // Also, there might be a small amount of time where there is no key window; |
418 // in that case as well, just use our main browser window if there is one. | 426 // in that case as well, just use our main browser window if there is one. |
419 // You might think that we should just always use the main window, but the | 427 // You might think that we should just always use the main window, but the |
420 // "About Chrome" window serves as a counterexample. | 428 // "About Chrome" window serves as a counterexample. |
421 window = mainWindow; | 429 window = mainWindow; |
422 } | 430 } |
423 | 431 |
424 BOOL hasTabs = | 432 BOOL hasTabs = |
425 [[window windowController] isKindOfClass:[TabWindowController class]]; | 433 [[window windowController] isKindOfClass:[TabWindowController class]]; |
426 [self adjustCloseWindowMenuItemKeyEquivalent:hasTabs]; | 434 BOOL enableCloseTabShortcut = hasTabs && !hasPopover_; |
427 [self adjustCloseTabMenuItemKeyEquivalent:hasTabs]; | 435 [self adjustCloseWindowMenuItemKeyEquivalent:enableCloseTabShortcut]; |
| 436 [self adjustCloseTabMenuItemKeyEquivalent:enableCloseTabShortcut]; |
428 } | 437 } |
429 | 438 |
430 // Fix up the "close tab/close window" command-key equivalents. We do this | 439 // Fix up the "close tab/close window" command-key equivalents. We do this |
431 // after a delay to ensure that window layer state has been set by the time | 440 // after a delay to ensure that window layer state has been set by the time |
432 // we do the enabling. This should only be called on the main thread, code that | 441 // we do the enabling. This should only be called on the main thread, code that |
433 // calls this (even as a side-effect) from other threads needs to be fixed. | 442 // calls this (even as a side-effect) from other threads needs to be fixed. |
434 - (void)delayedFixCloseMenuItemKeyEquivalents { | 443 - (void)delayedFixCloseMenuItemKeyEquivalents { |
435 DCHECK([NSThread isMainThread]); | 444 DCHECK([NSThread isMainThread]); |
436 if (!fileMenuUpdatePending_) { | 445 if (!fileMenuUpdatePending_) { |
437 // The OS prefers keypresses to timers, so it's possible that a cmd-w | 446 // The OS prefers keypresses to timers, so it's possible that a cmd-w |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 [windowController isKindOfClass:[BrowserWindowController class]]) { | 489 [windowController isKindOfClass:[BrowserWindowController class]]) { |
481 // If the profile is incognito, use the original profile. | 490 // If the profile is incognito, use the original profile. |
482 Profile* newProfile = [windowController profile]->GetOriginalProfile(); | 491 Profile* newProfile = [windowController profile]->GetOriginalProfile(); |
483 [self windowChangedToProfile:newProfile]; | 492 [self windowChangedToProfile:newProfile]; |
484 } else if (BrowserList::empty()) { | 493 } else if (BrowserList::empty()) { |
485 [self windowChangedToProfile: | 494 [self windowChangedToProfile: |
486 g_browser_process->profile_manager()->GetLastUsedProfile()]; | 495 g_browser_process->profile_manager()->GetLastUsedProfile()]; |
487 } | 496 } |
488 } | 497 } |
489 | 498 |
| 499 // Called on Lion and later when a popover (e.g. dictionary) is shown. |
| 500 - (void)popoverDidShow:(NSNotification*)notify { |
| 501 hasPopover_ = YES; |
| 502 [self fixCloseMenuItemKeyEquivalents]; |
| 503 } |
| 504 |
| 505 // Called on Lion and later when a popover (e.g. dictionary) is closed. |
| 506 - (void)popoverDidClose:(NSNotification*)notify { |
| 507 hasPopover_ = NO; |
| 508 [self fixCloseMenuItemKeyEquivalents]; |
| 509 } |
| 510 |
490 // Called when the user has changed browser windows, meaning the backing profile | 511 // Called when the user has changed browser windows, meaning the backing profile |
491 // may have changed. This can cause a rebuild of the user-data menus. This is a | 512 // may have changed. This can cause a rebuild of the user-data menus. This is a |
492 // no-op if the new profile is the same as the current one. This will always be | 513 // no-op if the new profile is the same as the current one. This will always be |
493 // the original profile and never incognito. | 514 // the original profile and never incognito. |
494 - (void)windowChangedToProfile:(Profile*)profile { | 515 - (void)windowChangedToProfile:(Profile*)profile { |
495 if (lastProfile_ == profile) | 516 if (lastProfile_ == profile) |
496 return; | 517 return; |
497 | 518 |
498 // Before tearing down the menu controller bridges, return the Cocoa menus to | 519 // Before tearing down the menu controller bridges, return the Cocoa menus to |
499 // their initial state. | 520 // their initial state. |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 std::vector<GURL> gurlVector; | 1123 std::vector<GURL> gurlVector; |
1103 gurlVector.push_back(gurl); | 1124 gurlVector.push_back(gurl); |
1104 | 1125 |
1105 [self openUrls:gurlVector]; | 1126 [self openUrls:gurlVector]; |
1106 } | 1127 } |
1107 | 1128 |
1108 // Apple Event handler that receives print event from service | 1129 // Apple Event handler that receives print event from service |
1109 // process, gets the required data and launches Print dialog. | 1130 // process, gets the required data and launches Print dialog. |
1110 - (void)submitCloudPrintJob:(NSAppleEventDescriptor*)event { | 1131 - (void)submitCloudPrintJob:(NSAppleEventDescriptor*)event { |
1111 // Pull parameter list out of Apple Event. | 1132 // Pull parameter list out of Apple Event. |
1112 NSAppleEventDescriptor *paramList = | 1133 NSAppleEventDescriptor* paramList = |
1113 [event paramDescriptorForKeyword:cloud_print::kAECloudPrintClass]; | 1134 [event paramDescriptorForKeyword:cloud_print::kAECloudPrintClass]; |
1114 | 1135 |
1115 if (paramList != nil) { | 1136 if (paramList != nil) { |
1116 // Pull required fields out of parameter list. | 1137 // Pull required fields out of parameter list. |
1117 NSString* mime = [[paramList descriptorAtIndex:1] stringValue]; | 1138 NSString* mime = [[paramList descriptorAtIndex:1] stringValue]; |
1118 NSString* inputPath = [[paramList descriptorAtIndex:2] stringValue]; | 1139 NSString* inputPath = [[paramList descriptorAtIndex:2] stringValue]; |
1119 NSString* printTitle = [[paramList descriptorAtIndex:3] stringValue]; | 1140 NSString* printTitle = [[paramList descriptorAtIndex:3] stringValue]; |
1120 NSString* printTicket = [[paramList descriptorAtIndex:4] stringValue]; | 1141 NSString* printTicket = [[paramList descriptorAtIndex:4] stringValue]; |
1121 // Convert the title to UTF 16 as required. | 1142 // Convert the title to UTF 16 as required. |
1122 string16 title16 = base::SysNSStringToUTF16(printTitle); | 1143 string16 title16 = base::SysNSStringToUTF16(printTitle); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 } | 1296 } |
1276 | 1297 |
1277 - (void)clearStartupUrls { | 1298 - (void)clearStartupUrls { |
1278 startupUrls_.clear(); | 1299 startupUrls_.clear(); |
1279 } | 1300 } |
1280 | 1301 |
1281 - (BookmarkMenuBridge*)bookmarkMenuBridge { | 1302 - (BookmarkMenuBridge*)bookmarkMenuBridge { |
1282 return bookmarkMenuBridge_.get(); | 1303 return bookmarkMenuBridge_.get(); |
1283 } | 1304 } |
1284 | 1305 |
1285 - (void)applicationDidChangeScreenParameters:(NSNotification *)notification { | 1306 - (void)applicationDidChangeScreenParameters:(NSNotification*)notification { |
1286 // During this callback the working area is not always already updated. Defer. | 1307 // During this callback the working area is not always already updated. Defer. |
1287 [self performSelector:@selector(delayedPanelManagerScreenParametersUpdate) | 1308 [self performSelector:@selector(delayedPanelManagerScreenParametersUpdate) |
1288 withObject:nil | 1309 withObject:nil |
1289 afterDelay:0]; | 1310 afterDelay:0]; |
1290 } | 1311 } |
1291 | 1312 |
1292 - (void)delayedPanelManagerScreenParametersUpdate { | 1313 - (void)delayedPanelManagerScreenParametersUpdate { |
1293 PanelManager::GetInstance()->OnDisplayChanged(); | 1314 PanelManager::GetInstance()->OnDisplayChanged(); |
1294 } | 1315 } |
1295 | 1316 |
(...skipping 13 matching lines...) Expand all Loading... |
1309 | 1330 |
1310 } // namespace browser | 1331 } // namespace browser |
1311 | 1332 |
1312 namespace app_controller_mac { | 1333 namespace app_controller_mac { |
1313 | 1334 |
1314 bool IsOpeningNewWindow() { | 1335 bool IsOpeningNewWindow() { |
1315 return g_is_opening_new_window; | 1336 return g_is_opening_new_window; |
1316 } | 1337 } |
1317 | 1338 |
1318 } // namespace app_controller_mac | 1339 } // namespace app_controller_mac |
OLD | NEW |