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