Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: ui/base/cursor/cursor_loader_x11.cc

Issue 10919135: Move ash specific cursor code to CursorManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 <X11/Xlib.h>
8 #include <X11/cursorfont.h>
9
10 #include "base/logging.h"
11 #include "grit/ui_resources.h"
12 #include "ui/base/cursor/cursor.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/base/x/x11_util.h"
15 #include "ui/gfx/image/image.h"
16 #include "ui/gfx/image/image_skia.h"
17
18 namespace {
19
20 const int kAnimatedCursorFrameDelayMs = 25;
Daniel Erat 2012/09/06 23:47:15 This seems like it should be a parameter to LoadAn
mazda 2012/09/07 02:20:57 Done.
21
22 // Returns X font cursor shape from an Aura cursor.
23 int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
24 switch (native_cursor.native_type()) {
25 case ui::kCursorMiddlePanning:
26 return XC_fleur;
27 case ui::kCursorEastPanning:
28 return XC_sb_right_arrow;
29 case ui::kCursorNorthPanning:
30 return XC_sb_up_arrow;
31 case ui::kCursorNorthEastPanning:
32 return XC_top_right_corner;
33 case ui::kCursorNorthWestPanning:
34 return XC_top_left_corner;
35 case ui::kCursorSouthPanning:
36 return XC_sb_down_arrow;
37 case ui::kCursorSouthEastPanning:
38 return XC_bottom_right_corner;
39 case ui::kCursorSouthWestPanning:
40 return XC_bottom_left_corner;
41 case ui::kCursorWestPanning:
42 return XC_sb_left_arrow;
43 case ui::kCursorNone:
44 case ui::kCursorGrab:
45 case ui::kCursorGrabbing:
46 // TODO(jamescook): Need cursors for these. crbug.com/111650
47 return XC_left_ptr;
48
49 case ui::kCursorNull:
50 case ui::kCursorPointer:
51 case ui::kCursorNoDrop:
52 case ui::kCursorNotAllowed:
53 case ui::kCursorCopy:
54 case ui::kCursorMove:
55 case ui::kCursorEastResize:
56 case ui::kCursorNorthResize:
57 case ui::kCursorSouthResize:
58 case ui::kCursorWestResize:
59 case ui::kCursorNorthEastResize:
60 case ui::kCursorNorthWestResize:
61 case ui::kCursorSouthWestResize:
62 case ui::kCursorSouthEastResize:
63 case ui::kCursorIBeam:
64 case ui::kCursorAlias:
65 case ui::kCursorCell:
66 case ui::kCursorContextMenu:
67 case ui::kCursorCross:
68 case ui::kCursorHelp:
69 case ui::kCursorWait:
70 case ui::kCursorNorthSouthResize:
71 case ui::kCursorEastWestResize:
72 case ui::kCursorNorthEastSouthWestResize:
73 case ui::kCursorNorthWestSouthEastResize:
74 case ui::kCursorProgress:
75 case ui::kCursorColumnResize:
76 case ui::kCursorRowResize:
77 case ui::kCursorVerticalText:
78 case ui::kCursorZoomIn:
79 case ui::kCursorZoomOut:
80 NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should "
81 << "have an image asset.";
82 return XC_left_ptr;
83 case ui::kCursorCustom:
84 NOTREACHED();
85 return XC_left_ptr;
86 }
87 NOTREACHED();
88 return XC_left_ptr;
89 }
90
91 } // namespace
92
93 namespace ui {
94
95 CursorLoader* CursorLoader::Create() {
96 return new CursorLoaderX11;
97 }
98
99 CursorLoaderX11::CursorLoaderX11()
100 : invisible_cursor_(0U) {
101 Display* xdisplay = ui::GetXDisplay();
102 // Initialize invisible cursor.
103 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
104 XColor black;
105 black.red = black.green = black.blue = 0;
106 Pixmap blank = XCreateBitmapFromData(xdisplay, DefaultRootWindow(xdisplay),
107 nodata, 8, 8);
108 invisible_cursor_ = XCreatePixmapCursor(xdisplay, blank, blank,
109 &black, &black, 0, 0);
110 XFreePixmap(xdisplay, blank);
111 }
112
113 CursorLoaderX11::~CursorLoaderX11() {
114 UnloadAll();
115 // Clears XCursorCache.
116 ui::GetXCursor(ui::kCursorClearXCursorCache);
117
118 XFreeCursor(ui::GetXDisplay(), invisible_cursor_);
119 }
120
121 void CursorLoaderX11::LoadImageCursor(
122 int id, int resource_id, int hot_x, int hot_y) {
123 const gfx::ImageSkia* image =
124 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
125 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
126 ui::GetScaleFactorFromScale(device_scale_factor()));
127 gfx::Point hot(hot_x * device_scale_factor(), hot_y * device_scale_factor());
128 XcursorImage* x_image =
129 ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot);
130 cursors_[id] = ui::CreateReffedCustomXCursor(x_image);
131 // |bitmap| is owned by the resource bundle. So we do not need to free it.
132 }
133
134 // Creates an animated X Cursor from an image resource and puts it in the
135 // cursor map. The image is assumed to be a concatenation of animation frames.
136 // Also, each frame is assumed to be square (width == height)
137 void CursorLoaderX11::LoadAnimatedCursor(
138 int id, int resource_id, int hot_x, int hot_y) {
139 const gfx::ImageSkia* image =
140 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
141 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
142 ui::GetScaleFactorFromScale(device_scale_factor()));
143 const SkBitmap bitmap = image_rep.sk_bitmap();
144 DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config);
145 int frame_width = bitmap.height();
146 int frame_height = frame_width;
147 int total_width = bitmap.width();
148 DCHECK_EQ(total_width % frame_width, 0);
149 int frame_count = total_width / frame_width;
150 DCHECK_GT(frame_count, 0);
151 XcursorImages* x_images = XcursorImagesCreate(frame_count);
152 x_images->nimage = frame_count;
153 bitmap.lockPixels();
154 unsigned int* pixels = bitmap.getAddr32(0, 0);
155 // Create each frame.
156 for (int i = 0; i < frame_count; ++i) {
157 XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height);
158 for (int j = 0; j < frame_height; ++j) {
159 // Copy j'th row of i'th frame.
160 memcpy(x_image->pixels + j * frame_width,
161 pixels + i * frame_width + j * total_width,
162 frame_width * 4);
163 }
164 x_image->xhot = hot_x * device_scale_factor();
165 x_image->yhot = hot_y * device_scale_factor();
166 x_image->delay = kAnimatedCursorFrameDelayMs;
167 x_images->images[i] = x_image;
168 }
169 bitmap.unlockPixels();
170
171 animated_cursors_[id] = std::make_pair(
172 XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images);
173 // |bitmap| is owned by the resource bundle. So we do not need to free it.
174 }
175
176 void CursorLoaderX11::UnloadAll() {
177 for (ImageCursorMap::const_iterator it = cursors_.begin();
178 it != cursors_.end(); ++it)
179 ui::UnrefCustomXCursor(it->second);
180
181 // Free animated cursors and images.
182 for (AnimatedCursorMap::iterator it = animated_cursors_.begin();
183 it != animated_cursors_.end(); ++it) {
184 XcursorImagesDestroy(it->second.second); // also frees individual frames.
185 XFreeCursor(ui::GetXDisplay(), it->second.first);
186 }
187 }
188
189 void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) {
190 DCHECK(cursor);
191
192 ::Cursor xcursor;
193 if (IsImageCursor(*cursor))
194 xcursor = ImageCursorFromNative(*cursor);
195 else if (*cursor == ui::kCursorNone)
196 xcursor = invisible_cursor_;
Daniel Erat 2012/09/06 23:47:15 nit: delete extra space after '='
mazda 2012/09/07 02:20:57 Done.
197 else if (*cursor == ui::kCursorCustom)
198 xcursor = cursor->platform();
199 else if (device_scale_factor() == 1.0f)
200 xcursor = ui::GetXCursor(CursorShapeFromNative(*cursor));
201 else
202 xcursor = ImageCursorFromNative(ui::kCursorPointer);
203
204 cursor->SetPlatformCursor(xcursor);
205 }
206
207 void CursorLoaderX11::HideHostCursor() {
208 XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()),
209 invisible_cursor_);
210 }
211
212 bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) {
213 int type = native_cursor.native_type();
214 return cursors_.find(type) != cursors_.end() ||
215 animated_cursors_.find(type) != animated_cursors_.end();
216 }
217
218 ::Cursor CursorLoaderX11::ImageCursorFromNative(
219 gfx::NativeCursor native_cursor) {
220 int type = native_cursor.native_type();
221 if (animated_cursors_.find(type) != animated_cursors_.end())
Daniel Erat 2012/09/06 23:47:15 nit: if you're not going to do anything with the i
mazda 2012/09/07 02:20:57 Done.
222 return animated_cursors_[type].first;
223 DCHECK(cursors_.find(type) != cursors_.end());
224 return cursors_[type];
225 }
226
227 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698