diff options
-rw-r--r-- | apps/DEPS | 2 | ||||
-rw-r--r-- | apps/app_shim/app_shim_host_mac.cc | 20 | ||||
-rw-r--r-- | apps/app_shim/app_shim_host_mac.h | 5 | ||||
-rw-r--r-- | apps/app_shim/app_shim_messages.h | 5 | ||||
-rw-r--r-- | chrome/app/chrome_main_app_mode_mac.mm | 22 | ||||
-rw-r--r-- | ui/base/cocoa/focus_window_set.h | 21 | ||||
-rw-r--r-- | ui/base/cocoa/focus_window_set.mm | 26 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
8 files changed, 102 insertions, 1 deletions
@@ -1,6 +1,7 @@ include_rules = [ "+base", "+content", + "+ui", # Temporary allowed includes. # TODO(benwells): remove these (http://crbug.com/159366) "+chrome/browser/browser_process.h", @@ -8,6 +9,7 @@ include_rules = [ "+chrome/browser/profiles", "+chrome/browser/shell_integration.h", "+chrome/browser/ui/extensions/application_launch.h", + "+chrome/browser/ui/extensions/shell_window.h", "+chrome/browser/ui/host_desktop.h", "+chrome/browser/ui/web_applications/web_app_ui.h", "+chrome/browser/web_applications/web_app.h", diff --git a/apps/app_shim/app_shim_host_mac.cc b/apps/app_shim/app_shim_host_mac.cc index 8cff755..b2d577f 100644 --- a/apps/app_shim/app_shim_host_mac.cc +++ b/apps/app_shim/app_shim_host_mac.cc @@ -15,8 +15,10 @@ #include "chrome/browser/extensions/shell_window_registry.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/browser/ui/extensions/shell_window.h" #include "chrome/common/extensions/extension_constants.h" #include "ipc/ipc_channel_proxy.h" +#include "ui/base/cocoa/focus_window_set.h" AppShimHost::AppShimHost() : channel_(NULL), profile_(NULL) { @@ -38,6 +40,7 @@ bool AppShimHost::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(AppShimHost, message) IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp) + IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -55,6 +58,23 @@ void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) { Send(new AppShimMsg_LaunchApp_Done(success)); } +void AppShimHost::OnFocus() { + DCHECK(CalledOnValidThread()); + if (!profile_) + return; + extensions::ShellWindowRegistry* registry = + extensions::ShellWindowRegistry::Get(profile_); + const std::set<ShellWindow*> windows = + registry->GetShellWindowsForApp(app_id_); + std::set<gfx::NativeWindow> native_windows; + for (std::set<ShellWindow*>::const_iterator i = windows.begin(); + i != windows.end(); + ++i) { + native_windows.insert((*i)->GetNativeWindow()); + } + ui::FocusWindowSet(native_windows); +} + bool AppShimHost::LaunchAppImpl(const std::string& profile_dir, const std::string& app_id) { DCHECK(CalledOnValidThread()); diff --git a/apps/app_shim/app_shim_host_mac.h b/apps/app_shim/app_shim_host_mac.h index 8ebc0cd..fbfd0fa 100644 --- a/apps/app_shim/app_shim_host_mac.h +++ b/apps/app_shim/app_shim_host_mac.h @@ -60,6 +60,11 @@ class AppShimHost : public IPC::Listener, // app shim to send multiple launch messages. void OnLaunchApp(std::string profile, std::string app_id); + // Called when the app shim process notifies that the app should be brought + // to the front (i.e. the user has clicked on the app's icon in the dock or + // Cmd+Tabbed to it.) + void OnFocus(); + bool LaunchAppImpl(const std::string& profile_dir, const std::string& app_id); // The AppShimHost listens to the NOTIFICATION_EXTENSION_HOST_DESTROYED diff --git a/apps/app_shim/app_shim_messages.h b/apps/app_shim/app_shim_messages.h index 1e49ce4..6a6cc6d 100644 --- a/apps/app_shim/app_shim_messages.h +++ b/apps/app_shim/app_shim_messages.h @@ -20,3 +20,8 @@ IPC_MESSAGE_CONTROL1(AppShimMsg_LaunchApp_Done, IPC_MESSAGE_CONTROL2(AppShimHostMsg_LaunchApp, std::string /* profile name */, std::string /* app id */) + +// Sent when the user has indicated a desire to focus the app, either by +// clicking on the app's icon in the dock or by selecting it with Cmd+Tab. In +// response, Chrome brings the app's windows to the foreground. +IPC_MESSAGE_CONTROL0(AppShimHostMsg_FocusApp) diff --git a/chrome/app/chrome_main_app_mode_mac.mm b/chrome/app/chrome_main_app_mode_mac.mm index a75f38d..513aad2 100644 --- a/chrome/app/chrome_main_app_mode_mac.mm +++ b/chrome/app/chrome_main_app_mode_mac.mm @@ -51,6 +51,10 @@ class AppShimController : public IPC::Listener { // shim process should die. void OnLaunchAppDone(bool success); + // Called when the app is activated, either by the user clicking on it in the + // dock or by Cmd+Tabbing to it. + void OnDidActivateApplication(); + // Quits the app shim process. void Quit(); @@ -95,14 +99,30 @@ void AppShimController::OnChannelError() { } void AppShimController::OnLaunchAppDone(bool success) { - if (!success) + if (!success) { Quit(); + return; + } + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserverForName:NSWorkspaceDidActivateApplicationNotification + object:nil + queue:nil + usingBlock:^(NSNotification* notification) { + NSRunningApplication* activated_app = + [[notification userInfo] objectForKey:NSWorkspaceApplicationKey]; + if ([activated_app isEqual:[NSRunningApplication currentApplication]]) + OnDidActivateApplication(); + }]; } void AppShimController::Quit() { [NSApp terminate:nil]; } +void AppShimController::OnDidActivateApplication() { + channel_->Send(new AppShimHostMsg_FocusApp); +} + //----------------------------------------------------------------------------- // A ReplyEventHandler is a helper class to send an Apple Event to a process diff --git a/ui/base/cocoa/focus_window_set.h b/ui/base/cocoa/focus_window_set.h new file mode 100644 index 0000000..f414c8a --- /dev/null +++ b/ui/base/cocoa/focus_window_set.h @@ -0,0 +1,21 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_COCOA_FOCUS_WINDOW_SET_H_ +#define UI_BASE_COCOA_FOCUS_WINDOW_SET_H_ + +#include <set> + +#include "ui/base/ui_export.h" +#include "ui/gfx/native_widget_types.h" + +namespace ui { + +// Brings a group of windows to the front without changing their order, and +// makes the frontmost one key and main. +UI_EXPORT void FocusWindowSet(std::set<gfx::NativeWindow> windows); + +} // namespace ui + +#endif // UI_BASE_COCOA_FOCUS_WINDOW_SET_H_ diff --git a/ui/base/cocoa/focus_window_set.mm b/ui/base/cocoa/focus_window_set.mm new file mode 100644 index 0000000..c2b6560 --- /dev/null +++ b/ui/base/cocoa/focus_window_set.mm @@ -0,0 +1,26 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +#include "ui/base/cocoa/focus_window_set.h" + +namespace ui { + +void FocusWindowSet(std::set<NSWindow*> windows) { + NSArray* ordered_windows = [NSApp orderedWindows]; + [NSApp activateIgnoringOtherApps:YES]; + NSWindow* frontmost_window = nil; + for (int i = [ordered_windows count] - 1; i >= 0; i--) { + NSWindow* win = [ordered_windows objectAtIndex:i]; + if (windows.find(win) != windows.end()) { + [win orderFront:nil]; + frontmost_window = win; + } + } + [frontmost_window makeMainWindow]; + [frontmost_window makeKeyWindow]; +} + +} // namespace ui @@ -96,6 +96,8 @@ 'base/cocoa/find_pasteboard.mm', 'base/cocoa/focus_tracker.h', 'base/cocoa/focus_tracker.mm', + 'base/cocoa/focus_window_set.h', + 'base/cocoa/focus_window_set.mm', 'base/cocoa/fullscreen_window_manager.h', 'base/cocoa/fullscreen_window_manager.mm', 'base/cocoa/nib_loading.h', |