[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / ui / base / cursor / cursor_loader_x11.cc
blobe0bb9eaeb70dc90074b1f4e8856db81899dcbe89
1 // Copyright (c) 2012 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/cursor_loader_x11.h"
7 #include <float.h>
8 #include <X11/Xlib.h>
9 #include <X11/cursorfont.h>
11 #include "base/logging.h"
12 #include "grit/ui_resources.h"
13 #include "skia/ext/image_operations.h"
14 #include "ui/base/cursor/cursor.h"
15 #include "ui/base/cursor/cursor_util.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/base/x/x11_util.h"
18 #include "ui/gfx/image/image.h"
19 #include "ui/gfx/image/image_skia.h"
20 #include "ui/gfx/point_conversions.h"
21 #include "ui/gfx/size_conversions.h"
22 #include "ui/gfx/skbitmap_operations.h"
23 #include "ui/gfx/skia_util.h"
25 namespace {
27 // Returns X font cursor shape from an Aura cursor.
28 int CursorShapeFromNative(const gfx::NativeCursor& native_cursor) {
29 switch (native_cursor.native_type()) {
30 case ui::kCursorMiddlePanning:
31 return XC_fleur;
32 case ui::kCursorEastPanning:
33 return XC_sb_right_arrow;
34 case ui::kCursorNorthPanning:
35 return XC_sb_up_arrow;
36 case ui::kCursorNorthEastPanning:
37 return XC_top_right_corner;
38 case ui::kCursorNorthWestPanning:
39 return XC_top_left_corner;
40 case ui::kCursorSouthPanning:
41 return XC_sb_down_arrow;
42 case ui::kCursorSouthEastPanning:
43 return XC_bottom_right_corner;
44 case ui::kCursorSouthWestPanning:
45 return XC_bottom_left_corner;
46 case ui::kCursorWestPanning:
47 return XC_sb_left_arrow;
48 case ui::kCursorNone:
49 case ui::kCursorGrab:
50 case ui::kCursorGrabbing:
51 // TODO(jamescook): Need cursors for these. crbug.com/111650
52 return XC_left_ptr;
54 #if defined(OS_CHROMEOS)
55 case ui::kCursorNull:
56 case ui::kCursorPointer:
57 case ui::kCursorNoDrop:
58 case ui::kCursorNotAllowed:
59 case ui::kCursorCopy:
60 case ui::kCursorMove:
61 case ui::kCursorEastResize:
62 case ui::kCursorNorthResize:
63 case ui::kCursorSouthResize:
64 case ui::kCursorWestResize:
65 case ui::kCursorNorthEastResize:
66 case ui::kCursorNorthWestResize:
67 case ui::kCursorSouthWestResize:
68 case ui::kCursorSouthEastResize:
69 case ui::kCursorIBeam:
70 case ui::kCursorAlias:
71 case ui::kCursorCell:
72 case ui::kCursorContextMenu:
73 case ui::kCursorCross:
74 case ui::kCursorHelp:
75 case ui::kCursorWait:
76 case ui::kCursorNorthSouthResize:
77 case ui::kCursorEastWestResize:
78 case ui::kCursorNorthEastSouthWestResize:
79 case ui::kCursorNorthWestSouthEastResize:
80 case ui::kCursorProgress:
81 case ui::kCursorColumnResize:
82 case ui::kCursorRowResize:
83 case ui::kCursorVerticalText:
84 case ui::kCursorZoomIn:
85 case ui::kCursorZoomOut:
86 case ui::kCursorHand:
87 // In some environments, the image assets are not set (e.g. in
88 // content-browsertests, content-shell etc.).
89 return XC_left_ptr;
90 #else // defined(OS_CHROMEOS)
91 case ui::kCursorNull:
92 return XC_left_ptr;
93 case ui::kCursorPointer:
94 return XC_left_ptr;
95 case ui::kCursorMove:
96 return XC_fleur;
97 case ui::kCursorCross:
98 return XC_crosshair;
99 case ui::kCursorHand:
100 return XC_hand2;
101 case ui::kCursorIBeam:
102 return XC_xterm;
103 case ui::kCursorProgress:
104 case ui::kCursorWait:
105 return XC_watch;
106 case ui::kCursorHelp:
107 return XC_question_arrow;
108 case ui::kCursorEastResize:
109 return XC_right_side;
110 case ui::kCursorNorthResize:
111 return XC_top_side;
112 case ui::kCursorNorthEastResize:
113 return XC_top_right_corner;
114 case ui::kCursorNorthWestResize:
115 return XC_top_left_corner;
116 case ui::kCursorSouthResize:
117 return XC_bottom_side;
118 case ui::kCursorSouthEastResize:
119 return XC_bottom_right_corner;
120 case ui::kCursorSouthWestResize:
121 return XC_bottom_left_corner;
122 case ui::kCursorWestResize:
123 return XC_left_side;
124 case ui::kCursorNorthSouthResize:
125 return XC_sb_v_double_arrow;
126 case ui::kCursorEastWestResize:
127 return XC_sb_h_double_arrow;
128 case ui::kCursorColumnResize:
129 return XC_sb_h_double_arrow;
130 case ui::kCursorRowResize:
131 return XC_sb_v_double_arrow;
132 #endif // defined(OS_CHROMEOS)
133 case ui::kCursorCustom:
134 NOTREACHED();
135 return XC_left_ptr;
137 NOTREACHED() << "Case not handled for " << native_cursor.native_type();
138 return XC_left_ptr;
141 } // namespace
143 namespace ui {
145 CursorLoader* CursorLoader::Create() {
146 return new CursorLoaderX11;
149 CursorLoaderX11::CursorLoaderX11()
150 : invisible_cursor_(CreateInvisibleCursor(), gfx::GetXDisplay()) {
153 CursorLoaderX11::~CursorLoaderX11() {
154 UnloadAll();
157 void CursorLoaderX11::LoadImageCursor(int id,
158 int resource_id,
159 const gfx::Point& hot) {
160 const gfx::ImageSkia* image =
161 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
162 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale());
163 SkBitmap bitmap = image_rep.sk_bitmap();
164 gfx::Point hotpoint = hot;
165 // TODO(oshima): The cursor should use resource scale factor when
166 // fractional scale factor is enabled. crbug.com/372212
167 ScaleAndRotateCursorBitmapAndHotpoint(
168 scale() / image_rep.scale(), rotation(), &bitmap, &hotpoint);
170 XcursorImage* x_image = SkBitmapToXcursorImage(&bitmap, hotpoint);
171 cursors_[id] = CreateReffedCustomXCursor(x_image);
172 // |image_rep| is owned by the resource bundle. So we do not need to free it.
175 void CursorLoaderX11::LoadAnimatedCursor(int id,
176 int resource_id,
177 const gfx::Point& hot,
178 int frame_delay_ms) {
179 // TODO(oshima|tdanderson): Support rotation and fractional scale factor.
180 const gfx::ImageSkia* image =
181 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
182 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale());
183 SkBitmap bitmap = image_rep.sk_bitmap();
184 int frame_width = bitmap.height();
185 int frame_height = frame_width;
186 int total_width = bitmap.width();
187 DCHECK_EQ(total_width % frame_width, 0);
188 int frame_count = total_width / frame_width;
189 DCHECK_GT(frame_count, 0);
190 XcursorImages* x_images = XcursorImagesCreate(frame_count);
191 x_images->nimage = frame_count;
193 for (int frame = 0; frame < frame_count; ++frame) {
194 gfx::Point hotpoint = hot;
195 int x_offset = frame_width * frame;
196 DCHECK_LE(x_offset + frame_width, total_width);
198 SkBitmap cropped = SkBitmapOperations::CreateTiledBitmap(
199 bitmap, x_offset, 0, frame_width, frame_height);
200 DCHECK_EQ(frame_width, cropped.width());
201 DCHECK_EQ(frame_height, cropped.height());
203 XcursorImage* x_image = SkBitmapToXcursorImage(&cropped, hotpoint);
205 x_image->delay = frame_delay_ms;
206 x_images->images[frame] = x_image;
209 animated_cursors_[id] = std::make_pair(
210 XcursorImagesLoadCursor(gfx::GetXDisplay(), x_images), x_images);
211 // |bitmap| is owned by the resource bundle. So we do not need to free it.
214 void CursorLoaderX11::UnloadAll() {
215 for (ImageCursorMap::const_iterator it = cursors_.begin();
216 it != cursors_.end(); ++it)
217 UnrefCustomXCursor(it->second);
219 // Free animated cursors and images.
220 for (AnimatedCursorMap::iterator it = animated_cursors_.begin();
221 it != animated_cursors_.end(); ++it) {
222 XcursorImagesDestroy(it->second.second); // also frees individual frames.
223 XFreeCursor(gfx::GetXDisplay(), it->second.first);
227 void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) {
228 DCHECK(cursor);
230 ::Cursor xcursor;
231 if (IsImageCursor(*cursor))
232 xcursor = ImageCursorFromNative(*cursor);
233 else if (*cursor == kCursorNone)
234 xcursor = invisible_cursor_.get();
235 else if (*cursor == kCursorCustom)
236 xcursor = cursor->platform();
237 else if (scale() == 1.0f && rotation() == gfx::Display::ROTATE_0) {
238 xcursor = GetXCursor(CursorShapeFromNative(*cursor));
239 } else {
240 xcursor = ImageCursorFromNative(kCursorPointer);
243 cursor->SetPlatformCursor(xcursor);
246 const XcursorImage* CursorLoaderX11::GetXcursorImageForTest(int id) {
247 return test::GetCachedXcursorImage(cursors_[id]);
250 bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) {
251 int type = native_cursor.native_type();
252 return cursors_.count(type) || animated_cursors_.count(type);
255 ::Cursor CursorLoaderX11::ImageCursorFromNative(
256 gfx::NativeCursor native_cursor) {
257 int type = native_cursor.native_type();
258 if (animated_cursors_.count(type))
259 return animated_cursors_[type].first;
261 ImageCursorMap::iterator find = cursors_.find(type);
262 if (find != cursors_.end())
263 return cursors_[type];
264 return GetXCursor(CursorShapeFromNative(native_cursor));
267 } // namespace ui