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