app_list_positioner.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/app_list/app_list_positioner.h" 6 7#include <algorithm> 8 9#include "base/logging.h" 10#include "ui/gfx/point.h" 11#include "ui/gfx/rect.h" 12 13AppListPositioner::AppListPositioner(const gfx::Display& display, 14 const gfx::Size& window_size, 15 int min_distance_from_edge) 16 : display_(display), 17 window_size_(window_size), 18 min_distance_from_edge_(min_distance_from_edge) {} 19 20void AppListPositioner::WorkAreaSubtract(const gfx::Rect& rect) { 21 gfx::Rect work_area = display_.work_area(); 22 work_area.Subtract(rect); 23 display_.set_work_area(work_area); 24} 25 26void AppListPositioner::WorkAreaInset(int left, 27 int top, 28 int right, 29 int bottom) { 30 gfx::Rect work_area = display_.work_area(); 31 work_area.Inset(left, top, right, bottom); 32 display_.set_work_area(work_area); 33} 34 35gfx::Point AppListPositioner::GetAnchorPointForScreenCorner( 36 ScreenCorner corner) const { 37 const gfx::Rect& screen_rect = display_.bounds(); 38 gfx::Point anchor; 39 switch (corner) { 40 case SCREEN_CORNER_TOP_LEFT: 41 anchor = screen_rect.origin(); 42 break; 43 case SCREEN_CORNER_TOP_RIGHT: 44 anchor = screen_rect.top_right(); 45 break; 46 case SCREEN_CORNER_BOTTOM_LEFT: 47 anchor = screen_rect.bottom_left(); 48 break; 49 case SCREEN_CORNER_BOTTOM_RIGHT: 50 anchor = screen_rect.bottom_right(); 51 break; 52 default: 53 NOTREACHED(); 54 anchor = gfx::Point(); 55 } 56 return ClampAnchorPoint(anchor); 57} 58 59gfx::Point AppListPositioner::GetAnchorPointForShelfCorner( 60 ScreenEdge shelf_edge) const { 61 const gfx::Rect& screen_rect = display_.bounds(); 62 const gfx::Rect& work_area = display_.work_area(); 63 gfx::Point anchor; 64 switch (shelf_edge) { 65 case SCREEN_EDGE_LEFT: 66 anchor = gfx::Point(work_area.x(), screen_rect.y()); 67 break; 68 case SCREEN_EDGE_RIGHT: 69 anchor = gfx::Point(work_area.right(), screen_rect.y()); 70 break; 71 case SCREEN_EDGE_TOP: 72 anchor = gfx::Point(screen_rect.x(), work_area.y()); 73 break; 74 case SCREEN_EDGE_BOTTOM: 75 anchor = gfx::Point(screen_rect.x(), work_area.bottom()); 76 break; 77 default: 78 NOTREACHED(); 79 anchor = gfx::Point(); 80 } 81 return ClampAnchorPoint(anchor); 82} 83 84gfx::Point AppListPositioner::GetAnchorPointForShelfCenter( 85 ScreenEdge shelf_edge) const { 86 const gfx::Rect& work_area = display_.work_area(); 87 gfx::Point anchor; 88 switch (shelf_edge) { 89 case SCREEN_EDGE_LEFT: 90 anchor = 91 gfx::Point(work_area.x(), work_area.y() + work_area.height() / 2); 92 break; 93 case SCREEN_EDGE_RIGHT: 94 anchor = 95 gfx::Point(work_area.right(), work_area.y() + work_area.height() / 2); 96 break; 97 case SCREEN_EDGE_TOP: 98 anchor = gfx::Point(work_area.x() + work_area.width() / 2, work_area.y()); 99 break; 100 case SCREEN_EDGE_BOTTOM: 101 anchor = 102 gfx::Point(work_area.x() + work_area.width() / 2, work_area.bottom()); 103 break; 104 default: 105 NOTREACHED(); 106 anchor = gfx::Point(); 107 } 108 return ClampAnchorPoint(anchor); 109} 110 111gfx::Point AppListPositioner::GetAnchorPointForShelfCursor( 112 ScreenEdge shelf_edge, 113 const gfx::Point& cursor) const { 114 const gfx::Rect& work_area = display_.work_area(); 115 gfx::Point anchor; 116 switch (shelf_edge) { 117 case SCREEN_EDGE_LEFT: 118 anchor = gfx::Point(work_area.x(), cursor.y()); 119 break; 120 case SCREEN_EDGE_RIGHT: 121 anchor = gfx::Point(work_area.right(), cursor.y()); 122 break; 123 case SCREEN_EDGE_TOP: 124 anchor = gfx::Point(cursor.x(), work_area.y()); 125 break; 126 case SCREEN_EDGE_BOTTOM: 127 anchor = gfx::Point(cursor.x(), work_area.bottom()); 128 break; 129 default: 130 NOTREACHED(); 131 anchor = gfx::Point(); 132 } 133 return ClampAnchorPoint(anchor); 134} 135 136AppListPositioner::ScreenEdge AppListPositioner::GetShelfEdge( 137 const gfx::Rect& shelf_rect) const { 138 const gfx::Rect& screen_rect = display_.bounds(); 139 const gfx::Rect& work_area = display_.work_area(); 140 141 // If we can't find the shelf, return SCREEN_EDGE_UNKNOWN. If the display 142 // size is the same as the work area, and does not contain the shelf, either 143 // the shelf is hidden or on another monitor. 144 if (work_area == screen_rect && !work_area.Contains(shelf_rect)) 145 return SCREEN_EDGE_UNKNOWN; 146 147 // Note: On Windows 8 the work area won't include split windows on the left or 148 // right, and neither will |shelf_rect|. 149 if (shelf_rect.x() == work_area.x() && 150 shelf_rect.width() == work_area.width()) { 151 // Shelf is horizontal. 152 if (shelf_rect.bottom() == screen_rect.bottom()) 153 return SCREEN_EDGE_BOTTOM; 154 else if (shelf_rect.y() == screen_rect.y()) 155 return SCREEN_EDGE_TOP; 156 } else if (shelf_rect.y() == work_area.y() && 157 shelf_rect.height() == work_area.height()) { 158 // Shelf is vertical. 159 if (shelf_rect.x() == screen_rect.x()) 160 return SCREEN_EDGE_LEFT; 161 else if (shelf_rect.right() == screen_rect.right()) 162 return SCREEN_EDGE_RIGHT; 163 } 164 165 return SCREEN_EDGE_UNKNOWN; 166} 167 168int AppListPositioner::GetCursorDistanceFromShelf( 169 ScreenEdge shelf_edge, 170 const gfx::Point& cursor) const { 171 const gfx::Rect& work_area = display_.work_area(); 172 switch (shelf_edge) { 173 case SCREEN_EDGE_UNKNOWN: 174 return 0; 175 case SCREEN_EDGE_LEFT: 176 return std::max(0, cursor.x() - work_area.x()); 177 case SCREEN_EDGE_RIGHT: 178 return std::max(0, work_area.right() - cursor.x()); 179 case SCREEN_EDGE_TOP: 180 return std::max(0, cursor.y() - work_area.y()); 181 case SCREEN_EDGE_BOTTOM: 182 return std::max(0, work_area.bottom() - cursor.y()); 183 default: 184 NOTREACHED(); 185 return 0; 186 } 187} 188 189gfx::Point AppListPositioner::ClampAnchorPoint(gfx::Point anchor) const { 190 gfx::Rect bounds_rect(display_.work_area()); 191 192 // Anchor the center of the window in a region that prevents the window 193 // showing outside of the work area. 194 bounds_rect.Inset(window_size_.width() / 2 + min_distance_from_edge_, 195 window_size_.height() / 2 + min_distance_from_edge_); 196 197 anchor.SetToMax(bounds_rect.origin()); 198 anchor.SetToMin(bounds_rect.bottom_right()); 199 return anchor; 200} 201