Aura: Combine cursor support for Linux and Windows

+ Change gfx::NativeCursor to an int id on Aura.
+ Fix several cursor-related TODOs in GetCursor() methods.
+ Move X11 cursor cache into x11_util
+ Set platform-specific cursors in aura::DesktopHostWin and DesktopHostLinux

BUG=99871
TEST=manual

Review URL: http://codereview.chromium.org/8256001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105850 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 5a9013c..52b76d2 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -38,6 +38,10 @@
 #include "ui/gfx/gtk_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/cursor.h"
+#endif
+
 // If we don't clamp the maximum width, then very long URLs and titles can make
 // the bubble arbitrarily wide.
 const int kMaxContentsWidth = 500;
@@ -90,12 +94,11 @@
 
 gfx::NativeCursor ContentSettingBubbleContents::Favicon::GetCursor(
     const views::MouseEvent& event) {
-#if defined(OS_WIN)
+#if defined(USE_AURA)
+  return aura::kCursorHand;
+#elif defined(OS_WIN)
   static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_HAND);
   return g_hand_cursor;
-#elif defined(USE_AURA)
-  // TODO(saintlou):
-  return gfx::kNullCursor;
 #elif defined(TOOLKIT_USES_GTK)
   return gfx::GetCursor(GDK_HAND2);
 #endif
diff --git a/ui/aura/cursor.h b/ui/aura/cursor.h
index f8e8dda..33664e8 100644
--- a/ui/aura/cursor.h
+++ b/ui/aura/cursor.h
@@ -6,17 +6,60 @@
 #define UI_AURA_CURSOR_H_
 #pragma once
 
-#include "ui/aura/aura_export.h"
-
 namespace aura {
 
-enum AURA_EXPORT CursorType {
-  CURSOR_POINTER,
-  CURSOR_LINK,
-  CURSOR_WAIT,
-  CURSOR_SIZE_HORIZONTAL,
-  CURSOR_SIZE_VERTICAL
-};
+// TODO(jamescook): Once we're on C++0x we could change these constants
+// to an enum and forward declare it in native_widget_types.h.
+
+// Equivalent to a NULL HCURSOR on Windows.
+const int kCursorNull = 0;
+
+// Aura cursors mirror WebKit cursors from WebCursorInfo, but are replicated
+// here so we don't introduce a WebKit dependency.
+const int kCursorPointer = 1;
+const int kCursorCross = 2;
+const int kCursorHand = 3;
+const int kCursorIBeam = 4;
+const int kCursorWait = 5;
+const int kCursorHelp = 6;
+const int kCursorEastResize = 7;
+const int kCursorNorthResize = 8;
+const int kCursorNorthEastResize = 9;
+const int kCursorNorthWestResize = 10;
+const int kCursorSouthResize = 11;
+const int kCursorSouthEastResize = 12;
+const int kCursorSouthWestResize = 13;
+const int kCursorWestResize = 14;
+const int kCursorNorthSouthResize = 15;
+const int kCursorEastWestResize = 16;
+const int kCursorNorthEastSouthWestResize = 17;
+const int kCursorNorthWestSouthEastResize = 18;
+const int kCursorColumnResize = 19;
+const int kCursorRowResize = 20;
+const int kCursorMiddlePanning = 21;
+const int kCursorEastPanning = 22;
+const int kCursorNorthPanning = 23;
+const int kCursorNorthEastPanning = 24;
+const int kCursorNorthWestPanning = 25;
+const int kCursorSouthPanning = 26;
+const int kCursorSouthEastPanning = 27;
+const int kCursorSouthWestPanning = 28;
+const int kCursorWestPanning = 29;
+const int kCursorMove = 30;
+const int kCursorVerticalText = 31;
+const int kCursorCell = 32;
+const int kCursorContextMenu = 33;
+const int kCursorAlias = 34;
+const int kCursorProgress = 35;
+const int kCursorNoDrop = 36;
+const int kCursorCopy = 37;
+const int kCursorNone = 38;
+const int kCursorNotAllowed = 39;
+const int kCursorZoomIn = 40;
+const int kCursorZoomOut = 41;
+const int kCursorGrab = 42;
+const int kCursorGrabbing = 43;
+const int kCursorCustom = 44;
 
 }  // namespace aura
 
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index 335b298..7522fba5 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -38,7 +38,7 @@
     return false;
   }
   virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
-    return NULL;
+    return gfx::kNullCursor;
   }
   virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
     return HTCAPTION;
diff --git a/ui/aura/desktop_host_linux.cc b/ui/aura/desktop_host_linux.cc
index c0fc3cc..ff2d6aa 100644
--- a/ui/aura/desktop_host_linux.cc
+++ b/ui/aura/desktop_host_linux.cc
@@ -6,16 +6,107 @@
 
 #include "base/message_loop.h"
 #include "base/message_pump_x.h"
+#include "ui/aura/cursor.h"
 #include "ui/aura/desktop.h"
 #include "ui/aura/event.h"
 #include "ui/base/touch/touch_factory.h"
+#include "ui/base/x/x11_util.h"
 
