Index: chrome/browser/ui/app_list/app_list_service_mac.mm |
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm |
index f81978247d1fefd8e287e960472727558e5b3894..217f2ac706dc8b531a5adb038cecbf45b474aa0c 100644 |
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm |
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm |
@@ -2,18 +2,18 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#import "chrome/browser/ui/app_list/app_list_service_mac.h" |
+ |
#include <ApplicationServices/ApplicationServices.h> |
#import <Cocoa/Cocoa.h> |
#include "apps/app_launcher.h" |
-#include "apps/app_shim/app_shim_handler_mac.h" |
#include "apps/app_shim/app_shim_mac.h" |
#include "apps/pref_names.h" |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/file_util.h" |
#include "base/lazy_instance.h" |
-#include "base/mac/scoped_nsobject.h" |
#include "base/memory/singleton.h" |
#include "base/message_loop/message_loop.h" |
#include "chrome/browser/browser_process.h" |
@@ -77,55 +77,6 @@ const NSTimeInterval kAnimationDuration = 0.2; |
// Distance towards the screen edge that the app list moves from when showing. |
const CGFloat kDistanceMovedOnShow = 20; |
-// AppListServiceMac manages global resources needed for the app list to |
-// operate, and controls when the app list is opened and closed. |
-class AppListServiceMac : public AppListServiceImpl, |
- public apps::AppShimHandler { |
- public: |
- virtual ~AppListServiceMac(); |
- |
- static AppListServiceMac* GetInstance() { |
- return Singleton<AppListServiceMac, |
- LeakySingletonTraits<AppListServiceMac> >::get(); |
- } |
- |
- void ShowWindowNearDock(); |
- |
- // AppListService overrides: |
- virtual void Init(Profile* initial_profile) OVERRIDE; |
- virtual void CreateForProfile(Profile* requested_profile) OVERRIDE; |
- virtual void ShowForProfile(Profile* requested_profile) OVERRIDE; |
- virtual void DismissAppList() OVERRIDE; |
- virtual bool IsAppListVisible() const OVERRIDE; |
- virtual gfx::NativeWindow GetAppListWindow() OVERRIDE; |
- virtual AppListControllerDelegate* CreateControllerDelegate() OVERRIDE; |
- |
- // AppListServiceImpl overrides: |
- virtual void CreateShortcut() OVERRIDE; |
- |
- // AppShimHandler overrides: |
- virtual void OnShimLaunch(apps::AppShimHandler::Host* host, |
- apps::AppShimLaunchType launch_type) OVERRIDE; |
- virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE; |
- virtual void OnShimFocus(apps::AppShimHandler::Host* host, |
- apps::AppShimFocusType focus_type) OVERRIDE; |
- virtual void OnShimSetHidden(apps::AppShimHandler::Host* host, |
- bool hidden) OVERRIDE; |
- virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE; |
- |
- private: |
- friend struct DefaultSingletonTraits<AppListServiceMac>; |
- |
- AppListServiceMac(); |
- |
- base::scoped_nsobject<AppListWindowController> window_controller_; |
- base::scoped_nsobject<AppListAnimationController> animation_controller_; |
- base::scoped_nsobject<NSRunningApplication> previously_active_application_; |
- NSPoint last_start_origin_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AppListServiceMac); |
-}; |
- |
class AppListControllerDelegateCocoa : public AppListControllerDelegate { |
public: |
AppListControllerDelegateCocoa(); |
@@ -317,12 +268,137 @@ void AppListControllerDelegateCocoa::LaunchApp( |
profile, extension, NEW_FOREGROUND_TAB)); |
} |
+enum DockLocation { |
+ DockLocationOtherDisplay, |
+ DockLocationBottom, |
+ DockLocationLeft, |
+ DockLocationRight, |
+}; |
+ |
+DockLocation DockLocationInDisplay(const gfx::Display& display) { |
+ // Assume the dock occupies part of the work area either on the left, right or |
+ // bottom of the display. Note in the autohide case, it is always 4 pixels. |
+ const gfx::Rect work_area = display.work_area(); |
+ const gfx::Rect display_bounds = display.bounds(); |
+ if (work_area.bottom() != display_bounds.bottom()) |
+ return DockLocationBottom; |
+ |
+ if (work_area.x() != display_bounds.x()) |
+ return DockLocationLeft; |
+ |
+ if (work_area.right() != display_bounds.right()) |
+ return DockLocationRight; |
+ |
+ return DockLocationOtherDisplay; |
+} |
+ |
+// If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock), |
+// adjust |anchor| away from the edge by a constant amount to reduce overlap and |
+// ensure the dock icon can still be clicked to dismiss the app list. |
+int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) { |
+ const int kAutohideDockThreshold = 10; |
+ const int kExtraDistance = 50; // A dock with 40 items is about this size. |
+ if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold) |
+ return anchor; |
+ |
+ return anchor + |
+ (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance); |
+} |
+ |
+void GetAppListWindowOrigins( |
+ NSWindow* window, NSPoint* target_origin, NSPoint* start_origin) { |
+ gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]); |
+ // Ensure y coordinates are flipped back into AppKit's coordinate system. |
+ const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]); |
+ if (!CGCursorIsVisible()) { |
+ // If Chrome is the active application, display on the same display as |
+ // Chrome's keyWindow since this will catch activations triggered, e.g, via |
+ // WebStore install. If another application is active, OSX doesn't provide a |
+ // reliable way to get the display in use. Fall back to the primary display |
+ // since it has the menu bar and is likely to be correct, e.g., for |
+ // activations from Spotlight. |
+ const gfx::NativeView key_view = [[NSApp keyWindow] contentView]; |
+ const gfx::Rect work_area = key_view && [NSApp isActive] ? |
+ screen->GetDisplayNearestWindow(key_view).work_area() : |
+ screen->GetPrimaryDisplay().work_area(); |
+ *target_origin = NSMakePoint(work_area.x(), max_y - work_area.bottom()); |
+ *start_origin = *target_origin; |
+ return; |
+ } |
+ |
+ gfx::Point anchor = screen->GetCursorScreenPoint(); |
+ const gfx::Display display = screen->GetDisplayNearestPoint(anchor); |
+ const DockLocation dock_location = DockLocationInDisplay(display); |
+ const gfx::Rect display_bounds = display.bounds(); |
+ |
+ if (dock_location == DockLocationOtherDisplay) { |
+ // Just display at the bottom-left of the display the cursor is on. |
+ *target_origin = NSMakePoint(display_bounds.x(), |
+ max_y - display_bounds.bottom()); |
+ *start_origin = *target_origin; |
+ return; |
+ } |
+ |
+ // Anchor the center of the window in a region that prevents the window |
+ // showing outside of the work area. |
+ const NSSize window_size = [window frame].size; |
+ const gfx::Rect work_area = display.work_area(); |
+ gfx::Rect anchor_area = work_area; |
+ anchor_area.Inset(window_size.width / 2, window_size.height / 2); |
+ anchor.SetToMax(anchor_area.origin()); |
+ anchor.SetToMin(anchor_area.bottom_right()); |
+ |
+ // Move anchor to the dock, keeping the other axis aligned with the cursor. |
+ switch (dock_location) { |
+ case DockLocationBottom: |
+ anchor.set_y(AdjustPointForDynamicDock( |
+ anchor_area.bottom(), display_bounds.bottom(), work_area.bottom())); |
+ break; |
+ case DockLocationLeft: |
+ anchor.set_x(AdjustPointForDynamicDock( |
+ anchor_area.x(), display_bounds.x(), work_area.x())); |
+ break; |
+ case DockLocationRight: |
+ anchor.set_x(AdjustPointForDynamicDock( |
+ anchor_area.right(), display_bounds.right(), work_area.right())); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ |
+ *target_origin = NSMakePoint(anchor.x() - window_size.width / 2, |
+ max_y - anchor.y() - window_size.height / 2); |
+ *start_origin = *target_origin; |
+ |
+ switch (dock_location) { |
+ case DockLocationBottom: |
+ start_origin->y -= kDistanceMovedOnShow; |
+ break; |
+ case DockLocationLeft: |
+ start_origin->x -= kDistanceMovedOnShow; |
+ break; |
+ case DockLocationRight: |
+ start_origin->x += kDistanceMovedOnShow; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+} |
+ |
+} // namespace |
+ |
AppListServiceMac::AppListServiceMac() { |
animation_controller_.reset([[AppListAnimationController alloc] init]); |
} |
AppListServiceMac::~AppListServiceMac() {} |
+// static |
+AppListServiceMac* AppListServiceMac::GetInstance() { |
+ return Singleton<AppListServiceMac, |
+ LeakySingletonTraits<AppListServiceMac> >::get(); |
+} |
+ |
void AppListServiceMac::Init(Profile* initial_profile) { |
// On Mac, Init() is called multiple times for a process: any time there is no |
// browser window open and a new window is opened, and during process startup |
@@ -457,123 +533,6 @@ void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host, |
void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {} |
-enum DockLocation { |
- DockLocationOtherDisplay, |
- DockLocationBottom, |
- DockLocationLeft, |
- DockLocationRight, |
-}; |
- |
-DockLocation DockLocationInDisplay(const gfx::Display& display) { |
- // Assume the dock occupies part of the work area either on the left, right or |
- // bottom of the display. Note in the autohide case, it is always 4 pixels. |
- const gfx::Rect work_area = display.work_area(); |
- const gfx::Rect display_bounds = display.bounds(); |
- if (work_area.bottom() != display_bounds.bottom()) |
- return DockLocationBottom; |
- |
- if (work_area.x() != display_bounds.x()) |
- return DockLocationLeft; |
- |
- if (work_area.right() != display_bounds.right()) |
- return DockLocationRight; |
- |
- return DockLocationOtherDisplay; |
-} |
- |
-// If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock), |
-// adjust |anchor| away from the edge by a constant amount to reduce overlap and |
-// ensure the dock icon can still be clicked to dismiss the app list. |
-int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) { |
- const int kAutohideDockThreshold = 10; |
- const int kExtraDistance = 50; // A dock with 40 items is about this size. |
- if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold) |
- return anchor; |
- |
- return anchor + |
- (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance); |
-} |
- |
-void GetAppListWindowOrigins( |
- NSWindow* window, NSPoint* target_origin, NSPoint* start_origin) { |
- gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]); |
- // Ensure y coordinates are flipped back into AppKit's coordinate system. |
- const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]); |
- if (!CGCursorIsVisible()) { |
- // If Chrome is the active application, display on the same display as |
- // Chrome's keyWindow since this will catch activations triggered, e.g, via |
- // WebStore install. If another application is active, OSX doesn't provide a |
- // reliable way to get the display in use. Fall back to the primary display |
- // since it has the menu bar and is likely to be correct, e.g., for |
- // activations from Spotlight. |
- const gfx::NativeView key_view = [[NSApp keyWindow] contentView]; |
- const gfx::Rect work_area = key_view && [NSApp isActive] ? |
- screen->GetDisplayNearestWindow(key_view).work_area() : |
- screen->GetPrimaryDisplay().work_area(); |
- *target_origin = NSMakePoint(work_area.x(), max_y - work_area.bottom()); |
- *start_origin = *target_origin; |
- return; |
- } |
- |
- gfx::Point anchor = screen->GetCursorScreenPoint(); |
- const gfx::Display display = screen->GetDisplayNearestPoint(anchor); |
- const DockLocation dock_location = DockLocationInDisplay(display); |
- const gfx::Rect display_bounds = display.bounds(); |
- |
- if (dock_location == DockLocationOtherDisplay) { |
- // Just display at the bottom-left of the display the cursor is on. |
- *target_origin = NSMakePoint(display_bounds.x(), |
- max_y - display_bounds.bottom()); |
- *start_origin = *target_origin; |
- return; |
- } |
- |
- // Anchor the center of the window in a region that prevents the window |
- // showing outside of the work area. |
- const NSSize window_size = [window frame].size; |
- const gfx::Rect work_area = display.work_area(); |
- gfx::Rect anchor_area = work_area; |
- anchor_area.Inset(window_size.width / 2, window_size.height / 2); |
- anchor.SetToMax(anchor_area.origin()); |
- anchor.SetToMin(anchor_area.bottom_right()); |
- |
- // Move anchor to the dock, keeping the other axis aligned with the cursor. |
- switch (dock_location) { |
- case DockLocationBottom: |
- anchor.set_y(AdjustPointForDynamicDock( |
- anchor_area.bottom(), display_bounds.bottom(), work_area.bottom())); |
- break; |
- case DockLocationLeft: |
- anchor.set_x(AdjustPointForDynamicDock( |
- anchor_area.x(), display_bounds.x(), work_area.x())); |
- break; |
- case DockLocationRight: |
- anchor.set_x(AdjustPointForDynamicDock( |
- anchor_area.right(), display_bounds.right(), work_area.right())); |
- break; |
- default: |
- NOTREACHED(); |
- } |
- |
- *target_origin = NSMakePoint(anchor.x() - window_size.width / 2, |
- max_y - anchor.y() - window_size.height / 2); |
- *start_origin = *target_origin; |
- |
- switch (dock_location) { |
- case DockLocationBottom: |
- start_origin->y -= kDistanceMovedOnShow; |
- break; |
- case DockLocationLeft: |
- start_origin->x -= kDistanceMovedOnShow; |
- break; |
- case DockLocationRight: |
- start_origin->x += kDistanceMovedOnShow; |
- break; |
- default: |
- NOTREACHED(); |
- } |
-} |
- |
void AppListServiceMac::ShowWindowNearDock() { |
NSWindow* window = GetAppListWindow(); |
DCHECK(window); |
@@ -592,7 +551,15 @@ void AppListServiceMac::ShowWindowNearDock() { |
[NSApp activateIgnoringOtherApps:YES]; |
} |
-} // namespace |
+// static |
+AppListService* AppListService::Get() { |
+ return AppListServiceMac::GetInstance(); |
+} |
+ |
+// static |
+void AppListService::InitAll(Profile* initial_profile) { |
+ Get()->Init(initial_profile); |
+} |
@implementation AppListAnimationController |
@@ -644,13 +611,3 @@ void AppListServiceMac::ShowWindowNearDock() { |
} |
@end |
- |
-// static |
-AppListService* AppListService::Get() { |
- return AppListServiceMac::GetInstance(); |
-} |
- |
-// static |
-void AppListService::InitAll(Profile* initial_profile) { |
- Get()->Init(initial_profile); |
-} |