14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/views/app_list/win/app_list_win.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_positioner.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_switches.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/app_list/views/app_list_view.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/screen.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/views/widget/widget.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const wchar_t kTrayClassName[] = L"Shell_TrayWnd";
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// If the mouse cursor is less than this distance, in pixels, away from the
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// taskbar, it is considered to be in the taskbar for the purpose of anchoring.
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static const int kSnapDistance = 50;
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The minimum distance, in pixels, to position the app list from the taskbar or
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// edge of screen.
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static const int kMinDistanceFromEdge = 3;
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Utility methods for showing the app list.
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Attempts to find the bounds of the Windows taskbar. Returns true on success.
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// |rect| is in screen coordinates. If the taskbar is in autohide mode and is
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// not visible, |rect| will be outside the current monitor's bounds, except for
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// one pixel of overlap where the edge of the taskbar is shown.
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool GetTaskbarRect(gfx::Rect* rect) {
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!taskbar_hwnd)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  RECT win_rect;
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!GetWindowRect(taskbar_hwnd, &win_rect))
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *rect = gfx::Rect(win_rect);
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Point AppListWin::FindAnchorPoint(const gfx::Size& view_size,
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       const gfx::Display& display,
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       const gfx::Point& cursor,
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       const gfx::Rect& taskbar_rect,
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       bool center_window) {
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppListPositioner positioner(display, view_size, kMinDistanceFromEdge);
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Subtract the taskbar area since the display's default work_area will not
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // subtract it if the taskbar is set to auto-hide, and the app list should
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // never overlap the taskbar.
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  positioner.WorkAreaSubtract(taskbar_rect);
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Special case for app list in the center of the screen.
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (center_window)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return positioner.GetAnchorPointForScreenCenter();
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Find which edge of the screen the taskbar is attached to.
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppListPositioner::ScreenEdge edge = positioner.GetShelfEdge(taskbar_rect);
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Snap to the taskbar edge. If the cursor is greater than kSnapDistance away,
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // anchor to the corner. Otherwise, anchor to the cursor position.
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point anchor;
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (edge == AppListPositioner::SCREEN_EDGE_UNKNOWN) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If we can't find the taskbar, snap to the bottom left.
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return positioner.GetAnchorPointForScreenCorner(
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        AppListPositioner::SCREEN_CORNER_BOTTOM_LEFT);
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (positioner.GetCursorDistanceFromShelf(edge, cursor) > kSnapDistance)
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return positioner.GetAnchorPointForShelfCorner(edge);
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return positioner.GetAnchorPointForShelfCursor(edge, cursor);
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppListWin::MoveNearCursor(app_list::AppListView* view) {
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Screen* screen =
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      gfx::Screen::GetScreenFor(view->GetWidget()->GetNativeView());
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Display display = screen->GetDisplayNearestPoint(cursor);
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  view->SetBubbleArrow(views::BubbleBorder::FLOAT);
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect taskbar_rect;
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetTaskbarRect(&taskbar_rect);
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  view->SetAnchorPoint(FindAnchorPoint(view->GetPreferredSize(),
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       display,
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       cursor,
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       taskbar_rect,
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       view->ShouldCenterWindow()));
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
96