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/image/image_skia.h"
10 #include "ui/gfx/point.h"
11 #include "ui/resources/grit/ui_resources.h"
29 const CursorSetType id
;
30 const CursorData
* cursors
;
32 const CursorData
* animated_cursors
;
33 const int animated_length
;
36 const CursorData kNormalCursors
[] = {
37 {ui::kCursorNull
, IDR_AURA_CURSOR_PTR
, {4, 4}, {8, 9}},
38 {ui::kCursorPointer
, IDR_AURA_CURSOR_PTR
, {4, 4}, {8, 9}},
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
,
46 {ui::kCursorSouthWestResize
, IDR_AURA_CURSOR_SOUTH_WEST_RESIZE
,
48 {ui::kCursorSouthEastResize
, IDR_AURA_CURSOR_SOUTH_EAST_RESIZE
,
50 {ui::kCursorNorthWestResize
, IDR_AURA_CURSOR_NORTH_WEST_RESIZE
,
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
,
69 {ui::kCursorNorthSouthResize
, IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE
,
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
,
93 {ui::kCursorSouthWestResize
, IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE
,
95 {ui::kCursorSouthEastResize
, IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE
,
97 {ui::kCursorNorthWestResize
, IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE
,
99 {ui::kCursorNorthResize
, IDR_AURA_CURSOR_BIG_NORTH_RESIZE
,
101 {ui::kCursorSouthResize
, IDR_AURA_CURSOR_BIG_SOUTH_RESIZE
,
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
,
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
,
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
,
120 {ui::kCursorNorthSouthResize
, IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE
,
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
[] = {
138 kNormalCursors
, arraysize(kNormalCursors
),
139 kAnimatedCursors
, arraysize(kAnimatedCursors
)
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
];
158 bool SearchTable(const CursorData
* table
,
164 bool resource_2x_available
=
165 ResourceBundle::GetSharedInstance().GetMaxScaleFactor() ==
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
);
182 bool GetCursorDataFor(CursorSetType cursor_set_id
,
187 const CursorSet
* cursor_set
= GetCursorSetByType(cursor_set_id
);
189 SearchTable(cursor_set
->cursors
,
191 id
, scale_factor
, resource_id
, point
)) {
195 // Falls back to the default cursor set.
196 cursor_set
= GetCursorSetByType(ui::CURSOR_SET_NORMAL
);
198 return SearchTable(cursor_set
->cursors
,
200 id
, scale_factor
, resource_id
, point
);
203 bool GetAnimatedCursorDataFor(CursorSetType cursor_set_id
,
208 const CursorSet
* cursor_set
= GetCursorSetByType(cursor_set_id
);
210 SearchTable(cursor_set
->animated_cursors
,
211 cursor_set
->animated_length
,
212 id
, scale_factor
, resource_id
, point
)) {
216 // Falls back to the default cursor set.
217 cursor_set
= GetCursorSetByType(ui::CURSOR_SET_NORMAL
);
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
,
227 DCHECK(bitmap
&& point
);
229 if (!GetCursorDataFor(ui::CURSOR_SET_NORMAL
,
230 cursor
.native_type(),
231 cursor
.device_scale_factor(),
237 const SkBitmap
* cursor_bitmap
= ResourceBundle::GetSharedInstance().
238 GetImageSkiaNamed(resource_id
)->bitmap();
241 *bitmap
= *cursor_bitmap
;