cursors_aura.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright (c) 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 "ui/base/cursor/cursors_aura.h"
6
7#include "grit/ui_resources.h"
8#include "ui/base/resource/resource_bundle.h"
9#include "ui/gfx/point.h"
10
11namespace ui {
12namespace {
13
14struct HotPoint {
15  int x;
16  int y;
17};
18
19struct CursorData {
20  int id;
21  int resource_id;
22  HotPoint hot_1x;
23  HotPoint hot_2x;
24};
25
26struct CursorSet {
27  const CursorSetType id;
28  const CursorData* cursors;
29  const int length;
30  const CursorData* animated_cursors;
31  const int animated_length;
32};
33
34const CursorData kNormalCursors[] = {
35  {ui::kCursorNull, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}},
36  {ui::kCursorPointer, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}},
37  {ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}},
38  {ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}},
39  {ui::kCursorCopy, IDR_AURA_CURSOR_COPY, {9, 9}, {18, 18}},
40  {ui::kCursorHand, IDR_AURA_CURSOR_HAND, {9, 4}, {19, 8}},
41  {ui::kCursorMove, IDR_AURA_CURSOR_MOVE, {11, 11}, {23, 23}},
42  {ui::kCursorNorthEastResize, IDR_AURA_CURSOR_NORTH_EAST_RESIZE,
43   {12, 11}, {25, 23}},
44  {ui::kCursorSouthWestResize, IDR_AURA_CURSOR_SOUTH_WEST_RESIZE,
45   {12, 11}, {25, 23}},
46  {ui::kCursorSouthEastResize, IDR_AURA_CURSOR_SOUTH_EAST_RESIZE,
47   {11, 11}, {24, 23}},
48  {ui::kCursorNorthWestResize, IDR_AURA_CURSOR_NORTH_WEST_RESIZE,
49   {11, 11}, {24, 23}},
50  {ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE, {11, 12}, {23, 23}},
51  {ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE, {11, 12}, {23, 23}},
52  {ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE, {12, 11}, {25, 23}},
53  {ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE, {12, 11}, {25, 23}},
54  {ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM, {12, 12}, {24, 25}},
55  {ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS, {8, 6}, {15, 11}},
56  {ui::kCursorCell, IDR_AURA_CURSOR_CELL, {11, 11}, {24, 23}},
57  {ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, {4, 4}, {8, 9}},
58  {ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR, {12, 12}, {25, 23}},
59  {ui::kCursorHelp, IDR_AURA_CURSOR_HELP, {4, 4}, {8, 9}},
60  {ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ, {12, 11}, {26, 23}},
61  {ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN, {10, 10}, {20, 20}},
62  {ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, {10, 10}, {20, 20}},
63  {ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE, {11, 12}, {23, 23}},
64  {ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE, {12, 11}, {25, 23}},
65  {ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE,
66   {12, 11}, {25, 23}},
67  {ui::kCursorNorthSouthResize, IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE,
68   {11, 12}, {23, 23}},
69  {ui::kCursorNorthEastSouthWestResize,
70   IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, {12, 11}, {25, 23}},
71  {ui::kCursorNorthWestSouthEastResize,
72   IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, {11, 11}, {24, 23}},
73  {ui::kCursorGrab, IDR_AURA_CURSOR_GRAB, {8, 5}, {16, 10}},
74  {ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, {9, 9}, {18, 18}},
75};
76
77const CursorData kLargeCursors[] = {
78  // The 2x hotspots should be double of the 1x, even though the cursors are
79  // shown as same size as 1x (64x64). Since, in 2x dpi screen, the 1x large
80  // cursor assets (64x64) are internally enlarged to the double size (128x128)
81  // by ResourceBundleImageSource.
82  {ui::kCursorNull, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {20, 20}},
83  {ui::kCursorPointer, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {20, 20}},
84  {ui::kCursorNoDrop, IDR_AURA_CURSOR_BIG_NO_DROP, {10, 10}, {20, 20}},
85  {ui::kCursorNotAllowed, IDR_AURA_CURSOR_BIG_NO_DROP, {23, 23}, {46, 46}},
86  {ui::kCursorCopy, IDR_AURA_CURSOR_BIG_COPY, {10, 10}, {20, 20}},
87  {ui::kCursorHand, IDR_AURA_CURSOR_BIG_HAND, {25, 7}, {50, 14}},
88  {ui::kCursorMove, IDR_AURA_CURSOR_BIG_MOVE, {32, 31}, {64, 62}},
89  {ui::kCursorNorthEastResize, IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE,
90   {31, 28}, {62, 56}},
91  {ui::kCursorSouthWestResize, IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE,
92   {31, 28}, {62, 56}},
93  {ui::kCursorSouthEastResize, IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE,
94   {28, 28}, {56, 56}},
95  {ui::kCursorNorthWestResize, IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE,
96   {28, 28}, {56, 56}},
97  {ui::kCursorNorthResize, IDR_AURA_CURSOR_BIG_NORTH_RESIZE,
98   {29, 32}, {58, 64}},
99  {ui::kCursorSouthResize, IDR_AURA_CURSOR_BIG_SOUTH_RESIZE,
100   {29, 32}, {58, 64}},
101  {ui::kCursorEastResize, IDR_AURA_CURSOR_BIG_EAST_RESIZE, {35, 29}, {70, 58}},
102  {ui::kCursorWestResize, IDR_AURA_CURSOR_BIG_WEST_RESIZE, {35, 29}, {70, 58}},
103  {ui::kCursorIBeam, IDR_AURA_CURSOR_BIG_IBEAM, {30, 32}, {30, 64}},
104  {ui::kCursorAlias, IDR_AURA_CURSOR_BIG_ALIAS, {19, 11}, {38, 22}},
105  {ui::kCursorCell, IDR_AURA_CURSOR_BIG_CELL, {30, 30}, {60, 60}},
106  {ui::kCursorContextMenu, IDR_AURA_CURSOR_BIG_CONTEXT_MENU,
107   {11, 11}, {22, 22}},
108  {ui::kCursorCross, IDR_AURA_CURSOR_BIG_CROSSHAIR, {31, 30}, {62, 60}},
109  {ui::kCursorHelp, IDR_AURA_CURSOR_BIG_HELP, {10, 11}, {20, 22}},
110  {ui::kCursorVerticalText, IDR_AURA_CURSOR_BIG_XTERM_HORIZ,
111   {32, 30}, {64, 60}},
112  {ui::kCursorZoomIn, IDR_AURA_CURSOR_BIG_ZOOM_IN, {25, 26}, {50, 52}},
113  {ui::kCursorZoomOut, IDR_AURA_CURSOR_BIG_ZOOM_OUT, {26, 26}, {52, 52}},
114  {ui::kCursorRowResize, IDR_AURA_CURSOR_BIG_ROW_RESIZE, {29, 32}, {58, 64}},
115  {ui::kCursorColumnResize, IDR_AURA_CURSOR_BIG_COL_RESIZE, {35, 29}, {70, 58}},
116  {ui::kCursorEastWestResize, IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE,
117   {35, 29}, {70, 58}},
118  {ui::kCursorNorthSouthResize, IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE,
119   {29, 32}, {58, 64}},
120  {ui::kCursorNorthEastSouthWestResize,
121   IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE, {32, 30}, {64, 60}},
122  {ui::kCursorNorthWestSouthEastResize,
123   IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE, {32, 31}, {64, 62}},
124  {ui::kCursorGrab, IDR_AURA_CURSOR_BIG_GRAB, {21, 11}, {42, 22}},
125  {ui::kCursorGrabbing, IDR_AURA_CURSOR_BIG_GRABBING, {20, 12}, {40, 24}},
126};
127
128const CursorData kAnimatedCursors[] = {
129  {ui::kCursorWait, IDR_THROBBER, {7, 7}, {14, 14}},
130  {ui::kCursorProgress, IDR_THROBBER, {7, 7}, {14, 14}},
131};
132
133const CursorSet kCursorSets[] = {
134  {
135    CURSOR_SET_NORMAL,
136    kNormalCursors, arraysize(kNormalCursors),
137    kAnimatedCursors, arraysize(kAnimatedCursors)
138  },
139  {
140    CURSOR_SET_LARGE,
141    kLargeCursors, arraysize(kLargeCursors),
142    // TODO(yoshiki): Replace animated cursors with big assets. crbug.com/247254
143    kAnimatedCursors, arraysize(kAnimatedCursors)
144  },
145};
146
147const CursorSet* GetCursorSetByType(CursorSetType cursor_set_id) {
148  for (size_t i = 0; i < arraysize(kCursorSets); ++i) {
149    if (kCursorSets[i].id == cursor_set_id)
150      return &kCursorSets[i];
151  }
152
153  return NULL;
154}
155
156bool SearchTable(const CursorData* table,
157                 size_t table_length,
158                 int id,
159                 float scale_factor,
160                 int* resource_id,
161                 gfx::Point* point) {
162  bool resource_2x_available =
163      ResourceBundle::GetSharedInstance().GetMaxScaleFactor() ==
164      SCALE_FACTOR_200P;
165  for (size_t i = 0; i < table_length; ++i) {
166    if (table[i].id == id) {
167      *resource_id = table[i].resource_id;
168      *point = scale_factor == 1.0f || !resource_2x_available ?
169               gfx::Point(table[i].hot_1x.x, table[i].hot_1x.y) :
170               gfx::Point(table[i].hot_2x.x, table[i].hot_2x.y);
171      return true;
172    }
173  }
174
175  return false;
176}
177
178}  // namespace
179
180bool GetCursorDataFor(CursorSetType cursor_set_id,
181                      int id,
182                      float scale_factor,
183                      int* resource_id,
184                      gfx::Point* point) {
185  const CursorSet* cursor_set = GetCursorSetByType(cursor_set_id);
186  if (cursor_set &&
187      SearchTable(cursor_set->cursors,
188                  cursor_set->length,
189                  id, scale_factor, resource_id, point)) {
190      return true;
191  }
192
193  // Falls back to the default cursor set.
194  cursor_set = GetCursorSetByType(ui::CURSOR_SET_NORMAL);
195  DCHECK(cursor_set);
196  return SearchTable(cursor_set->cursors,
197                     cursor_set->length,
198                     id, scale_factor, resource_id, point);
199}
200
201bool GetAnimatedCursorDataFor(CursorSetType cursor_set_id,
202                              int id,
203                              float scale_factor,
204                              int* resource_id,
205                              gfx::Point* point) {
206  const CursorSet* cursor_set = GetCursorSetByType(cursor_set_id);
207  if (cursor_set &&
208      SearchTable(cursor_set->animated_cursors,
209                  cursor_set->animated_length,
210                  id, scale_factor, resource_id, point)) {
211    return true;
212  }
213
214  // Falls back to the default cursor set.
215  cursor_set = GetCursorSetByType(ui::CURSOR_SET_NORMAL);
216  DCHECK(cursor_set);
217  return SearchTable(cursor_set->animated_cursors,
218                     cursor_set->animated_length,
219                     id, scale_factor, resource_id, point);
220}
221
222}  // namespace ui
223