OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "ui/base/cursor/cursor_loader_x11.h" | |
6 | |
7 #include <float.h> | |
8 #include <X11/Xlib.h> | |
9 #include <X11/cursorfont.h> | |
10 | |
11 #include "base/logging.h" | |
12 #include "skia/ext/image_operations.h" | |
13 #include "ui/base/cursor/cursor.h" | |
14 #include "ui/base/cursor/cursor_util.h" | |
15 #include "ui/base/x/x11_util.h" | |
16 #include "ui/gfx/image/image.h" | |
17 #include "ui/gfx/point_conversions.h" | |
18 #include "ui/gfx/size_conversions.h" | |
19 #include "ui/gfx/skbitmap_operations.h" | |
20 #include "ui/gfx/skia_util.h" | |
21 | |
22 namespace { | |
23 | |
24 // Returns X font cursor shape from an Aura cursor. | |
25 int CursorShapeFromNative(const gfx::NativeCursor& native_cursor) { | |
26 switch (native_cursor.native_type()) { | |
27 case ui::kCursorMiddlePanning: | |
28 return XC_fleur; | |
29 case ui::kCursorEastPanning: | |
30 return XC_sb_right_arrow; | |
31 case ui::kCursorNorthPanning: | |
32 return XC_sb_up_arrow; | |
33 case ui::kCursorNorthEastPanning: | |
34 return XC_top_right_corner; | |
35 case ui::kCursorNorthWestPanning: | |
36 return XC_top_left_corner; | |
37 case ui::kCursorSouthPanning: | |
38 return XC_sb_down_arrow; | |
39 case ui::kCursorSouthEastPanning: | |
40 return XC_bottom_right_corner; | |
41 case ui::kCursorSouthWestPanning: | |
42 return XC_bottom_left_corner; | |
43 case ui::kCursorWestPanning: | |
44 return XC_sb_left_arrow; | |
45 case ui::kCursorNone: | |
46 case ui::kCursorGrab: | |
47 case ui::kCursorGrabbing: | |
48 // TODO(jamescook): Need cursors for these. crbug.com/111650 | |
49 return XC_left_ptr; | |
50 | |
51 #if defined(OS_CHROMEOS) | |
52 case ui::kCursorNull: | |
53 case ui::kCursorPointer: | |
54 case ui::kCursorNoDrop: | |
55 case ui::kCursorNotAllowed: | |
56 case ui::kCursorCopy: | |
57 case ui::kCursorMove: | |
58 case ui::kCursorEastResize: | |
59 case ui::kCursorNorthResize: | |
60 case ui::kCursorSouthResize: | |
61 case ui::kCursorWestResize: | |
62 case ui::kCursorNorthEastResize: | |
63 case ui::kCursorNorthWestResize: | |
64 case ui::kCursorSouthWestResize: | |
65 case ui::kCursorSouthEastResize: | |
66 case ui::kCursorIBeam: | |
67 case ui::kCursorAlias: | |
68 case ui::kCursorCell: | |
69 case ui::kCursorContextMenu: | |
70 case ui::kCursorCross: | |
71 case ui::kCursorHelp: | |
72 case ui::kCursorWait: | |
73 case ui::kCursorNorthSouthResize: | |
74 case ui::kCursorEastWestResize: | |
75 case ui::kCursorNorthEastSouthWestResize: | |
76 case ui::kCursorNorthWestSouthEastResize: | |
77 case ui::kCursorProgress: | |
78 case ui::kCursorColumnResize: | |
79 case ui::kCursorRowResize: | |
80 case ui::kCursorVerticalText: | |
81 case ui::kCursorZoomIn: | |
82 case ui::kCursorZoomOut: | |
83 case ui::kCursorHand: | |
84 // In some environments, the image assets are not set (e.g. in | |
85 // content-browsertests, content-shell etc.). | |
86 return XC_left_ptr; | |
87 #else // defined(OS_CHROMEOS) | |
88 case ui::kCursorNull: | |
89 return XC_left_ptr; | |
90 case ui::kCursorPointer: | |
91 return XC_left_ptr; | |
92 case ui::kCursorMove: | |
93 return XC_fleur; | |
94 case ui::kCursorCross: | |
95 return XC_crosshair; | |
96 case ui::kCursorHand: | |
97 return XC_hand2; | |
98 case ui::kCursorIBeam: | |
99 return XC_xterm; | |
100 case ui::kCursorProgress: | |
101 case ui::kCursorWait: | |
102 return XC_watch; | |
103 case ui::kCursorHelp: | |
104 return XC_question_arrow; | |
105 case ui::kCursorEastResize: | |
106 return XC_right_side; | |
107 case ui::kCursorNorthResize: | |
108 return XC_top_side; | |
109 case ui::kCursorNorthEastResize: | |
110 return XC_top_right_corner; | |
111 case ui::kCursorNorthWestResize: | |
112 return XC_top_left_corner; | |
113 case ui::kCursorSouthResize: | |
114 return XC_bottom_side; | |
115 case ui::kCursorSouthEastResize: | |
116 return XC_bottom_right_corner; | |
117 case ui::kCursorSouthWestResize: | |
118 return XC_bottom_left_corner; | |
119 case ui::kCursorWestResize: | |
120 return XC_left_side; | |
121 case ui::kCursorNorthSouthResize: | |
122 return XC_sb_v_double_arrow; | |
123 case ui::kCursorEastWestResize: | |
124 return XC_sb_h_double_arrow; | |
125 case ui::kCursorColumnResize: | |
126 return XC_sb_h_double_arrow; | |
127 case ui::kCursorRowResize: | |
128 return XC_sb_v_double_arrow; | |
129 #endif // defined(OS_CHROMEOS) | |
130 case ui::kCursorCustom: | |
131 NOTREACHED(); | |
132 return XC_left_ptr; | |
133 } | |
134 NOTREACHED() << "Case not handled for " << native_cursor.native_type(); | |
135 return XC_left_ptr; | |
136 } | |
137 | |
138 } // namespace | |
139 | |
140 namespace ui { | |
141 | |
142 CursorLoader* CursorLoader::Create() { | |
143 return new CursorLoaderX11; | |
144 } | |
145 | |
146 CursorLoaderX11::CursorLoaderX11() | |
147 : invisible_cursor_(CreateInvisibleCursor(), gfx::GetXDisplay()) { | |
148 } | |
149 | |
150 CursorLoaderX11::~CursorLoaderX11() { | |
151 UnloadAll(); | |
152 } | |
153 | |
154 void CursorLoaderX11::LoadImageCursor(int id, | |
155 int resource_id, | |
156 const gfx::Point& hot) { | |
157 SkBitmap bitmap; | |
158 gfx::Point hotspot = hot; | |
159 | |
160 GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap); | |
161 XcursorImage* x_image = SkBitmapToXcursorImage(&bitmap, hotspot); | |
162 cursors_[id] = CreateReffedCustomXCursor(x_image); | |
163 } | |
164 | |
165 void CursorLoaderX11::LoadAnimatedCursor(int id, | |
166 int resource_id, | |
167 const gfx::Point& hot, | |
168 int frame_delay_ms) { | |
169 std::vector<SkBitmap> bitmaps; | |
170 gfx::Point hotspot = hot; | |
171 | |
172 GetAnimatedCursorBitmaps( | |
173 resource_id, scale(), rotation(), &hotspot, &bitmaps); | |
174 | |
175 XcursorImages* x_images = XcursorImagesCreate(bitmaps.size()); | |
176 x_images->nimage = bitmaps.size(); | |
177 | |
178 for (unsigned int frame = 0; frame < bitmaps.size(); ++frame) { | |
179 XcursorImage* x_image = SkBitmapToXcursorImage(&bitmaps[frame], hotspot); | |
180 x_image->delay = frame_delay_ms; | |
181 x_images->images[frame] = x_image; | |
182 } | |
183 | |
184 animated_cursors_[id] = std::make_pair( | |
185 XcursorImagesLoadCursor(gfx::GetXDisplay(), x_images), x_images); | |
186 } | |
187 | |
188 void CursorLoaderX11::UnloadAll() { | |
189 for (ImageCursorMap::const_iterator it = cursors_.begin(); | |
190 it != cursors_.end(); ++it) | |
191 UnrefCustomXCursor(it->second); | |
192 | |
193 // Free animated cursors and images. | |
194 for (AnimatedCursorMap::iterator it = animated_cursors_.begin(); | |
195 it != animated_cursors_.end(); ++it) { | |
196 XcursorImagesDestroy(it->second.second); // also frees individual frames. | |
197 XFreeCursor(gfx::GetXDisplay(), it->second.first); | |
198 } | |
199 } | |
200 | |
201 void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) { | |
202 DCHECK(cursor); | |
203 | |
204 ::Cursor xcursor; | |
205 if (IsImageCursor(*cursor)) | |
206 xcursor = ImageCursorFromNative(*cursor); | |
207 else if (*cursor == kCursorNone) | |
208 xcursor = invisible_cursor_.get(); | |
209 else if (*cursor == kCursorCustom) | |
210 xcursor = cursor->platform(); | |
211 else if (scale() == 1.0f && rotation() == gfx::Display::ROTATE_0) { | |
212 xcursor = GetXCursor(CursorShapeFromNative(*cursor)); | |
213 } else { | |
214 xcursor = ImageCursorFromNative(kCursorPointer); | |
215 } | |
216 | |
217 cursor->SetPlatformCursor(xcursor); | |
218 } | |
219 | |
220 const XcursorImage* CursorLoaderX11::GetXcursorImageForTest(int id) { | |
221 return test::GetCachedXcursorImage(cursors_[id]); | |
222 } | |
223 | |
224 bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) { | |
225 int type = native_cursor.native_type(); | |
226 return cursors_.count(type) || animated_cursors_.count(type); | |
227 } | |
228 | |
229 ::Cursor CursorLoaderX11::ImageCursorFromNative( | |
230 gfx::NativeCursor native_cursor) { | |
231 int type = native_cursor.native_type(); | |
232 if (animated_cursors_.count(type)) | |
233 return animated_cursors_[type].first; | |
234 | |
235 ImageCursorMap::iterator find = cursors_.find(type); | |
236 if (find != cursors_.end()) | |
237 return cursors_[type]; | |
238 return GetXCursor(CursorShapeFromNative(native_cursor)); | |
239 } | |
240 | |
241 } // namespace ui | |
OLD | NEW |