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