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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ui/base/cursor/cursor_loader_x11.cc
diff --git a/ui/base/cursor/cursor_loader_x11.cc b/ui/base/cursor/cursor_loader_x11.cc
new file mode 100644
index 0000000000000000000000000000000000000000..65ba578d2736a11c81c7959a36c426417602a367
--- /dev/null
+++ b/ui/base/cursor/cursor_loader_x11.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/cursor/cursor_loader_x11.h"
+
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+
+#include "base/logging.h"
+#include "grit/ui_resources.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace {
+
+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.
+
+// Returns X font cursor shape from an Aura cursor.
+int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
+ switch (native_cursor.native_type()) {
+ case ui::kCursorMiddlePanning:
+ return XC_fleur;
+ case ui::kCursorEastPanning:
+ return XC_sb_right_arrow;
+ case ui::kCursorNorthPanning:
+ return XC_sb_up_arrow;
+ case ui::kCursorNorthEastPanning:
+ return XC_top_right_corner;
+ case ui::kCursorNorthWestPanning:
+ return XC_top_left_corner;
+ case ui::kCursorSouthPanning:
+ return XC_sb_down_arrow;
+ case ui::kCursorSouthEastPanning:
+ return XC_bottom_right_corner;
+ case ui::kCursorSouthWestPanning:
+ return XC_bottom_left_corner;
+ case ui::kCursorWestPanning:
+ return XC_sb_left_arrow;
+ case ui::kCursorNone:
+ case ui::kCursorGrab:
+ case ui::kCursorGrabbing:
+ // TODO(jamescook): Need cursors for these. crbug.com/111650
+ return XC_left_ptr;
+
+ case ui::kCursorNull:
+ case ui::kCursorPointer:
+ case ui::kCursorNoDrop:
+ case ui::kCursorNotAllowed:
+ case ui::kCursorCopy:
+ case ui::kCursorMove:
+ case ui::kCursorEastResize:
+ case ui::kCursorNorthResize:
+ case ui::kCursorSouthResize:
+ case ui::kCursorWestResize:
+ case ui::kCursorNorthEastResize:
+ case ui::kCursorNorthWestResize:
+ case ui::kCursorSouthWestResize:
+ case ui::kCursorSouthEastResize:
+ case ui::kCursorIBeam:
+ case ui::kCursorAlias:
+ case ui::kCursorCell:
+ case ui::kCursorContextMenu:
+ case ui::kCursorCross:
+ case ui::kCursorHelp:
+ case ui::kCursorWait:
+ case ui::kCursorNorthSouthResize:
+ case ui::kCursorEastWestResize:
+ case ui::kCursorNorthEastSouthWestResize:
+ case ui::kCursorNorthWestSouthEastResize:
+ case ui::kCursorProgress:
+ case ui::kCursorColumnResize:
+ case ui::kCursorRowResize:
+ case ui::kCursorVerticalText:
+ case ui::kCursorZoomIn:
+ case ui::kCursorZoomOut:
+ NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should "
+ << "have an image asset.";
+ return XC_left_ptr;
+ case ui::kCursorCustom:
+ NOTREACHED();
+ return XC_left_ptr;
+ }
+ NOTREACHED();
+ return XC_left_ptr;
+}
+
+} // namespace
+
+namespace ui {
+
+CursorLoader* CursorLoader::Create() {
+ return new CursorLoaderX11;
+}
+
+CursorLoaderX11::CursorLoaderX11()
+ : invisible_cursor_(0U) {
+ Display* xdisplay = ui::GetXDisplay();
+ // Initialize invisible cursor.
+ char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ XColor black;
+ black.red = black.green = black.blue = 0;
+ Pixmap blank = XCreateBitmapFromData(xdisplay, DefaultRootWindow(xdisplay),
+ nodata, 8, 8);
+ invisible_cursor_ = XCreatePixmapCursor(xdisplay, blank, blank,
+ &black, &black, 0, 0);
+ XFreePixmap(xdisplay, blank);
+}
+
+CursorLoaderX11::~CursorLoaderX11() {
+ UnloadAll();
+ // Clears XCursorCache.
+ ui::GetXCursor(ui::kCursorClearXCursorCache);
+
+ XFreeCursor(ui::GetXDisplay(), invisible_cursor_);
+}
+
+void CursorLoaderX11::LoadImageCursor(
+ int id, int resource_id, int hot_x, int hot_y) {
+ const gfx::ImageSkia* image =
+ ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
+ const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
+ ui::GetScaleFactorFromScale(device_scale_factor()));
+ gfx::Point hot(hot_x * device_scale_factor(), hot_y * device_scale_factor());
+ XcursorImage* x_image =
+ ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot);
+ cursors_[id] = ui::CreateReffedCustomXCursor(x_image);
+ // |bitmap| is owned by the resource bundle. So we do not need to free it.
+}
+
+// Creates an animated X Cursor from an image resource and puts it in the
+// cursor map. The image is assumed to be a concatenation of animation frames.
+// Also, each frame is assumed to be square (width == height)
+void CursorLoaderX11::LoadAnimatedCursor(
+ int id, int resource_id, int hot_x, int hot_y) {
+ const gfx::ImageSkia* image =
+ ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
+ const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
+ ui::GetScaleFactorFromScale(device_scale_factor()));
+ const SkBitmap bitmap = image_rep.sk_bitmap();
+ DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config);
+ int frame_width = bitmap.height();
+ int frame_height = frame_width;
+ int total_width = bitmap.width();
+ DCHECK_EQ(total_width % frame_width, 0);
+ int frame_count = total_width / frame_width;
+ DCHECK_GT(frame_count, 0);
+ XcursorImages* x_images = XcursorImagesCreate(frame_count);
+ x_images->nimage = frame_count;
+ bitmap.lockPixels();
+ unsigned int* pixels = bitmap.getAddr32(0, 0);
+ // Create each frame.
+ for (int i = 0; i < frame_count; ++i) {
+ XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height);
+ for (int j = 0; j < frame_height; ++j) {
+ // Copy j'th row of i'th frame.
+ memcpy(x_image->pixels + j * frame_width,
+ pixels + i * frame_width + j * total_width,
+ frame_width * 4);
+ }
+ x_image->xhot = hot_x * device_scale_factor();
+ x_image->yhot = hot_y * device_scale_factor();
+ x_image->delay = kAnimatedCursorFrameDelayMs;
+ x_images->images[i] = x_image;
+ }
+ bitmap.unlockPixels();
+
+ animated_cursors_[id] = std::make_pair(
+ XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images);
+ // |bitmap| is owned by the resource bundle. So we do not need to free it.
+}
+
+void CursorLoaderX11::UnloadAll() {
+ for (ImageCursorMap::const_iterator it = cursors_.begin();
+ it != cursors_.end(); ++it)
+ ui::UnrefCustomXCursor(it->second);
+
+ // Free animated cursors and images.
+ for (AnimatedCursorMap::iterator it = animated_cursors_.begin();
+ it != animated_cursors_.end(); ++it) {
+ XcursorImagesDestroy(it->second.second); // also frees individual frames.
+ XFreeCursor(ui::GetXDisplay(), it->second.first);
+ }
+}
+
+void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) {
+ DCHECK(cursor);
+
+ ::Cursor xcursor;
+ if (IsImageCursor(*cursor))
+ xcursor = ImageCursorFromNative(*cursor);
+ else if (*cursor == ui::kCursorNone)
+ xcursor = invisible_cursor_;
Daniel Erat 2012/09/06 23:47:15 nit: delete extra space after '='
mazda 2012/09/07 02:20:57 Done.
+ else if (*cursor == ui::kCursorCustom)
+ xcursor = cursor->platform();
+ else if (device_scale_factor() == 1.0f)
+ xcursor = ui::GetXCursor(CursorShapeFromNative(*cursor));
+ else
+ xcursor = ImageCursorFromNative(ui::kCursorPointer);
+
+ cursor->SetPlatformCursor(xcursor);
+}
+
+void CursorLoaderX11::HideHostCursor() {
+ XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()),
+ invisible_cursor_);
+}
+
+bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) {
+ int type = native_cursor.native_type();
+ return cursors_.find(type) != cursors_.end() ||
+ animated_cursors_.find(type) != animated_cursors_.end();
+}
+
+::Cursor CursorLoaderX11::ImageCursorFromNative(
+ gfx::NativeCursor native_cursor) {
+ int type = native_cursor.native_type();
+ 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.
+ return animated_cursors_[type].first;
+ DCHECK(cursors_.find(type) != cursors_.end());
+ return cursors_[type];
+}
+
+}

Powered by Google App Engine
This is Rietveld 408576698