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

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: address comment 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 // Returns X font cursor shape from an Aura cursor.
21 int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
22 switch (native_cursor.native_type()) {
23 case ui::kCursorMiddlePanning:
24 return XC_fleur;
25 case ui::kCursorEastPanning:
26 return XC_sb_right_arrow;
27 case ui::kCursorNorthPanning:
28 return XC_sb_up_arrow;
29 case ui::kCursorNorthEastPanning:
30 return XC_top_right_corner;
31 case ui::kCursorNorthWestPanning:
32 return XC_top_left_corner;
33 case ui::kCursorSouthPanning:
34 return XC_sb_down_arrow;
35 case ui::kCursorSouthEastPanning:
36 return XC_bottom_right_corner;
37 case ui::kCursorSouthWestPanning:
38 return XC_bottom_left_corner;
39 case ui::kCursorWestPanning:
40 return XC_sb_left_arrow;
41 case ui::kCursorNone:
42 case ui::kCursorGrab:
43 case ui::kCursorGrabbing:
44 // TODO(jamescook): Need cursors for these. crbug.com/111650
45 return XC_left_ptr;
46
47 case ui::kCursorNull:
48 case ui::kCursorPointer:
49 case ui::kCursorNoDrop:
50 case ui::kCursorNotAllowed:
51 case ui::kCursorCopy:
52 case ui::kCursorMove:
53 case ui::kCursorEastResize:
54 case ui::kCursorNorthResize:
55 case ui::kCursorSouthResize:
56 case ui::kCursorWestResize:
57 case ui::kCursorNorthEastResize:
58 case ui::kCursorNorthWestResize:
59 case ui::kCursorSouthWestResize:
60 case ui::kCursorSouthEastResize:
61 case ui::kCursorIBeam:
62 case ui::kCursorAlias:
63 case ui::kCursorCell:
64 case ui::kCursorContextMenu:
65 case ui::kCursorCross:
66 case ui::kCursorHelp:
67 case ui::kCursorWait:
68 case ui::kCursorNorthSouthResize:
69 case ui::kCursorEastWestResize:
70 case ui::kCursorNorthEastSouthWestResize:
71 case ui::kCursorNorthWestSouthEastResize:
72 case ui::kCursorProgress:
73 case ui::kCursorColumnResize:
74 case ui::kCursorRowResize:
75 case ui::kCursorVerticalText:
76 case ui::kCursorZoomIn:
77 case ui::kCursorZoomOut:
78 NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should "
79 << "have an image asset.";
80 return XC_left_ptr;
81 case ui::kCursorCustom:
82 NOTREACHED();
83 return XC_left_ptr;
84 }
85 NOTREACHED();
86 return XC_left_ptr;
87 }
88
89 } // namespace
90
91 namespace ui {
92
93 CursorLoader* CursorLoader::Create() {
94 return new CursorLoaderX11;
95 }
96
97 CursorLoaderX11::CursorLoaderX11()
98 : invisible_cursor_(0U) {
99 Display* xdisplay = ui::GetXDisplay();
100 // Initialize invisible cursor.
101 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
102 XColor black;
103 black.red = black.green = black.blue = 0;
104 Pixmap blank = XCreateBitmapFromData(xdisplay, DefaultRootWindow(xdisplay),
105 nodata, 8, 8);
106 invisible_cursor_ = XCreatePixmapCursor(xdisplay, blank, blank,
107 &black, &black, 0, 0);
108 XFreePixmap(xdisplay, blank);
oshima 2012/09/07 19:52:01 There is a leak inside pixmap, so you probably hav
mazda 2012/09/07 22:38:14 Thanks. I'll do it.
109 }
110
111 CursorLoaderX11::~CursorLoaderX11() {
112 UnloadAll();
113 // Clears XCursorCache.
114 ui::GetXCursor(ui::kCursorClearXCursorCache);
115
116 XFreeCursor(ui::GetXDisplay(), invisible_cursor_);
117 }
118
119 void CursorLoaderX11::LoadImageCursor(
120 int id, int resource_id, int hot_x, int hot_y) {
121 const gfx::ImageSkia* image =
122 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
123 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
124 ui::GetScaleFactorFromScale(device_scale_factor()));
125 gfx::Point hot(hot_x * device_scale_factor(), hot_y * device_scale_factor());
126 XcursorImage* x_image =
127 ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot);
128 cursors_[id] = ui::CreateReffedCustomXCursor(x_image);
129 // |bitmap| is owned by the resource bundle. So we do not need to free it.
130 }
131
132 void CursorLoaderX11::LoadAnimatedCursor(
133 int id, int resource_id, int hot_x, int hot_y, int frame_delay_ms) {
134 const gfx::ImageSkia* image =
135 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
136 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
137 ui::GetScaleFactorFromScale(device_scale_factor()));
138 const SkBitmap bitmap = image_rep.sk_bitmap();
139 DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config);
140 int frame_width = bitmap.height();
141 int frame_height = frame_width;
142 int total_width = bitmap.width();
143 DCHECK_EQ(total_width % frame_width, 0);
144 int frame_count = total_width / frame_width;
145 DCHECK_GT(frame_count, 0);
146 XcursorImages* x_images = XcursorImagesCreate(frame_count);
147 x_images->nimage = frame_count;
148 bitmap.lockPixels();
149 unsigned int* pixels = bitmap.getAddr32(0, 0);
150 // Create each frame.
151 for (int i = 0; i < frame_count; ++i) {
152 XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height);
153 for (int j = 0; j < frame_height; ++j) {
154 // Copy j'th row of i'th frame.
155 memcpy(x_image->pixels + j * frame_width,
156 pixels + i * frame_width + j * total_width,
157 frame_width * 4);
158 }
159 x_image->xhot = hot_x * device_scale_factor();
160 x_image->yhot = hot_y * device_scale_factor();
161 x_image->delay = frame_delay_ms;
162 x_images->images[i] = x_image;
163 }
164 bitmap.unlockPixels();
165
166 animated_cursors_[id] = std::make_pair(
167 XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images);
168 // |bitmap| is owned by the resource bundle. So we do not need to free it.
169 }
170
171 void CursorLoaderX11::UnloadAll() {
172 for (ImageCursorMap::const_iterator it = cursors_.begin();
173 it != cursors_.end(); ++it)
174 ui::UnrefCustomXCursor(it->second);
175
176 // Free animated cursors and images.
177 for (AnimatedCursorMap::iterator it = animated_cursors_.begin();
178 it != animated_cursors_.end(); ++it) {
179 XcursorImagesDestroy(it->second.second); // also frees individual frames.
180 XFreeCursor(ui::GetXDisplay(), it->second.first);
181 }
182 }
183
184 void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) {
185 DCHECK(cursor);
186
187 ::Cursor xcursor;
188 if (IsImageCursor(*cursor))
189 xcursor = ImageCursorFromNative(*cursor);
190 else if (*cursor == ui::kCursorNone)
191 xcursor = invisible_cursor_;
192 else if (*cursor == ui::kCursorCustom)
193 xcursor = cursor->platform();
194 else if (device_scale_factor() == 1.0f)
195 xcursor = ui::GetXCursor(CursorShapeFromNative(*cursor));
196 else
197 xcursor = ImageCursorFromNative(ui::kCursorPointer);
198
199 cursor->SetPlatformCursor(xcursor);
200 }
201
202 void CursorLoaderX11::HideHostCursor() {
203 XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()),
204 invisible_cursor_);
205 }
206
207 bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) {
208 int type = native_cursor.native_type();
209 return cursors_.find(type) != cursors_.end() ||
210 animated_cursors_.find(type) != animated_cursors_.end();
211 }
212
213 ::Cursor CursorLoaderX11::ImageCursorFromNative(
214 gfx::NativeCursor native_cursor) {
215 int type = native_cursor.native_type();
216 if (animated_cursors_.count(type))
217 return animated_cursors_[type].first;
218 DCHECK(cursors_.find(type) != cursors_.end());
219 return cursors_[type];
220 }
221
222 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698