+#include <X11/cursorfont.h>
 #include <X11/Xlib.h>
 
 namespace aura {
 
 namespace {
 
+// Returns X font cursor shape from an Aura cursor.
+int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
+  switch (native_cursor) {
+    case aura::kCursorNull:
+      return XC_left_ptr;
+    case aura::kCursorPointer:
+      return XC_left_ptr;
+    case aura::kCursorCross:
+      return XC_crosshair;
+    case aura::kCursorHand:
+      return XC_hand2;
+    case aura::kCursorIBeam:
+      return XC_xterm;
+    case aura::kCursorWait:
+      return XC_watch;
+    case aura::kCursorHelp:
+      return XC_question_arrow;
+    case aura::kCursorEastResize:
+      return XC_right_side;
+    case aura::kCursorNorthResize:
+      return XC_top_side;
+    case aura::kCursorNorthEastResize:
+      return XC_top_right_corner;
+    case aura::kCursorNorthWestResize:
+      return XC_top_left_corner;
+    case aura::kCursorSouthResize:
+      return XC_bottom_side;
+    case aura::kCursorSouthEastResize:
+      return XC_bottom_right_corner;
+    case aura::kCursorSouthWestResize:
+      return XC_bottom_left_corner;
+    case aura::kCursorWestResize:
+      return XC_left_side;
+    case aura::kCursorNorthSouthResize:
+      return XC_sb_v_double_arrow;
+    case aura::kCursorEastWestResize:
+      return XC_sb_h_double_arrow;
+    case aura::kCursorNorthEastSouthWestResize:
+    case aura::kCursorNorthWestSouthEastResize:
+      // There isn't really a useful cursor available for these.
+      NOTIMPLEMENTED();
+      return XC_left_ptr;
+    case aura::kCursorColumnResize:
+      return XC_sb_h_double_arrow;
+    case aura::kCursorRowResize:
+      return XC_sb_v_double_arrow;
+    case aura::kCursorMiddlePanning:
+      return XC_fleur;
+    case aura::kCursorEastPanning:
+      return XC_sb_right_arrow;
+    case aura::kCursorNorthPanning:
+      return XC_sb_up_arrow;
+    case aura::kCursorNorthEastPanning:
+      return XC_top_right_corner;
+    case aura::kCursorNorthWestPanning:
+      return XC_top_left_corner;
+    case aura::kCursorSouthPanning:
+      return XC_sb_down_arrow;
+    case aura::kCursorSouthEastPanning:
+      return XC_bottom_right_corner;
+    case aura::kCursorSouthWestPanning:
+      return XC_bottom_left_corner;
+    case aura::kCursorWestPanning:
+      return XC_sb_left_arrow;
+    case aura::kCursorMove:
+      return XC_fleur;
+    case aura::kCursorVerticalText:
+    case aura::kCursorCell:
+    case aura::kCursorContextMenu:
+    case aura::kCursorAlias:
+    case aura::kCursorProgress:
+    case aura::kCursorNoDrop:
+    case aura::kCursorCopy:
+    case aura::kCursorNone:
+    case aura::kCursorNotAllowed:
+    case aura::kCursorZoomIn:
+    case aura::kCursorZoomOut:
+    case aura::kCursorGrab:
+    case aura::kCursorGrabbing:
+    case aura::kCursorCustom:
+      // TODO(jamescook): Need cursors for these.
+      NOTIMPLEMENTED();
+      return XC_left_ptr;
+  }
+  NOTREACHED();
+  return XC_left_ptr;
+}
+
 class DesktopHostLinux : public DesktopHost {
  public:
   explicit DesktopHostLinux(const gfx::Rect& bounds);
@@ -39,7 +130,9 @@
   // The display and the native X window hosting the desktop.
   Display* xdisplay_;
   ::Window xwindow_;
-  Cursor xcursor_;
+
+  // Current Aura cursor.
+  gfx::NativeCursor current_cursor_;
 
   // The size of |xwindow_|.
   gfx::Rect bounds_;
@@ -51,7 +144,7 @@
     : desktop_(NULL),
       xdisplay_(NULL),
       xwindow_(0),
-      xcursor_(0),
+      current_cursor_(aura::kCursorNull),
       bounds_(bounds) {
   // This assumes that the message-pump creates and owns the display.
   xdisplay_ = base::MessagePumpX::GetDefaultXDisplay();
@@ -190,11 +283,16 @@
   XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
 }
 
-void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor_type) {
-  if (xcursor_ == cursor_type)
+void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) {
+  if (current_cursor_ == cursor)
     return;
-  xcursor_ = cursor_type;
-  XDefineCursor(xdisplay_, xwindow_, cursor_type);
+  current_cursor_ = cursor;
+  // Custom web cursors are handled directly.
+  if (cursor == kCursorCustom)
+    return;
+  int cursor_shape = CursorShapeFromNative(cursor);
+  ::Cursor xcursor = ui::GetXCursor(cursor_shape);
+  XDefineCursor(xdisplay_, xwindow_, xcursor);
 }
 
 gfx::Point DesktopHostLinux::QueryMouseLocation() {
diff --git a/ui/aura/desktop_host_win.cc b/ui/aura/desktop_host_win.cc
index 4ce1286..6d9908c 100644
--- a/ui/aura/desktop_host_win.cc
+++ b/ui/aura/desktop_host_win.cc
@@ -12,6 +12,90 @@
 
 namespace aura {
 
+namespace {
+
+const wchar_t* GetCursorId(gfx::NativeCursor native_cursor) {
+  switch (native_cursor) {
+    case kCursorNull:
+      return IDC_ARROW;
+    case kCursorPointer:
+      return IDC_ARROW;
+    case kCursorCross:
+      return IDC_CROSS;
+    case kCursorHand:
+      return IDC_HAND;
+    case kCursorIBeam:
+      return IDC_IBEAM;
+    case kCursorWait:
+      return IDC_WAIT;
+    case kCursorHelp:
+      return IDC_HELP;
+    case kCursorEastResize:
+      return IDC_SIZEWE;
+    case kCursorNorthResize:
+      return IDC_SIZENS;
+    case kCursorNorthEastResize:
+      return IDC_SIZENESW;
+    case kCursorNorthWestResize:
+      return IDC_SIZENWSE;
+    case kCursorSouthResize:
+      return IDC_SIZENS;
+    case kCursorSouthEastResize:
+      return IDC_SIZENWSE;
+    case kCursorSouthWestResize:
+      return IDC_SIZENESW;
+    case kCursorWestResize:
+      return IDC_SIZEWE;
+    case kCursorNorthSouthResize:
+      return IDC_SIZENS;
+    case kCursorEastWestResize:
+      return IDC_SIZEWE;
+    case kCursorNorthEastSouthWestResize:
+      return IDC_SIZENESW;
+    case kCursorNorthWestSouthEastResize:
+      return IDC_SIZENWSE;
+    case kCursorMove:
+      return IDC_SIZEALL;
+    case kCursorProgress:
+      return IDC_APPSTARTING;
+    case kCursorNoDrop:
+      return IDC_NO;
+    case kCursorNotAllowed:
+      return IDC_NO;
+    case kCursorColumnResize:
+    case kCursorRowResize:
+    case kCursorMiddlePanning:
+    case kCursorEastPanning:
+    case kCursorNorthPanning:
+    case kCursorNorthEastPanning:
+    case kCursorNorthWestPanning:
+    case kCursorSouthPanning:
+    case kCursorSouthEastPanning:
+    case kCursorSouthWestPanning:
+    case kCursorWestPanning:
+    case kCursorVerticalText:
+    case kCursorCell:
+    case kCursorContextMenu:
+    case kCursorAlias:
+    case kCursorCopy:
+    case kCursorNone:
+    case kCursorZoomIn:
+    case kCursorZoomOut:
+    case kCursorGrab:
+    case kCursorGrabbing:
+    case kCursorCustom:
+      // TODO(jamescook): Should we use WebKit glue resources for these?
+      // Or migrate those resources to someplace ui/aura can share?
+      NOTIMPLEMENTED();
+      return IDC_ARROW;
+    default:
+      NOTREACHED();
+      return IDC_ARROW;
+  }
+}
+
+}  // namespace
+
 // static
 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
   return new DesktopHostWin(bounds);
@@ -60,10 +144,14 @@
       SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION);
 }
 
-void DesktopHostWin::SetCursor(gfx::NativeCursor cursor) {
-  if (!cursor)
-    cursor = LoadCursor(NULL, IDC_ARROW);
-  ::SetCursor(cursor);
+void DesktopHostWin::SetCursor(gfx::NativeCursor native_cursor) {
+  // Custom web cursors are handled directly.
+  if (native_cursor == kCursorCustom)
+    return;
+  const wchar_t* cursor_id = GetCursorId(native_cursor);
+  // TODO(jamescook): Support for non-system cursors will require finding
+  // the appropriate module to pass to LoadCursor().
+  ::SetCursor(LoadCursor(NULL, cursor_id));
 }
 
 gfx::Point DesktopHostWin::QueryMouseLocation() {
diff --git a/ui/aura/test/test_window_delegate.cc b/ui/aura/test/test_window_delegate.cc
index 9986b78..770d80c 100644
--- a/ui/aura/test/test_window_delegate.cc
+++ b/ui/aura/test/test_window_delegate.cc
@@ -30,7 +30,7 @@
 }
 
 gfx::NativeCursor TestWindowDelegate::GetCursor(const gfx::Point& point) {
-  return NULL;
+  return gfx::kNullCursor;
 }
 
 int TestWindowDelegate::GetNonClientComponent(const gfx::Point& point) const {
diff --git a/ui/aura_shell/toplevel_frame_view.cc b/ui/aura_shell/toplevel_frame_view.cc
index e1a615f..61f659c 100644
--- a/ui/aura_shell/toplevel_frame_view.cc
+++ b/ui/aura_shell/toplevel_frame_view.cc
@@ -5,6 +5,7 @@
 #include "ui/aura_shell/toplevel_frame_view.h"
 
 #include "grit/ui_resources.h"
+#include "ui/aura/cursor.h"
 #include "ui/base/animation/throb_animation.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
@@ -472,28 +473,26 @@
 }
 
 gfx::NativeCursor ToplevelFrameView::GetCursor(const views::MouseEvent& event) {
-#if defined(OS_WIN)
   switch (current_hittest_code_) {
-    case HTTOPLEFT:
-    case HTBOTTOMRIGHT:
-      return LoadCursor(NULL, IDC_SIZENWSE);
-    case HTTOP:
     case HTBOTTOM:
-      return LoadCursor(NULL, IDC_SIZENS);
-    case HTTOPRIGHT:
+      return aura::kCursorSouthResize;
     case HTBOTTOMLEFT:
-      return LoadCursor(NULL, IDC_SIZENESW);
-    case HTRIGHT:
+      return aura::kCursorSouthWestResize;
+    case HTBOTTOMRIGHT:
+      return aura::kCursorSouthEastResize;
     case HTLEFT:
-      return LoadCursor(NULL, IDC_SIZEWE);
+      return aura::kCursorWestResize;
+    case HTRIGHT:
+      return aura::kCursorEastResize;
+    case HTTOP:
+      return aura::kCursorNorthResize;
+    case HTTOPLEFT:
+      return aura::kCursorNorthWestResize;
+    case HTTOPRIGHT:
+      return aura::kCursorNorthEastResize;
     default:
-      break;
+      return aura::kCursorNull;
   }
-  return NULL;
-#elif defined(OS_LINUX)
-  NOTIMPLEMENTED();
-  return gfx::kNullCursor;
-#endif
 }
 
 }  // namespace internal
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 39c2cff..5d61192 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -12,6 +12,7 @@
 #include <sys/shm.h>
 
 #include <list>
+#include <map>
 #include <vector>
 
 #include "base/command_line.h"
@@ -105,6 +106,38 @@
                             property);
 }
 
