Index: ui/aura/root_window_host_linux.cc |
diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc |
index 51d1013ef804b651b7b96a4c66895179dec4171b..b2c3366deca132f4963f8d724c3f0efdbcf593a7 100644 |
--- a/ui/aura/root_window_host_linux.cc |
+++ b/ui/aura/root_window_host_linux.cc |
@@ -5,6 +5,7 @@ |
#include "ui/aura/root_window_host_linux.h" |
#include <X11/Xatom.h> |
+#include <X11/Xcursor/Xcursor.h> |
#include <X11/cursorfont.h> |
#include <X11/extensions/XInput2.h> |
#include <X11/extensions/Xfixes.h> |
@@ -14,6 +15,9 @@ |
#include "base/message_pump_x.h" |
#include "base/stl_util.h" |
#include "base/stringprintf.h" |
+#include "grit/ui_resources_standard.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "third_party/skia/include/core/SkUnPreMultiply.h" |
#include "ui/aura/client/user_gesture_client.h" |
#include "ui/aura/dispatcher_linux.h" |
#include "ui/aura/env.h" |
@@ -21,10 +25,12 @@ |
#include "ui/aura/root_window.h" |
#include "ui/base/cursor/cursor.h" |
#include "ui/base/keycodes/keyboard_codes.h" |
+#include "ui/base/resource/resource_bundle.h" |
#include "ui/base/touch/touch_factory.h" |
#include "ui/base/x/x11_util.h" |
#include "ui/base/view_prop.h" |
#include "ui/gfx/compositor/layer.h" |
+#include "ui/gfx/image/image.h" |
using std::max; |
using std::min; |
@@ -292,6 +298,84 @@ const char* kAtomList[] = { |
} // namespace |
+// A utility class that provides X Cursor for NativeCursors for which we have |
+// image resources. |
+class RootWindowHostLinux::ImageCursors { |
+ public: |
+ explicit ImageCursors(Display* xdisplay) |
+ : xdisplay_(xdisplay) { |
+ LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP); |
+ LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY); |
+ // TODO (varunjain): add more cursors once we have assets. |
+ } |
+ |
+ virtual ~ImageCursors() { |
sky
2012/05/03 19:12:52
no virtual.
varunjain
2012/05/03 19:48:54
Done.
|
+ std::map<int, std::pair<Cursor, XcursorImage*> >::const_iterator it; |
+ for (it = cursors_.begin(); it != cursors_.end(); it++) { |
sky
2012/05/03 19:12:52
++it
varunjain
2012/05/03 19:48:54
Done.
|
+ XFreeCursor(xdisplay_, it->second.first); |
sail
2012/05/03 18:11:05
instead of doing your own reference counting can y
varunjain
2012/05/03 19:48:54
Done with ui::CreateReffedXCursor()
|
+ XcursorImageDestroy(it->second.second); |
+ } |
+ } |
+ |
+ // Returns true if we have an image resource loaded for the |native_cursor|. |
+ bool IsImageCursor(gfx::NativeCursor native_cursor) { |
+ return cursors_.find(native_cursor.native_type()) != cursors_.end(); |
+ } |
+ |
+ // Gets the X Cursor corresponding to the |native_cursor|. |
+ ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) { |
+ DCHECK(cursors_.find(native_cursor.native_type()) != cursors_.end()); |
+ return cursors_[native_cursor.native_type()].first; |
+ } |
+ |
+ private: |
+ // Creates an X Cursor from an image resource and puts it in the cursor map. |
+ void LoadImageCursor(int id, int resource_id) { |
+ const SkBitmap* bitmap = |
+ ui::ResourceBundle::GetSharedInstance().GetBitmapNamed(resource_id); |
sky
2012/05/03 19:12:52
GetBitmapNamed is deprecated, and as far as I know
varunjain
2012/05/03 19:48:54
Done.
|
+ if (bitmap->isNull()) |
+ return; |
+ |
+ DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config); |
+ XcursorImage* image = XcursorImageCreate(bitmap->width(), bitmap->height()); |
+ image->xhot = 0; |
+ image->yhot = 0; |
+ uint32* pixels = image->pixels; |
+ |
+ bitmap->lockPixels(); |
+ if (bitmap->width() && bitmap->height()) { |
+ int height = bitmap->height(), width = bitmap->width(); |
sail
2012/05/03 18:11:05
width,height should be on separate lines
varunjain
2012/05/03 19:48:54
Done.
|
+ for (int y = 0, i = 0; y < height; y++) { |
+ for (int x = 0; x < width; x++) { |
+ uint32 pixel = bitmap->getAddr32(0, y)[x]; |
sail
2012/05/03 18:11:05
this code seems to duplicate WebCursor::GetPlatfor
varunjain
2012/05/03 19:48:54
Done.
|
+ int alpha = SkColorGetA(pixel); |
+ if (alpha != 0 && alpha != 255) |
+ pixels[i] = SkUnPreMultiply::PMColorToColor(pixel); |
sky
2012/05/03 19:12:52
Don't we have code like this some where already?
varunjain
2012/05/03 19:48:54
Done.
|
+ else |
+ pixels[i] = pixel; |
+ ++i; |
+ } |
+ } |
+ } |
+ bitmap->unlockPixels(); |
+ |
+ cursors_[id] = std::make_pair( |
+ XcursorImageLoadCursor(xdisplay_, image), image); |
+ |
+ // |bitmap| is owned by the resource bundle. So we do not need to free it. |
+ } |
+ |
+ // A map to hold all image cursors. It maps the cursor ID to the cursor |
+ // object, where, the cursor object consists of the actual X Cursor and the |
+ // XcursorImage. We need to keep the images as well to be able to free them |
+ // on destruction. |
+ std::map<int, std::pair<Cursor, XcursorImage*> > cursors_; |
+ |
+ Display* xdisplay_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ImageCursors); |
+}; |
+ |
RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) |
: root_window_(NULL), |
xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
@@ -301,7 +385,8 @@ RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) |
cursor_shown_(true), |
bounds_(bounds), |
focus_when_shown_(false), |
- pointer_barriers_(NULL) { |
+ pointer_barriers_(NULL), |
+ image_cursors_(new ImageCursors(xdisplay_)) { |
XSetWindowAttributes swa; |
memset(&swa, 0, sizeof(swa)); |
swa.background_pixmap = None; |
@@ -795,6 +880,8 @@ bool RootWindowHostLinux::IsWindowManagerPresent() { |
void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { |
::Cursor xcursor = |
+ image_cursors_->IsImageCursor(cursor) ? |
+ image_cursors_->ImageCursorFromNative(cursor) : |
cursor == ui::kCursorNone ? |
invisible_cursor_ : |
cursor == ui::kCursorCustom ? |