Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(553)

Side by Side Diff: chrome/browser/ui/app_list/app_list_service_mac.mm

Issue 23072036: Adds an integration test for uninstalling app list search results. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: self review, aura is happy Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/app_list/app_list_service_mac.h"
6
5 #include <ApplicationServices/ApplicationServices.h> 7 #include <ApplicationServices/ApplicationServices.h>
6 #import <Cocoa/Cocoa.h> 8 #import <Cocoa/Cocoa.h>
7 9
8 #include "apps/app_launcher.h" 10 #include "apps/app_launcher.h"
9 #include "apps/app_shim/app_shim_handler_mac.h"
10 #include "apps/app_shim/app_shim_mac.h" 11 #include "apps/app_shim/app_shim_mac.h"
11 #include "apps/pref_names.h" 12 #include "apps/pref_names.h"
12 #include "base/bind.h" 13 #include "base/bind.h"
13 #include "base/command_line.h" 14 #include "base/command_line.h"
14 #include "base/file_util.h" 15 #include "base/file_util.h"
15 #include "base/lazy_instance.h" 16 #include "base/lazy_instance.h"
16 #include "base/mac/scoped_nsobject.h"
17 #include "base/memory/singleton.h" 17 #include "base/memory/singleton.h"
18 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
19 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/extensions/extension_service.h" 20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_system.h" 21 #include "chrome/browser/extensions/extension_system.h"
22 #include "chrome/browser/profiles/profile_manager.h" 22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" 23 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
24 #include "chrome/browser/ui/app_list/app_list_service.h" 24 #include "chrome/browser/ui/app_list/app_list_service.h"
25 #include "chrome/browser/ui/app_list/app_list_service_impl.h" 25 #include "chrome/browser/ui/app_list/app_list_service_impl.h"
26 #include "chrome/browser/ui/app_list/app_list_view_delegate.h" 26 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
(...skipping 17 matching lines...) Expand all
44 44
45 namespace gfx { 45 namespace gfx {
46 class ImageSkia; 46 class ImageSkia;
47 } 47 }
48 48
49 namespace { 49 namespace {
50 50
51 // Version of the app list shortcut version installed. 51 // Version of the app list shortcut version installed.
52 const int kShortcutVersion = 1; 52 const int kShortcutVersion = 1;
53 53
54 // AppListServiceMac manages global resources needed for the app list to
55 // operate, and controls when the app list is opened and closed.
56 class AppListServiceMac : public AppListServiceImpl,
57 public apps::AppShimHandler {
58 public:
59 virtual ~AppListServiceMac() {}
60
61 static AppListServiceMac* GetInstance() {
62 return Singleton<AppListServiceMac,
63 LeakySingletonTraits<AppListServiceMac> >::get();
64 }
65
66 void ShowWindowNearDock();
67
68 // AppListService overrides:
69 virtual void Init(Profile* initial_profile) OVERRIDE;
70 virtual void CreateForProfile(Profile* requested_profile) OVERRIDE;
71 virtual void ShowForProfile(Profile* requested_profile) OVERRIDE;
72 virtual void DismissAppList() OVERRIDE;
73 virtual bool IsAppListVisible() const OVERRIDE;
74 virtual gfx::NativeWindow GetAppListWindow() OVERRIDE;
75 virtual AppListControllerDelegate* CreateControllerDelegate() OVERRIDE;
76
77 // AppListServiceImpl overrides:
78 virtual void CreateShortcut() OVERRIDE;
79
80 // AppShimHandler overrides:
81 virtual void OnShimLaunch(apps::AppShimHandler::Host* host,
82 apps::AppShimLaunchType launch_type) OVERRIDE;
83 virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE;
84 virtual void OnShimFocus(apps::AppShimHandler::Host* host,
85 apps::AppShimFocusType focus_type) OVERRIDE;
86 virtual void OnShimSetHidden(apps::AppShimHandler::Host* host,
87 bool hidden) OVERRIDE;
88 virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE;
89
90 private:
91 friend struct DefaultSingletonTraits<AppListServiceMac>;
92
93 AppListServiceMac() {}
94
95 base::scoped_nsobject<AppListWindowController> window_controller_;
96 base::scoped_nsobject<NSRunningApplication> previously_active_application_;
97
98 DISALLOW_COPY_AND_ASSIGN(AppListServiceMac);
99 };
100
101 class AppListControllerDelegateCocoa : public AppListControllerDelegate { 54 class AppListControllerDelegateCocoa : public AppListControllerDelegate {
102 public: 55 public:
103 AppListControllerDelegateCocoa(); 56 AppListControllerDelegateCocoa();
104 virtual ~AppListControllerDelegateCocoa(); 57 virtual ~AppListControllerDelegateCocoa();
105 58
106 private: 59 private:
107 // AppListControllerDelegate overrides: 60 // AppListControllerDelegate overrides:
108 virtual void DismissView() OVERRIDE; 61 virtual void DismissView() OVERRIDE;
109 virtual gfx::NativeWindow GetAppListWindow() OVERRIDE; 62 virtual gfx::NativeWindow GetAppListWindow() OVERRIDE;
110 virtual bool CanPin() OVERRIDE; 63 virtual bool CanPin() OVERRIDE;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 Profile* profile, const extensions::Extension* extension, int event_flags) { 235 Profile* profile, const extensions::Extension* extension, int event_flags) {
283 LaunchApp(profile, extension, event_flags); 236 LaunchApp(profile, extension, event_flags);
284 } 237 }
285 238
286 void AppListControllerDelegateCocoa::LaunchApp( 239 void AppListControllerDelegateCocoa::LaunchApp(
287 Profile* profile, const extensions::Extension* extension, int event_flags) { 240 Profile* profile, const extensions::Extension* extension, int event_flags) {
288 chrome::OpenApplication(chrome::AppLaunchParams( 241 chrome::OpenApplication(chrome::AppLaunchParams(
289 profile, extension, NEW_FOREGROUND_TAB)); 242 profile, extension, NEW_FOREGROUND_TAB));
290 } 243 }
291 244
245 enum DockLocation {
246 DockLocationOtherDisplay,
247 DockLocationBottom,
248 DockLocationLeft,
249 DockLocationRight,
250 };
251
252 DockLocation DockLocationInDisplay(const gfx::Display& display) {
253 // Assume the dock occupies part of the work area either on the left, right or
254 // bottom of the display. Note in the autohide case, it is always 4 pixels.
255 const gfx::Rect work_area = display.work_area();
256 const gfx::Rect display_bounds = display.bounds();
257 if (work_area.bottom() != display_bounds.bottom())
258 return DockLocationBottom;
259
260 if (work_area.x() != display_bounds.x())
261 return DockLocationLeft;
262
263 if (work_area.right() != display_bounds.right())
264 return DockLocationRight;
265
266 return DockLocationOtherDisplay;
267 }
268
269 // If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock),
270 // adjust |anchor| away from the edge by a constant amount to reduce overlap and
271 // ensure the dock icon can still be clicked to dismiss the app list.
272 int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) {
273 const int kAutohideDockThreshold = 10;
274 const int kExtraDistance = 50; // A dock with 40 items is about this size.
275 if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold)
276 return anchor;
277
278 return anchor +
279 (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance);
280 }
281
282 NSPoint GetAppListWindowOrigin(NSWindow* window) {
283 gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]);
284 // Ensure y coordinates are flipped back into AppKit's coordinate system.
285 const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]);
286 if (!CGCursorIsVisible()) {
287 // If Chrome is the active application, display on the same display as
288 // Chrome's keyWindow since this will catch activations triggered, e.g, via
289 // WebStore install. If another application is active, OSX doesn't provide a
290 // reliable way to get the display in use. Fall back to the primary display
291 // since it has the menu bar and is likely to be correct, e.g., for
292 // activations from Spotlight.
293 const gfx::NativeView key_view = [[NSApp keyWindow] contentView];
294 const gfx::Rect work_area = key_view && [NSApp isActive] ?
295 screen->GetDisplayNearestWindow(key_view).work_area() :
296 screen->GetPrimaryDisplay().work_area();
297 return NSMakePoint(work_area.x(), max_y - work_area.bottom());
298 }
299
300 gfx::Point anchor = screen->GetCursorScreenPoint();
301 const gfx::Display display = screen->GetDisplayNearestPoint(anchor);
302 const DockLocation dock_location = DockLocationInDisplay(display);
303 const gfx::Rect display_bounds = display.bounds();
304
305 if (dock_location == DockLocationOtherDisplay) {
306 // Just display at the bottom-left of the display the cursor is on.
307 return NSMakePoint(display_bounds.x(), max_y - display_bounds.bottom());
308 }
309
310 // Anchor the center of the window in a region that prevents the window
311 // showing outside of the work area.
312 const NSSize window_size = [window frame].size;
313 const gfx::Rect work_area = display.work_area();
314 gfx::Rect anchor_area = work_area;
315 anchor_area.Inset(window_size.width / 2, window_size.height / 2);
316 anchor.SetToMax(anchor_area.origin());
317 anchor.SetToMin(anchor_area.bottom_right());
318
319 // Move anchor to the dock, keeping the other axis aligned with the cursor.
320 switch (dock_location) {
321 case DockLocationBottom:
322 anchor.set_y(AdjustPointForDynamicDock(
323 anchor_area.bottom(), display_bounds.bottom(), work_area.bottom()));
324 break;
325 case DockLocationLeft:
326 anchor.set_x(AdjustPointForDynamicDock(
327 anchor_area.x(), display_bounds.x(), work_area.x()));
328 break;
329 case DockLocationRight:
330 anchor.set_x(AdjustPointForDynamicDock(
331 anchor_area.right(), display_bounds.right(), work_area.right()));
332 break;
333 default:
334 NOTREACHED();
335 }
336
337 return NSMakePoint(
338 anchor.x() - window_size.width / 2,
339 max_y - anchor.y() - window_size.height / 2);
340 }
341
342 } // namespace
343
344 AppListServiceMac::AppListServiceMac() {}
345 AppListServiceMac::~AppListServiceMac() {}
346
347 // static
348 AppListServiceMac* AppListServiceMac::GetInstance() {
349 return Singleton<AppListServiceMac,
350 LeakySingletonTraits<AppListServiceMac> >::get();
351 }
352
292 void AppListServiceMac::Init(Profile* initial_profile) { 353 void AppListServiceMac::Init(Profile* initial_profile) {
293 // On Mac, Init() is called multiple times for a process: any time there is no 354 // On Mac, Init() is called multiple times for a process: any time there is no
294 // browser window open and a new window is opened, and during process startup 355 // browser window open and a new window is opened, and during process startup
295 // to handle the silent launch case (e.g. for app shims). In the startup case, 356 // to handle the silent launch case (e.g. for app shims). In the startup case,
296 // a profile has not yet been determined so |initial_profile| will be NULL. 357 // a profile has not yet been determined so |initial_profile| will be NULL.
297 static bool init_called_with_profile = false; 358 static bool init_called_with_profile = false;
298 if (initial_profile && !init_called_with_profile) { 359 if (initial_profile && !init_called_with_profile) {
299 init_called_with_profile = true; 360 init_called_with_profile = true;
300 HandleCommandLineFlags(initial_profile); 361 HandleCommandLineFlags(initial_profile);
301 PrefService* local_state = g_browser_process->local_state(); 362 PrefService* local_state = g_browser_process->local_state();
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 void AppListServiceMac::OnShimClose(apps::AppShimHandler::Host* host) {} 474 void AppListServiceMac::OnShimClose(apps::AppShimHandler::Host* host) {}
414 475
415 void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host, 476 void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host,
416 apps::AppShimFocusType focus_type) {} 477 apps::AppShimFocusType focus_type) {}
417 478
418 void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host, 479 void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host,
419 bool hidden) {} 480 bool hidden) {}
420 481
421 void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {} 482 void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {}
422 483
423 enum DockLocation {
424 DockLocationOtherDisplay,
425 DockLocationBottom,
426 DockLocationLeft,
427 DockLocationRight,
428 };
429
430 DockLocation DockLocationInDisplay(const gfx::Display& display) {
431 // Assume the dock occupies part of the work area either on the left, right or
432 // bottom of the display. Note in the autohide case, it is always 4 pixels.
433 const gfx::Rect work_area = display.work_area();
434 const gfx::Rect display_bounds = display.bounds();
435 if (work_area.bottom() != display_bounds.bottom())
436 return DockLocationBottom;
437
438 if (work_area.x() != display_bounds.x())
439 return DockLocationLeft;
440
441 if (work_area.right() != display_bounds.right())
442 return DockLocationRight;
443
444 return DockLocationOtherDisplay;
445 }
446
447 // If |work_area_edge| is too close to the |screen_edge| (e.g. autohide dock),
448 // adjust |anchor| away from the edge by a constant amount to reduce overlap and
449 // ensure the dock icon can still be clicked to dismiss the app list.
450 int AdjustPointForDynamicDock(int anchor, int screen_edge, int work_area_edge) {
451 const int kAutohideDockThreshold = 10;
452 const int kExtraDistance = 50; // A dock with 40 items is about this size.
453 if (abs(work_area_edge - screen_edge) > kAutohideDockThreshold)
454 return anchor;
455
456 return anchor +
457 (screen_edge < work_area_edge ? kExtraDistance : -kExtraDistance);
458 }
459
460 NSPoint GetAppListWindowOrigin(NSWindow* window) {
461 gfx::Screen* const screen = gfx::Screen::GetScreenFor([window contentView]);
462 // Ensure y coordinates are flipped back into AppKit's coordinate system.
463 const CGFloat max_y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]);
464 if (!CGCursorIsVisible()) {
465 // If Chrome is the active application, display on the same display as
466 // Chrome's keyWindow since this will catch activations triggered, e.g, via
467 // WebStore install. If another application is active, OSX doesn't provide a
468 // reliable way to get the display in use. Fall back to the primary display
469 // since it has the menu bar and is likely to be correct, e.g., for
470 // activations from Spotlight.
471 const gfx::NativeView key_view = [[NSApp keyWindow] contentView];
472 const gfx::Rect work_area = key_view && [NSApp isActive] ?
473 screen->GetDisplayNearestWindow(key_view).work_area() :
474 screen->GetPrimaryDisplay().work_area();
475 return NSMakePoint(work_area.x(), max_y - work_area.bottom());
476 }
477
478 gfx::Point anchor = screen->GetCursorScreenPoint();
479 const gfx::Display display = screen->GetDisplayNearestPoint(anchor);
480 const DockLocation dock_location = DockLocationInDisplay(display);
481 const gfx::Rect display_bounds = display.bounds();
482
483 if (dock_location == DockLocationOtherDisplay) {
484 // Just display at the bottom-left of the display the cursor is on.
485 return NSMakePoint(display_bounds.x(), max_y - display_bounds.bottom());
486 }
487
488 // Anchor the center of the window in a region that prevents the window
489 // showing outside of the work area.
490 const NSSize window_size = [window frame].size;
491 const gfx::Rect work_area = display.work_area();
492 gfx::Rect anchor_area = work_area;
493 anchor_area.Inset(window_size.width / 2, window_size.height / 2);
494 anchor.SetToMax(anchor_area.origin());
495 anchor.SetToMin(anchor_area.bottom_right());
496
497 // Move anchor to the dock, keeping the other axis aligned with the cursor.
498 switch (dock_location) {
499 case DockLocationBottom:
500 anchor.set_y(AdjustPointForDynamicDock(
501 anchor_area.bottom(), display_bounds.bottom(), work_area.bottom()));
502 break;
503 case DockLocationLeft:
504 anchor.set_x(AdjustPointForDynamicDock(
505 anchor_area.x(), display_bounds.x(), work_area.x()));
506 break;
507 case DockLocationRight:
508 anchor.set_x(AdjustPointForDynamicDock(
509 anchor_area.right(), display_bounds.right(), work_area.right()));
510 break;
511 default:
512 NOTREACHED();
513 }
514
515 return NSMakePoint(
516 anchor.x() - window_size.width / 2,
517 max_y - anchor.y() - window_size.height / 2);
518 }
519
520 void AppListServiceMac::ShowWindowNearDock() { 484 void AppListServiceMac::ShowWindowNearDock() {
521 NSWindow* window = GetAppListWindow(); 485 NSWindow* window = GetAppListWindow();
522 DCHECK(window); 486 DCHECK(window);
523 [window setFrameOrigin:GetAppListWindowOrigin(window)]; 487 [window setFrameOrigin:GetAppListWindowOrigin(window)];
524 488
525 // Before activating, see if an application other than Chrome is currently the 489 // Before activating, see if an application other than Chrome is currently the
526 // active application, so that it can be reactivated when dismissing. 490 // active application, so that it can be reactivated when dismissing.
527 previously_active_application_.reset([ActiveApplicationNotChrome() retain]); 491 previously_active_application_.reset([ActiveApplicationNotChrome() retain]);
528 492
529 [window makeKeyAndOrderFront:nil]; 493 [window makeKeyAndOrderFront:nil];
530 [NSApp activateIgnoringOtherApps:YES]; 494 [NSApp activateIgnoringOtherApps:YES];
531 } 495 }
532 496
533 } // namespace
534
535 // static 497 // static
536 AppListService* AppListService::Get() { 498 AppListService* AppListService::Get() {
537 return AppListServiceMac::GetInstance(); 499 return AppListServiceMac::GetInstance();
538 } 500 }
539 501
540 // static 502 // static
541 void AppListService::InitAll(Profile* initial_profile) { 503 void AppListService::InitAll(Profile* initial_profile) {
542 Get()->Init(initial_profile); 504 Get()->Init(initial_profile);
543 } 505 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698