+// A process wide singleton that manages the usage of X cursors.
+class XCursorCache {
+ public:
+   XCursorCache() {}
+  ~XCursorCache() {
+    Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
+    for (std::map<int, Cursor>::iterator it =
+        cache_.begin(); it != cache_.end(); ++it) {
+      XFreeCursor(display, it->second);
+    }
+    cache_.clear();
+  }
+
+  Cursor GetCursor(int cursor_shape) {
+    // Lookup cursor by attempting to insert a null value, which avoids
+    // a second pass through the map after a cache miss.
+    std::pair<std::map<int, Cursor>::iterator, bool> it = cache_.insert(
+        std::make_pair(cursor_shape, 0));
+    if (it.second) {
+      Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
+      it.first->second = XCreateFontCursor(display, cursor_shape);
+    }
+    return it.first->second;
+  }
+
+ private:
+  // Maps X11 font cursor shapes to Cursor IDs.
+  std::map<int, Cursor> cache_;
+
+  DISALLOW_COPY_AND_ASSIGN(XCursorCache);
+};
+
 }  // namespace
 
 bool XDisplayExists() {
@@ -180,6 +213,11 @@
   return XDefaultScreen(display);
 }
 
+Cursor GetXCursor(int cursor_shape) {
+  static XCursorCache cache;
+  return cache.GetCursor(cursor_shape);
+}
+
 XID GetX11RootWindow() {
   return DefaultRootWindow(GetXDisplay());
 }
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index 6763c04a..519e235 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -22,6 +22,7 @@
 typedef unsigned long XID;
 typedef unsigned long XSharedMemoryId;  // ShmSeg in the X headers.
 typedef struct _XDisplay Display;
