app_list_win.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/app_list/win/app_list_win.h"
6
7#include "base/command_line.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/app_list/app_list_positioner.h"
10#include "ui/app_list/app_list_switches.h"
11#include "ui/app_list/views/app_list_view.h"
12#include "ui/gfx/screen.h"
13#include "ui/views/widget/widget.h"
14
15namespace {
16
17static const wchar_t kTrayClassName[] = L"Shell_TrayWnd";
18
19// If the mouse cursor is less than this distance, in pixels, away from the
20// taskbar, it is considered to be in the taskbar for the purpose of anchoring.
21static const int kSnapDistance = 50;
22
23// The minimum distance, in pixels, to position the app list from the taskbar or
24// edge of screen.
25static const int kMinDistanceFromEdge = 3;
26
27// Utility methods for showing the app list.
28// Attempts to find the bounds of the Windows taskbar. Returns true on success.
29// |rect| is in screen coordinates. If the taskbar is in autohide mode and is
30// not visible, |rect| will be outside the current monitor's bounds, except for
31// one pixel of overlap where the edge of the taskbar is shown.
32bool GetTaskbarRect(gfx::Rect* rect) {
33  HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
34  if (!taskbar_hwnd)
35    return false;
36
37  RECT win_rect;
38  if (!GetWindowRect(taskbar_hwnd, &win_rect))
39    return false;
40
41  *rect = gfx::Rect(win_rect);
42  return true;
43}
44
45}  // namespace
46
47AppListWin::AppListWin(app_list::AppListView* view,
48                       const base::Closure& on_should_dismiss)
49    : view_(view),
50      activation_tracker_(view, on_should_dismiss),
51      window_icon_updated_(false) {}
52
53AppListWin::~AppListWin() {}
54
55gfx::Point AppListWin::FindAnchorPoint(const gfx::Size& view_size,
56                                       const gfx::Display& display,
57                                       const gfx::Point& cursor,
58                                       const gfx::Rect& taskbar_rect) {
59  AppListPositioner positioner(display, view_size, kMinDistanceFromEdge);
60
61  // Subtract the taskbar area since the display's default work_area will not
62  // subtract it if the taskbar is set to auto-hide, and the app list should
63  // never overlap the taskbar.
64  positioner.WorkAreaSubtract(taskbar_rect);
65
66  // The experimental app list is placed in the center of the screen.
67  if (app_list::switches::IsExperimentalAppListPositionEnabled())
68    return positioner.GetAnchorPointForScreenCenter();
69
70  // Find which edge of the screen the taskbar is attached to.
71  AppListPositioner::ScreenEdge edge = positioner.GetShelfEdge(taskbar_rect);
72
73  // Snap to the taskbar edge. If the cursor is greater than kSnapDistance away,
74  // anchor to the corner. Otherwise, anchor to the cursor position.
75  gfx::Point anchor;
76  if (edge == AppListPositioner::SCREEN_EDGE_UNKNOWN) {
77    // If we can't find the taskbar, snap to the bottom left.
78    return positioner.GetAnchorPointForScreenCorner(
79        AppListPositioner::SCREEN_CORNER_BOTTOM_LEFT);
80  }
81
82  if (positioner.GetCursorDistanceFromShelf(edge, cursor) > kSnapDistance)
83    return positioner.GetAnchorPointForShelfCorner(edge);
84
85  return positioner.GetAnchorPointForShelfCursor(edge, cursor);
86}
87
88void AppListWin::Show() {
89  view_->GetWidget()->Show();
90  if (!window_icon_updated_) {
91    view_->GetWidget()->GetTopLevelWidget()->UpdateWindowIcon();
92    window_icon_updated_ = true;
93  }
94  view_->GetWidget()->Activate();
95}
96
97void AppListWin::Hide() {
98  view_->GetWidget()->Hide();
99  activation_tracker_.OnViewHidden();
100}
101
102void AppListWin::MoveNearCursor() {
103  gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
104  gfx::Screen* screen =
105      gfx::Screen::GetScreenFor(view_->GetWidget()->GetNativeView());
106  gfx::Display display = screen->GetDisplayNearestPoint(cursor);
107
108  view_->SetBubbleArrow(views::BubbleBorder::FLOAT);
109  gfx::Rect taskbar_rect;
110  GetTaskbarRect(&taskbar_rect);
111  view_->SetAnchorPoint(FindAnchorPoint(view_->GetPreferredSize(), display,
112                                        cursor, taskbar_rect));
113}
114
115bool AppListWin::IsVisible() {
116  return view_->GetWidget()->IsVisible();
117}
118
119void AppListWin::Prerender() {
120  view_->Prerender();
121}
122
123gfx::NativeWindow AppListWin::GetWindow() {
124  return view_->GetWidget()->GetNativeWindow();
125}
126
127void AppListWin::SetProfile(Profile* profile) {
128  view_->SetProfileByPath(profile->GetPath());
129}
130