summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/DEPS2
-rw-r--r--apps/app_shim/app_shim_host_mac.cc20
-rw-r--r--apps/app_shim/app_shim_host_mac.h5
-rw-r--r--apps/app_shim/app_shim_messages.h5
-rw-r--r--chrome/app/chrome_main_app_mode_mac.mm22
-rw-r--r--ui/base/cocoa/focus_window_set.h21
-rw-r--r--ui/base/cocoa/focus_window_set.mm26
-rw-r--r--ui/ui.gyp2
8 files changed, 102 insertions, 1 deletions
diff --git a/apps/DEPS b/apps/DEPS
index d328be8..df03f2b 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -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
diff --git a/ui/ui.gyp b/ui/ui.gyp
index b45ce06..0801604 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -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',