+typedef unsigned long Cursor;
 
 #if defined(TOOLKIT_USES_GTK)
 typedef struct _GdkDrawable GdkWindow;
@@ -67,6 +68,10 @@
 // Return the default screen number for the display
 int GetDefaultScreen(Display* display);
 
+// Returns an X11 Cursor, sharable across the process.
+// |cursor_shape| is an X font cursor shape, see XCreateFontCursor().
+UI_EXPORT Cursor GetXCursor(int cursor_shape);
+
 // These functions do not cache their results --------------------------
 
 // Get the X window id for the default root window
diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h
index 319f3a3..a932309 100644
--- a/ui/gfx/native_widget_types.h
+++ b/ui/gfx/native_widget_types.h
@@ -41,10 +41,6 @@
 namespace aura {
 class Window;
 }
-
-#if defined(USE_X11)
-typedef unsigned long Cursor;
-#endif
 #endif  // defined(USE_AURA)
 
 #if defined(OS_WIN)
@@ -95,27 +91,34 @@
 namespace gfx {
 
 #if defined(USE_AURA)
+// See ui/aura/cursor.h for values.
+typedef int NativeCursor;
 typedef aura::Window* NativeView;
 typedef aura::Window* NativeWindow;
 typedef SkRegion* NativeRegion;
 #elif defined(OS_WIN)
+typedef HCURSOR NativeCursor;
 typedef HWND NativeView;
 typedef HWND NativeWindow;
 typedef HRGN NativeRegion;
 #elif defined(OS_MACOSX)
+typedef void* NativeCursor;
 typedef NSView* NativeView;
 typedef NSWindow* NativeWindow;
 #elif defined(USE_WAYLAND)
+typedef void* NativeCursor;
 typedef ui::WaylandWindow* NativeView;
 typedef ui::WaylandWindow* NativeWindow;
 // TODO(dnicoara) This should be replaced with a cairo region or maybe
 // a Wayland specific region
 typedef GdkRegion* NativeRegion;
 #elif defined(USE_X11)
+typedef GdkCursor* NativeCursor;
 typedef GtkWidget* NativeView;
 typedef GtkWindow* NativeWindow;
 typedef GdkRegion* NativeRegion;
 #elif defined(OS_ANDROID)
+typedef void* NativeCursor;
 typedef ChromeView* NativeView;
 typedef ChromeView* NativeWindow;
 typedef void* NativeRegion;
@@ -125,42 +128,36 @@
 typedef HFONT NativeFont;
 typedef HWND NativeEditView;
 typedef HDC NativeDrawingContext;
-typedef HCURSOR NativeCursor;
 typedef HMENU NativeMenu;
 typedef IAccessible* NativeViewAccessible;
 #elif defined(OS_MACOSX)
 typedef NSFont* NativeFont;
 typedef NSTextField* NativeEditView;
 typedef CGContext* NativeDrawingContext;
-typedef void* NativeCursor;
 typedef void* NativeMenu;
 typedef void* NativeViewAccessible;
 #elif defined(USE_WAYLAND)
 typedef PangoFontDescription* NativeFont;
 typedef void* NativeEditView;
 typedef cairo_t* NativeDrawingContext;
-typedef void* NativeCursor;
 typedef void* NativeMenu;
 typedef void* NativeViewAccessible;
 #elif defined(TOOLKIT_USES_GTK)
 typedef PangoFontDescription* NativeFont;
 typedef GtkWidget* NativeEditView;
 typedef cairo_t* NativeDrawingContext;
-typedef GdkCursor* NativeCursor;
 typedef GtkWidget* NativeMenu;
 typedef void* NativeViewAccessible;
 #elif defined(USE_AURA)
 typedef PangoFontDescription* NativeFont;
 typedef void* NativeEditView;
 typedef cairo_t* NativeDrawingContext;
-typedef Cursor NativeCursor;
 typedef void* NativeMenu;
 typedef void* NativeViewAccessible;
 #elif defined(OS_ANDROID)
 typedef void* NativeFont;
 typedef void* NativeEditView;
 typedef void* NativeDrawingContext;
-typedef void* NativeCursor;
 typedef void* NativeMenu;
 typedef void* NativeViewAccessible;
 #endif
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 75306086..57e2aba 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -416,7 +416,7 @@
 }
 
 gfx::NativeCursor View::GetCursorForPoint(const gfx::Point& point) const {
-  return NULL;
+  return gfx::kNullCursor;
 }
 
 bool View::OnKeyPressed(const KeyEvent& event) {
diff --git a/views/aura_desktop/aura_desktop_main.cc b/views/aura_desktop/aura_desktop_main.cc
index 033c21a..664d0dba2 100644
--- a/views/aura_desktop/aura_desktop_main.cc
+++ b/views/aura_desktop/aura_desktop_main.cc
@@ -41,7 +41,7 @@
     return false;
   }
   virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
