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
This commit is contained in:
apps
chrome/app
ui
@ -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",
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
21
ui/base/cocoa/focus_window_set.h
Normal file
21
ui/base/cocoa/focus_window_set.h
Normal file
@ -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_
|
26
ui/base/cocoa/focus_window_set.mm
Normal file
26
ui/base/cocoa/focus_window_set.mm
Normal file
@ -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',
|
||||
|
Reference in New Issue
Block a user