Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / app_list / linux / app_list_linux.cc
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/linux/app_list_linux.h"
6
7 #include "ui/app_list/app_list_switches.h"
8 #include "ui/app_list/views/app_list_view.h"
9 #include "ui/gfx/screen.h"
10 #include "ui/views/linux_ui/linux_ui.h"
11 #include "ui/views/widget/widget.h"
12
13 // static
14 AppListPositioner::ScreenEdge AppListLinux::ShelfLocationInDisplay(
15     const gfx::Display& display) {
16   // On Linux, it is difficult to find the shelf (due to the large variety of
17   // desktop environments). The shelf can usually be found on the edge where the
18   // display edge and work area do not match up, but there can be more than one
19   // such edge. The shelf is assumed to be on the side of the screen with the
20   // largest delta between the display edge and the work area edge. Ties are
21   // broken in the order: top, left, right, bottom.
22   const gfx::Rect work_area = display.work_area();
23   const gfx::Rect display_bounds = display.bounds();
24
25   int winning_margin = 0;
26   AppListPositioner::ScreenEdge winning_edge =
27       AppListPositioner::SCREEN_EDGE_UNKNOWN;
28
29   if (work_area.y() - display_bounds.y() > winning_margin) {
30     winning_margin = work_area.y() - display_bounds.y();
31     winning_edge = AppListPositioner::SCREEN_EDGE_TOP;
32   }
33
34   if (work_area.x() - display_bounds.x() > winning_margin) {
35     winning_margin = work_area.x() - display_bounds.x();
36     winning_edge = AppListPositioner::SCREEN_EDGE_LEFT;
37   }
38
39   if (display_bounds.right() - work_area.right() > winning_margin) {
40     winning_margin = display_bounds.right() - work_area.right();
41     winning_edge = AppListPositioner::SCREEN_EDGE_RIGHT;
42   }
43
44   if (display_bounds.bottom() - work_area.bottom() > winning_margin) {
45     winning_margin = display_bounds.bottom() - work_area.bottom();
46     winning_edge = AppListPositioner::SCREEN_EDGE_BOTTOM;
47   }
48
49   return winning_edge;
50 }
51
52 // static
53 gfx::Point AppListLinux::FindAnchorPoint(const gfx::Size& view_size,
54                                          const gfx::Display& display,
55                                          const gfx::Point& cursor,
56                                          AppListPositioner::ScreenEdge edge,
57                                          bool center_window) {
58   AppListPositioner positioner(display, view_size, 0);
59
60   // Special case for app list in the center of the screen.
61   if (center_window)
62     return positioner.GetAnchorPointForScreenCenter();
63
64   gfx::Point anchor;
65   // Snap to the shelf edge. If the cursor is greater than the window
66   // width/height away, anchor to the corner. Otherwise, anchor to the cursor
67   // position.
68   if (edge == AppListPositioner::SCREEN_EDGE_UNKNOWN) {
69     // If we can't find the shelf, snap to the top left.
70     return positioner.GetAnchorPointForScreenCorner(
71         AppListPositioner::SCREEN_CORNER_TOP_LEFT);
72   }
73
74   int snap_distance = edge == AppListPositioner::SCREEN_EDGE_BOTTOM ||
75                               edge == AppListPositioner::SCREEN_EDGE_TOP
76                           ? view_size.height()
77                           : view_size.width();
78   if (positioner.GetCursorDistanceFromShelf(edge, cursor) > snap_distance)
79     return positioner.GetAnchorPointForShelfCorner(edge);
80
81   return positioner.GetAnchorPointForShelfCursor(edge, cursor);
82 }
83
84 // static
85 void AppListLinux::MoveNearCursor(app_list::AppListView* view) {
86   gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
87   gfx::Screen* screen =
88       gfx::Screen::GetScreenFor(view->GetWidget()->GetNativeView());
89   gfx::Display display = screen->GetDisplayNearestPoint(cursor);
90
91   view->SetBubbleArrow(views::BubbleBorder::FLOAT);
92
93   // In the Unity desktop environment, special case SCREEN_EDGE_LEFT. It is
94   // always on the left side in Unity, but ShelfLocationInDisplay will not
95   // detect this if the shelf is hidden.
96   // TODO(mgiuca): Apply this special case in Gnome Shell also. The same logic
97   // applies, but we currently have no way to detect whether Gnome Shell is
98   // running.
99   views::LinuxUI* ui = views::LinuxUI::instance();
100   AppListPositioner::ScreenEdge edge;
101   if (ui && ui->UnityIsRunning())
102     edge = AppListPositioner::SCREEN_EDGE_LEFT;
103   else
104     edge = ShelfLocationInDisplay(display);
105   view->SetAnchorPoint(FindAnchorPoint(view->GetPreferredSize(),
106                                        display,
107                                        cursor,
108                                        edge,
109                                        view->ShouldCenterWindow()));
110 }