-    return NULL;
+    return gfx::kNullCursor;
   }
   virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
     return HTCLIENT;
diff --git a/views/controls/link.cc b/views/controls/link.cc
index 08f2447..4f717418 100644
--- a/views/controls/link.cc
+++ b/views/controls/link.cc
@@ -23,6 +23,10 @@
 #include "ui/gfx/gtk_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/cursor.h"
+#endif
+
 namespace views {
 
 const char Link::kViewClassName[] = "views/Link";
@@ -50,14 +54,13 @@
 gfx::NativeCursor Link::GetCursor(const MouseEvent& event) {
   if (!IsEnabled())
     return gfx::kNullCursor;
-#if defined(OS_WIN)
+#if defined(USE_AURA)
+  return aura::kCursorHand;
+#elif defined(OS_WIN)
   static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_HAND);
   return g_hand_cursor;
 #elif defined(TOOLKIT_USES_GTK)
   return gfx::GetCursor(GDK_HAND2);
-#else
-  // TODO(saintlou):
-  return gfx::kNullCursor;
 #endif
 }
 
diff --git a/views/controls/resize_area.cc b/views/controls/resize_area.cc
index 242498c..88ac5b5 100644
--- a/views/controls/resize_area.cc
+++ b/views/controls/resize_area.cc
@@ -13,6 +13,10 @@
 #include "ui/gfx/gtk_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/cursor.h"
