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/ui/app_list/app_list_positioner.h" 8 #include "ui/app_list/app_list_switches.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 13 namespace { 14 15 static 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. 19 static const int kSnapDistance = 50; 20 21 // The minimum distance, in pixels, to position the app list from the taskbar or 22 // edge of screen. 23 static 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. 30 bool 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 45 // static 46 gfx::Point AppListWin::FindAnchorPoint(const gfx::Size& view_size, 47 const gfx::Display& display, 48 const gfx::Point& cursor, 49 const gfx::Rect& taskbar_rect, 50 bool center_window) { 51 AppListPositioner positioner(display, view_size, kMinDistanceFromEdge); 52 53 // Subtract the taskbar area since the display's default work_area will not 54 // subtract it if the taskbar is set to auto-hide, and the app list should 55 // never overlap the taskbar. 56 positioner.WorkAreaSubtract(taskbar_rect); 57 58 // Special case for app list in the center of the screen. 59 if (center_window) 60 return positioner.GetAnchorPointForScreenCenter(); 61 62 // Find which edge of the screen the taskbar is attached to. 63 AppListPositioner::ScreenEdge edge = positioner.GetShelfEdge(taskbar_rect); 64 65 // Snap to the taskbar edge. If the cursor is greater than kSnapDistance away, 66 // anchor to the corner. Otherwise, anchor to the cursor position. 67 gfx::Point anchor; 68 if (edge == AppListPositioner::SCREEN_EDGE_UNKNOWN) { 69 // If we can't find the taskbar, snap to the bottom left. 70 return positioner.GetAnchorPointForScreenCorner( 71 AppListPositioner::SCREEN_CORNER_BOTTOM_LEFT); 72 } 73 74 if (positioner.GetCursorDistanceFromShelf(edge, cursor) > kSnapDistance) 75 return positioner.GetAnchorPointForShelfCorner(edge); 76 77 return positioner.GetAnchorPointForShelfCursor(edge, cursor); 78 } 79 80 // static 81 void AppListWin::MoveNearCursor(app_list::AppListView* view) { 82 gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(); 83 gfx::Screen* screen = 84 gfx::Screen::GetScreenFor(view->GetWidget()->GetNativeView()); 85 gfx::Display display = screen->GetDisplayNearestPoint(cursor); 86 87 view->SetBubbleArrow(views::BubbleBorder::FLOAT); 88 gfx::Rect taskbar_rect; 89 GetTaskbarRect(&taskbar_rect); 90 view->SetAnchorPoint(FindAnchorPoint(view->GetPreferredSize(), 91 display, 92 cursor, 93 taskbar_rect, 94 view->ShouldCenterWindow())); 95 } 96