summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 03:04:54 +0000
committerjeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-19 03:04:54 +0000
commit433739c4481fee1967d815207863a9a06fd18db2 (patch)
tree3125aac15a5d07a4eefeb22b78949a1e0d6da2f8
parent54f4375a328737e904ea36aa65d7e892e4129ddc (diff)
downloadchromium_src-433739c4481fee1967d815207863a9a06fd18db2.zip
chromium_src-433739c4481fee1967d815207863a9a06fd18db2.tar.gz
chromium_src-433739c4481fee1967d815207863a9a06fd18db2.tar.bz2
Giving focus to an app shim brings windows belonging to that app to the foreground.
When the user either clicks on the app shim's icon in the dock or selects it with Cmd+Tab, we send a message to Chrome to ask it to bring that app's windows to the front. BUG=138733, 168080 Review URL: https://codereview.chromium.org/12723011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188926 0039d316-1c4b-4281-b951-d872f2087c98
-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',