+#endif
+
 namespace views {
 
 const char ResizeArea::kViewClassName[] = "views/ResizeArea";
@@ -35,12 +39,11 @@
 gfx::NativeCursor ResizeArea::GetCursor(const MouseEvent& event) {
   if (!IsEnabled())
     return gfx::kNullCursor;
-#if defined(OS_WIN)
+#if defined(USE_AURA)
+  return aura::kCursorEastWestResize;
+#elif defined(OS_WIN)
   static HCURSOR g_resize_cursor = LoadCursor(NULL, IDC_SIZEWE);
   return g_resize_cursor;
-#elif defined(USE_AURA)
-  // TODO(saintlou):
-  return gfx::kNullCursor;
 #elif defined(OS_LINUX)
   return gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW);
 #endif
diff --git a/views/controls/single_split_view.cc b/views/controls/single_split_view.cc
index 4e46cfe..d67e11398 100644
--- a/views/controls/single_split_view.cc
+++ b/views/controls/single_split_view.cc
@@ -17,6 +17,10 @@
 #include "ui/gfx/gtk_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/cursor.h"
+#endif
+
 namespace views {
 
 // static
@@ -96,16 +100,16 @@
 gfx::NativeCursor SingleSplitView::GetCursor(const MouseEvent& event) {
   if (!IsPointInDivider(event.location()))
     return gfx::kNullCursor;
-#if defined(OS_WIN)
+#if defined(USE_AURA)
+  return is_horizontal_ ?
+      aura::kCursorEastWestResize : aura::kCursorNorthSouthResize;
+#elif defined(OS_WIN)
   static HCURSOR we_resize_cursor = LoadCursor(NULL, IDC_SIZEWE);
   static HCURSOR ns_resize_cursor = LoadCursor(NULL, IDC_SIZENS);
   return is_horizontal_ ? we_resize_cursor : ns_resize_cursor;
 #elif defined(TOOLKIT_USES_GTK)
   return gfx::GetCursor(is_horizontal_ ? GDK_SB_H_DOUBLE_ARROW :
                                          GDK_SB_V_DOUBLE_ARROW);
-#else
-  // TODO(saintlou):
-  return gfx::kNullCursor;
 #endif
 }
 
diff --git a/views/controls/textfield/native_textfield_views.cc b/views/controls/textfield/native_textfield_views.cc
index 20ebbc7..d2fbb143 100644
--- a/views/controls/textfield/native_textfield_views.cc
+++ b/views/controls/textfield/native_textfield_views.cc
@@ -37,6 +37,10 @@
 #include "ui/gfx/gtk_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/cursor.h"
+#endif
+
 namespace {
 
 // Text color for read only.
@@ -291,14 +295,12 @@
   bool in_selection = GetRenderText()->IsPointInSelection(event.location());
   bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
   bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
-#if defined(OS_WIN)
+#if defined(USE_AURA)
+  return text_cursor ? aura::kCursorIBeam : aura::kCursorNull;
+#elif defined(OS_WIN)
   static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM);
   static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
   return text_cursor ? ibeam : arrow;
-#elif defined(USE_AURA)
-  // TODO(saintlou):
-  (void)text_cursor;
-  return gfx::kNullCursor;
 #else
   return text_cursor ? gfx::GetCursor(GDK_XTERM) : NULL;
 #endif
diff --git a/views/view.cc b/views/view.cc
index fc1f938..925a40f 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -727,7 +727,7 @@
 }
 
 gfx::NativeCursor View::GetCursor(const MouseEvent& event) {
-#if defined(OS_WIN)
+#if defined(OS_WIN) && !defined(USE_AURA)
   static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
   return arrow;
 #else
diff --git a/webkit/glue/webcursor.cc b/webkit/glue/webcursor.cc
index 50a0bb6..1dd72909 100644
--- a/webkit/glue/webcursor.cc
+++ b/webkit/glue/webcursor.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
 
@@ -46,7 +46,7 @@
 void WebCursor::InitFromCursorInfo(const WebCursorInfo& cursor_info) {
   Clear();
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) && !defined(USE_AURA)
   if (cursor_info.externalHandle) {
     InitFromExternalCursor(cursor_info.externalHandle);
     return;
@@ -65,7 +65,7 @@
   cursor_info->hotSpot = hotspot_;
   ImageFromCustomData(&cursor_info->customImage);
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) && !defined(USE_AURA)
   cursor_info->externalHandle = external_cursor_;
 #endif
 }
diff --git a/webkit/glue/webcursor.h b/webkit/glue/webcursor.h
index cdd4ba7..9439a15 100644
--- a/webkit/glue/webcursor.h
+++ b/webkit/glue/webcursor.h
@@ -69,7 +69,7 @@
   // Returns a native cursor representing the current WebCursor instance.
   gfx::NativeCursor GetNativeCursor();
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) && !defined(USE_AURA)
   // Returns a HCURSOR representing the current WebCursor instance.
   // The ownership of the HCURSOR (does not apply to external cursors) remains
   // with the WebCursor instance.
diff --git a/webkit/glue/webcursor_aura.cc b/webkit/glue/webcursor_aura.cc
new file mode 100644
index 0000000..7610aff
--- /dev/null
+++ b/webkit/glue/webcursor_aura.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 2011 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 "webkit/glue/webcursor.h"
+
+#include "base/logging.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "ui/aura/cursor.h"
+
+using WebKit::WebCursorInfo;
+
+gfx::NativeCursor WebCursor::GetNativeCursor() {
+  switch (type_) {
+    case WebCursorInfo::TypePointer:
+      return aura::kCursorPointer;
+    case WebCursorInfo::TypeCross:
+      return aura::kCursorCross;
+    case WebCursorInfo::TypeHand:
+      return aura::kCursorHand;
+    case WebCursorInfo::TypeIBeam:
+      return aura::kCursorIBeam;
+    case WebCursorInfo::TypeWait:
+      return aura::kCursorWait;
+    case WebCursorInfo::TypeHelp:
+      return aura::kCursorHelp;
+    case WebCursorInfo::TypeEastResize:
+      return aura::kCursorEastResize;
+    case WebCursorInfo::TypeNorthResize:
+      return aura::kCursorNorthResize;
+    case WebCursorInfo::TypeNorthEastResize:
+      return aura::kCursorNorthEastResize;
+    case WebCursorInfo::TypeNorthWestResize:
+      return aura::kCursorNorthWestResize;
+    case WebCursorInfo::TypeSouthResize:
+      return aura::kCursorSouthResize;
+    case WebCursorInfo::TypeSouthEastResize:
+      return aura::kCursorSouthEastResize;
+    case WebCursorInfo::TypeSouthWestResize:
+      return aura::kCursorSouthWestResize;
+    case WebCursorInfo::TypeWestResize:
+      return aura::kCursorWestResize;
+    case WebCursorInfo::TypeNorthSouthResize:
+      return aura::kCursorNorthSouthResize;
+    case WebCursorInfo::TypeEastWestResize:
+      return aura::kCursorEastWestResize;
+    case WebCursorInfo::TypeNorthEastSouthWestResize:
+      return aura::kCursorNorthEastSouthWestResize;
+    case WebCursorInfo::TypeNorthWestSouthEastResize:
+      return aura::kCursorNorthWestSouthEastResize;
+    case WebCursorInfo::TypeColumnResize:
+      return aura::kCursorColumnResize;
+    case WebCursorInfo::TypeRowResize:
+      return aura::kCursorRowResize;
+    case WebCursorInfo::TypeMiddlePanning:
+      return aura::kCursorMiddlePanning;
+    case WebCursorInfo::TypeEastPanning:
+      return aura::kCursorEastPanning;
+    case WebCursorInfo::TypeNorthPanning:
+      return aura::kCursorNorthPanning;
+    case WebCursorInfo::TypeNorthEastPanning:
+      return aura::kCursorNorthEastPanning;
+    case WebCursorInfo::TypeNorthWestPanning:
+      return aura::kCursorNorthWestPanning;
+    case WebCursorInfo::TypeSouthPanning:
+      return aura::kCursorSouthPanning;
+    case WebCursorInfo::TypeSouthEastPanning:
+      return aura::kCursorSouthEastPanning;
+    case WebCursorInfo::TypeSouthWestPanning:
+      return aura::kCursorSouthWestPanning;
+    case WebCursorInfo::TypeWestPanning:
+      return aura::kCursorWestPanning;
+    case WebCursorInfo::TypeMove:
+      return aura::kCursorMove;
+    case WebCursorInfo::TypeVerticalText:
+      return aura::kCursorVerticalText;
+    case WebCursorInfo::TypeCell:
+      return aura::kCursorCell;
+    case WebCursorInfo::TypeContextMenu:
+      return aura::kCursorContextMenu;
+    case WebCursorInfo::TypeAlias:
+      return aura::kCursorAlias;
+    case WebCursorInfo::TypeProgress:
+      return aura::kCursorProgress;
+    case WebCursorInfo::TypeNoDrop:
+      return aura::kCursorNoDrop;
+    case WebCursorInfo::TypeCopy:
+      return aura::kCursorCopy;
+    case WebCursorInfo::TypeNone:
+      return aura::kCursorNone;
+    case WebCursorInfo::TypeNotAllowed:
+      return aura::kCursorNotAllowed;
+    case WebCursorInfo::TypeZoomIn:
+      return aura::kCursorZoomIn;
+    case WebCursorInfo::TypeZoomOut:
+      return aura::kCursorZoomOut;
+    case WebCursorInfo::TypeGrab:
+      return aura::kCursorGrab;
+    case WebCursorInfo::TypeGrabbing:
+      return aura::kCursorGrabbing;
+    case WebCursorInfo::TypeCustom:
+      return aura::kCursorCustom;
+    default:
+      NOTREACHED();
+      return gfx::kNullCursor;
+  }
+}
+
+void WebCursor::InitPlatformData() {
+}
+
+bool WebCursor::SerializePlatformData(Pickle* pickle) const {
+  return true;
+}
+
+bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
+  return true;
+}
+
+bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
+  return true;
+}
+
+void WebCursor::CleanupPlatformData() {
+}
+
+void WebCursor::CopyPlatformData(const WebCursor& other) {
+}
diff --git a/webkit/glue/webcursor_aurax11.cc b/webkit/glue/webcursor_aurax11.cc
deleted file mode 100644
index 824cdc55..0000000
--- a/webkit/glue/webcursor_aurax11.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2011 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 "webkit/glue/webcursor.h"
-
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#include <map>
-
-#include "base/message_loop.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
-
-using WebKit::WebCursorInfo;
-
-namespace {
-
-// A process wide singleton that manages the usage of X cursors.
-class CursorCache {
- public:
-   CursorCache() {}
-  ~CursorCache() {
-    Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
-    for (std::map<int, Cursor>::iterator it =
-        cache_.begin(); it != cache_.end(); ++it) {
-      XFreeCursor(display, it->second);
-    }
-    cache_.clear();
-  }
-
-  Cursor GetCursor(int web_cursor_info_type) {
-    Cursor cursor = gfx::kNullCursor;
-    std::pair<std::map<int, Cursor>::iterator, bool> it = cache_.insert(
-        std::make_pair(web_cursor_info_type, cursor));
-    if (it.second) {
-      cursor = XCreateFontCursor(base::MessagePumpForUI::GetDefaultXDisplay(),
-          GetXCursorType(web_cursor_info_type));
-      it.first->second = cursor;
-    }
-    return it.first->second;
-  }
-
- private:
-  int GetXCursorType(int web_cursor_info_type) {
-    switch (web_cursor_info_type) {
-      case WebCursorInfo::TypePointer:
-        return XC_left_ptr;
-      case WebCursorInfo::TypeCross:
-        return XC_crosshair;
-      case WebCursorInfo::TypeHand:
-        return XC_hand2;
-      case WebCursorInfo::TypeIBeam:
-        return XC_xterm;
-      case WebCursorInfo::TypeWait:
-        return XC_watch;
-      case WebCursorInfo::TypeHelp:
-        return XC_question_arrow;
-      case WebCursorInfo::TypeEastResize:
-        return XC_right_side;
-      case WebCursorInfo::TypeNorthResize:
-        return XC_top_side;
-      case WebCursorInfo::TypeNorthEastResize:
-        return XC_top_right_corner;
-      case WebCursorInfo::TypeNorthWestResize:
-        return XC_top_left_corner;
-      case WebCursorInfo::TypeSouthResize:
-        return XC_bottom_side;
-      case WebCursorInfo::TypeSouthEastResize:
-        return XC_bottom_right_corner;
-      case WebCursorInfo::TypeSouthWestResize:
-        return XC_bottom_left_corner;
-      case WebCursorInfo::TypeWestResize:
-        return XC_left_side;
-      case WebCursorInfo::TypeNorthSouthResize:
-        return XC_sb_v_double_arrow;
-      case WebCursorInfo::TypeEastWestResize:
-        return XC_sb_h_double_arrow;
-      case WebCursorInfo::TypeNorthEastSouthWestResize:
-      case WebCursorInfo::TypeNorthWestSouthEastResize:
-        // There isn't really a useful cursor available for these.
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeColumnResize:
-        return XC_sb_h_double_arrow;
-      case WebCursorInfo::TypeRowResize:
-        return XC_sb_v_double_arrow;
-      case WebCursorInfo::TypeMiddlePanning:
-        return XC_fleur;
-      case WebCursorInfo::TypeEastPanning:
-        return XC_sb_right_arrow;
-      case WebCursorInfo::TypeNorthPanning:
-        return XC_sb_up_arrow;
-      case WebCursorInfo::TypeNorthEastPanning:
-        return XC_top_right_corner;
-      case WebCursorInfo::TypeNorthWestPanning:
-        return XC_top_left_corner;
-      case WebCursorInfo::TypeSouthPanning:
-        return XC_sb_down_arrow;
-      case WebCursorInfo::TypeSouthEastPanning:
-        return XC_bottom_right_corner;
-      case WebCursorInfo::TypeSouthWestPanning:
-        return XC_bottom_left_corner;
-      case WebCursorInfo::TypeWestPanning:
-        return XC_sb_left_arrow;
-      case WebCursorInfo::TypeMove:
-        return XC_fleur;
-      case WebCursorInfo::TypeVerticalText:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeCell:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeContextMenu:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeAlias:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeProgress:
-        return XC_watch;
-      case WebCursorInfo::TypeNoDrop:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeCopy:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeNone:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeNotAllowed:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-      case WebCursorInfo::TypeZoomIn:
-      case WebCursorInfo::TypeZoomOut:
-      case WebCursorInfo::TypeGrab:
-      case WebCursorInfo::TypeGrabbing:
-      case WebCursorInfo::TypeCustom:
-        NOTIMPLEMENTED();
-        return XC_left_ptr;
-    }
-    NOTREACHED();
-    return XC_left_ptr;
-  }
-
-  std::map<int, Cursor> cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(CursorCache);
-};
-
-}  // namespace
-
-gfx::NativeCursor WebCursor::GetNativeCursor() {
-  static CursorCache cache;
-  return cache.GetCursor(type_);
-}
-
-void WebCursor::InitPlatformData() {
-}
-
-bool WebCursor::SerializePlatformData(Pickle* pickle) const {
-  return true;
-}
-
-bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
-  return true;
-}
-
-bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
-  return true;
-}
-
-void WebCursor::CleanupPlatformData() {
-}
-
-void WebCursor::CopyPlatformData(const WebCursor& other) {
-}
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 89c42c25..6ccde32 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -384,7 +384,7 @@
         'webcookie.h',
         'webcursor.cc',
         'webcursor.h',
-        'webcursor_aurax11.cc',
+        'webcursor_aura.cc',
         'webcursor_gtk.cc',
         'webcursor_gtk_data.h',
         'webcursor_mac.mm',
@@ -462,6 +462,9 @@
           'sources/': [
             ['exclude', '^../plugins/npapi/webplugin_delegate_impl_win.cc'],
           ],
+          'sources!': [
+            'webcursor_win.cc',
+          ],
         }],
         ['OS!="mac"', {
           'sources/': [['exclude', '_mac\\.(cc|mm)$']],