diff options
35 files changed, 773 insertions, 370 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index e4b0877..8d1f53b 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -274,6 +274,8 @@ 'wm/gestures/system_pinch_handler.h', 'wm/gestures/two_finger_drag_handler.cc', 'wm/gestures/two_finger_drag_handler.h', + 'wm/image_cursors.cc', + 'wm/image_cursors.h', 'wm/image_grid.cc', 'wm/image_grid.h', 'wm/maximize_bubble_controller.cc', diff --git a/ash/display/mouse_cursor_event_filter.cc b/ash/display/mouse_cursor_event_filter.cc index 2973ef8..469db41 100644 --- a/ash/display/mouse_cursor_event_filter.cc +++ b/ash/display/mouse_cursor_event_filter.cc @@ -153,6 +153,8 @@ bool MouseCursorEventFilter::WarpMouseCursorIfNecessary( if (dst_root->bounds().Contains(point_in_dst_screen)) { DCHECK_NE(dst_root, current_root); dst_root->MoveCursorTo(point_in_dst_screen); + ash::Shell::GetInstance()->cursor_manager()->SetDeviceScaleFactor( + dst_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); return true; } return false; diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index eb33f3d..acecc81 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -62,7 +62,6 @@ int DragDropController::StartDragAndDrop(const ui::OSExchangeData& data, int operation) { DCHECK(!IsDragDropInProgress()); - drag_cursor_ = ui::kCursorPointer; drag_drop_tracker_.reset(new DragDropTracker(root_window)); drag_data_ = &data; @@ -128,7 +127,6 @@ void DragDropController::DragUpdate(aura::Window* target, cursor = ui::kCursorAlias; else if (op & ui::DragDropTypes::DRAG_MOVE) cursor = ui::kCursorMove; - drag_cursor_ = cursor; ash::Shell::GetInstance()->cursor_manager()->SetCursor(cursor); } } @@ -145,7 +143,6 @@ void DragDropController::DragUpdate(aura::Window* target, void DragDropController::Drop(aura::Window* target, const ui::LocatedEvent& event) { - drag_cursor_ = ui::kCursorPointer; ash::Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorPointer); aura::client::DragDropDelegate* delegate = NULL; @@ -175,7 +172,6 @@ void DragDropController::Drop(aura::Window* target, } void DragDropController::DragCancel() { - drag_cursor_ = ui::kCursorPointer; ash::Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorPointer); // |drag_window_| can be NULL if we have just started the drag and have not @@ -197,10 +193,6 @@ bool DragDropController::IsDragDropInProgress() { return !!drag_drop_tracker_.get(); } -gfx::NativeCursor DragDropController::GetDragCursor() { - return drag_cursor_; -} - bool DragDropController::PreHandleKeyEvent(aura::Window* target, ui::KeyEvent* event) { if (IsDragDropInProgress() && event->key_code() == ui::VKEY_ESCAPE) { diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h index d138ef6..59f1f32 100644 --- a/ash/drag_drop/drag_drop_controller.h +++ b/ash/drag_drop/drag_drop_controller.h @@ -59,7 +59,6 @@ class ASH_EXPORT DragDropController const ui::LocatedEvent& event) OVERRIDE; virtual void DragCancel() OVERRIDE; virtual bool IsDragDropInProgress() OVERRIDE; - virtual gfx::NativeCursor GetDragCursor() OVERRIDE; // Overridden from aura::EventFilter: virtual bool PreHandleKeyEvent(aura::Window* target, @@ -92,7 +91,6 @@ class ASH_EXPORT DragDropController gfx::Point drag_image_offset_; const ui::OSExchangeData* drag_data_; int drag_operation_; - gfx::NativeCursor drag_cursor_; // Window that is currently under the drag cursor. aura::Window* drag_window_; diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc index b1e9583..20e4115 100644 --- a/ash/extended_desktop_unittest.cc +++ b/ash/extended_desktop_unittest.cc @@ -165,17 +165,17 @@ TEST_F(ExtendedDesktopTest, SystemModal) { TEST_F(ExtendedDesktopTest, TestCursor) { UpdateDisplay("1000x600,600x400"); - Shell::GetInstance()->ShowCursor(false); + Shell::GetInstance()->cursor_manager()->ShowCursor(false); Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); EXPECT_FALSE(root_windows[0]->cursor_shown()); EXPECT_FALSE(root_windows[1]->cursor_shown()); - Shell::GetInstance()->ShowCursor(true); + Shell::GetInstance()->cursor_manager()->ShowCursor(true); EXPECT_TRUE(root_windows[0]->cursor_shown()); EXPECT_TRUE(root_windows[1]->cursor_shown()); EXPECT_EQ(ui::kCursorPointer, root_windows[0]->last_cursor().native_type()); EXPECT_EQ(ui::kCursorPointer, root_windows[1]->last_cursor().native_type()); - Shell::GetInstance()->SetCursor(ui::kCursorCopy); + Shell::GetInstance()->cursor_manager()->SetCursor(ui::kCursorCopy); EXPECT_EQ(ui::kCursorCopy, root_windows[0]->last_cursor().native_type()); EXPECT_EQ(ui::kCursorCopy, root_windows[1]->last_cursor().native_type()); } diff --git a/ash/shell.cc b/ash/shell.cc index 6c26a09..ebfa9eb 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -372,6 +372,9 @@ void Shell::Init() { aura::RootWindow* root_window = display_controller_->GetPrimaryRootWindow(); active_root_window_ = root_window; + cursor_manager_.SetDeviceScaleFactor( + root_window->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); + #if !defined(OS_MACOSX) nested_dispatcher_controller_.reset(new NestedDispatcherController); accelerator_controller_.reset(new AcceleratorController); diff --git a/ash/wm/cursor_manager.cc b/ash/wm/cursor_manager.cc index 1ebc72b..3afee4b 100644 --- a/ash/wm/cursor_manager.cc +++ b/ash/wm/cursor_manager.cc @@ -5,8 +5,10 @@ #include "ash/wm/cursor_manager.h" #include "ash/wm/cursor_delegate.h" +#include "ash/wm/image_cursors.h" #include "base/logging.h" #include "ui/aura/env.h" +#include "ui/base/cursor/cursor.h" namespace ash { @@ -15,7 +17,9 @@ CursorManager::CursorManager() cursor_lock_count_(0), did_cursor_change_(false), cursor_to_set_on_unlock_(0), - cursor_visible_(true) { + cursor_visible_(true), + current_cursor_(ui::kCursorNone), + image_cursors_(new ImageCursors) { } CursorManager::~CursorManager() { @@ -42,7 +46,7 @@ void CursorManager::UnlockCursor() { void CursorManager::SetCursor(gfx::NativeCursor cursor) { if (cursor_lock_count_ == 0) { if (delegate_) - delegate_->SetCursor(cursor); + SetCursorInternal(cursor); } else { cursor_to_set_on_unlock_ = cursor; did_cursor_change_ = true; @@ -59,4 +63,20 @@ bool CursorManager::IsCursorVisible() const { return cursor_visible_; } +void CursorManager::SetDeviceScaleFactor(float device_scale_factor) { + if (image_cursors_->GetDeviceScaleFactor() == device_scale_factor) + return; + image_cursors_->SetDeviceScaleFactor(device_scale_factor); + SetCursorInternal(current_cursor_); +} + +void CursorManager::SetCursorInternal(gfx::NativeCursor cursor) { + DCHECK(delegate_); + current_cursor_ = cursor; + image_cursors_->SetPlatformCursor(¤t_cursor_); + current_cursor_.set_device_scale_factor( + image_cursors_->GetDeviceScaleFactor()); + delegate_->SetCursor(current_cursor_); +} + } // namespace ash diff --git a/ash/wm/cursor_manager.h b/ash/wm/cursor_manager.h index 9f2cc8b..f5b5548 100644 --- a/ash/wm/cursor_manager.h +++ b/ash/wm/cursor_manager.h @@ -7,12 +7,14 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "ui/aura/aura_export.h" #include "ui/aura/client/cursor_client.h" #include "ui/gfx/native_widget_types.h" namespace ash { class CursorDelegate; +class ImageCursors; // This class controls the visibility and the type of the cursor. // The cursor type can be locked so that the type stays the same @@ -33,11 +35,15 @@ class CursorManager : public aura::client::CursorClient { // Shows or hides the cursor. bool cursor_visible() const { return cursor_visible_; } + // Overridden from aura::client::CursorClient: virtual void SetCursor(gfx::NativeCursor) OVERRIDE; virtual void ShowCursor(bool show) OVERRIDE; virtual bool IsCursorVisible() const OVERRIDE; + virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE; private: + void SetCursorInternal(gfx::NativeCursor cursor); + CursorDelegate* delegate_; // Number of times LockCursor() has been invoked without a corresponding @@ -54,6 +60,11 @@ class CursorManager : public aura::client::CursorClient { // Is cursor visible? bool cursor_visible_; + // The cursor currently set. + gfx::NativeCursor current_cursor_; + + scoped_ptr<ImageCursors> image_cursors_; + DISALLOW_COPY_AND_ASSIGN(CursorManager); }; diff --git a/ash/wm/image_cursors.cc b/ash/wm/image_cursors.cc new file mode 100644 index 0000000..b0ec3f5 --- /dev/null +++ b/ash/wm/image_cursors.cc @@ -0,0 +1,123 @@ +// 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 "ash/wm/image_cursors.h" + +#include "base/logging.h" +#include "ui/base/cursor/cursor_loader.h" +#include "ui/base/cursor/cursor.h" +#include "ui/gfx/point.h" +#include "grit/ui_resources.h" + +namespace { + +const int kAnimatedCursorFrameDelayMs = 25; + +struct HotPoint { + int x; + int y; +}; + +struct CursorData { + int id; + int resource_id; + HotPoint hot_1x; + HotPoint hot_2x; +}; + +// TODO(oshima): Remove this comment (http://crbug.com/141586). +// The cursor's hot points are defined in chromeos cursor images at: +// http://folder/kuscher/projects/Chrome_OS/Pointers/focuspoint +const CursorData kImageCursors[] = { + {ui::kCursorNull, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}}, + {ui::kCursorPointer, IDR_AURA_CURSOR_PTR, {4, 4}, {8, 9}}, + {ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, {4, 4}, {8, 9}}, + {ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP, {4, 4}, {8, 9}}, + {ui::kCursorCopy, IDR_AURA_CURSOR_COPY, {4, 4}, {8, 9}}, + {ui::kCursorHand, IDR_AURA_CURSOR_HAND, {9, 4}, {19, 8}}, + {ui::kCursorMove, IDR_AURA_CURSOR_MOVE, {11, 11}, {23, 23}}, + {ui::kCursorNorthEastResize, IDR_AURA_CURSOR_NORTH_EAST_RESIZE, + {12, 11}, {25, 23}}, + {ui::kCursorSouthWestResize, IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, + {12, 11}, {25, 23}}, + {ui::kCursorSouthEastResize, IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, + {11, 11}, {24, 23}}, + {ui::kCursorNorthWestResize, IDR_AURA_CURSOR_NORTH_WEST_RESIZE, + {11, 11}, {24, 23}}, + {ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE, {11, 12}, {23, 23}}, + {ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE, {11, 12}, {23, 23}}, + {ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE, {12, 11}, {25, 23}}, + {ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE, {12, 11}, {25, 23}}, + {ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM, {12, 12}, {24, 25}}, + {ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS, {8, 6}, {15, 11}}, + {ui::kCursorCell, IDR_AURA_CURSOR_CELL, {11, 11}, {24, 23}}, + {ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, {4, 4}, {8, 9}}, + {ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR, {12, 12}, {25, 23}}, + {ui::kCursorHelp, IDR_AURA_CURSOR_HELP, {4, 4}, {8, 9}}, + {ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ, {12, 11}, {26, 23}}, + {ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN, {10, 10}, {20, 20}}, + {ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, {10, 10}, {20, 20}}, + {ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE, {11, 12}, {23, 23}}, + {ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE, {12, 11}, {25, 23}}, + {ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE, + {12, 11}, {25, 23}}, + {ui::kCursorNorthSouthResize, IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, + {11, 12}, {23, 23}}, + {ui::kCursorNorthEastSouthWestResize, + IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, {12, 11}, {25, 23}}, + {ui::kCursorNorthWestSouthEastResize, + IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, {11, 11}, {24, 23}}, + {ui::kCursorGrab, IDR_AURA_CURSOR_GRAB, {8, 5}, {16, 10}}, + {ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, {9, 9}, {18, 18}}, +}; + +const CursorData kAnimatedCursors[] = { + {ui::kCursorWait, IDR_THROBBER, {7, 7}, {14, 14}}, + {ui::kCursorProgress, IDR_THROBBER, {7, 7}, {14, 14}}, +}; + +} // namespace + +namespace ash { + +ImageCursors::ImageCursors() + : cursor_loader_(ui::CursorLoader::Create()) { +} + +ImageCursors::~ImageCursors() { +} + +float ImageCursors::GetDeviceScaleFactor() const { + return cursor_loader_->device_scale_factor(); +} + +void ImageCursors::SetDeviceScaleFactor(float device_scale_factor) { + if (GetDeviceScaleFactor() == device_scale_factor) + return; + + cursor_loader_->UnloadAll(); + cursor_loader_->set_device_scale_factor(device_scale_factor); + + for (size_t i = 0; i < arraysize(kImageCursors); ++i) { + const HotPoint& hot = device_scale_factor == 1.0f ? + kImageCursors[i].hot_1x : kImageCursors[i].hot_2x; + cursor_loader_->LoadImageCursor(kImageCursors[i].id, + kImageCursors[i].resource_id, + gfx::Point(hot.x, hot.y)); + } + for (size_t i = 0; i < arraysize(kAnimatedCursors); ++i) { + const HotPoint& hot = device_scale_factor == 1.0f ? + kAnimatedCursors[i].hot_1x : kAnimatedCursors[i].hot_2x; + cursor_loader_->LoadAnimatedCursor(kAnimatedCursors[i].id, + kAnimatedCursors[i].resource_id, + gfx::Point(hot.x, hot.y), + kAnimatedCursorFrameDelayMs); + } +} + +void ImageCursors::SetPlatformCursor(gfx::NativeCursor* cursor) { + cursor_loader_->SetPlatformCursor(cursor); +} + +} // namespace ash diff --git a/ash/wm/image_cursors.h b/ash/wm/image_cursors.h new file mode 100644 index 0000000..a1a7c41 --- /dev/null +++ b/ash/wm/image_cursors.h @@ -0,0 +1,43 @@ +// 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. + +#ifndef ASH_WM_IMAGE_CURSORS_H_ +#define ASH_WM_IMAGE_CURSORS_H_ + +#include "ash/ash_export.h" +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/native_widget_types.h" + +namespace ui { +class CursorLoader; +} + +namespace ash { + +// A utility class that provides cursors for NativeCursors for which we have +// image resources. +class ASH_EXPORT ImageCursors { + public: + ImageCursors(); + ~ImageCursors(); + + // Returns the device scale factor of cursors. + float GetDeviceScaleFactor() const; + + // Sets the device scale factor of the cursors with |device_scale_factor| and + // reloads the cursor images if necessary. + void SetDeviceScaleFactor(float device_scale_factor); + + // Sets the platform cursor based on the native type of |cursor|. + void SetPlatformCursor(gfx::NativeCursor* cursor); + + private: + scoped_ptr<ui::CursorLoader> cursor_loader_; + + DISALLOW_COPY_AND_ASSIGN(ImageCursors); +}; + +} // namespace ash + +#endif // ASH_WM_IMAGE_CURSORS_H_ diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index aa0f754..ce4be53 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc @@ -14,6 +14,7 @@ #include "base/message_loop.h" #include "base/run_loop.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" @@ -276,7 +277,10 @@ aura::client::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop( root_window, source->parent(), &drag_location); } CreateScopedWindowResizer(source, drag_location, HTCAPTION); - source->GetRootWindow()->SetCursor(ui::kCursorPointer); + aura::client::CursorClient* cursor_client = + aura::client::GetCursorClient(root_window); + if (cursor_client) + cursor_client->SetCursor(ui::kCursorPointer); #if !defined(OS_MACOSX) MessageLoopForUI* loop = MessageLoopForUI::current(); MessageLoop::ScopedNestableTaskAllower allow_nested(loop); diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc index 9462a66..5b55217 100644 --- a/chrome/browser/ui/ash/ash_init.cc +++ b/chrome/browser/ui/ash/ash_init.cc @@ -31,6 +31,7 @@ #include "chrome/browser/ui/ash/ime_controller_chromeos.h" #include "chrome/browser/ui/ash/keyboard_brightness_controller_chromeos.h" #include "chrome/browser/ui/ash/volume_controller_chromeos.h" +#include "ui/base/x/x11_util.h" #endif @@ -48,14 +49,18 @@ void OpenAsh() { switches::kAuraHostWindowUseFullscreen); #if defined(OS_CHROMEOS) - if (base::chromeos::IsRunningOnChromeOS()) + if (base::chromeos::IsRunningOnChromeOS()) { use_fullscreen = true; + // Hides the cursor outside of the Aura root window. The cursor will be + // drawn within the Aura root window, and it'll remain hidden after the + // Aura window is closed. + ui::HideHostCursor(); + } #endif if (use_fullscreen) { aura::DisplayManager::set_use_fullscreen_host_window(true); #if defined(OS_CHROMEOS) - aura::RootWindow::set_hide_host_cursor(true); // Hide the mouse cursor completely at boot. if (!chromeos::UserManager::Get()->IsUserLoggedIn()) ash::Shell::set_initially_hide_cursor(true); diff --git a/ui/aura/client/cursor_client.h b/ui/aura/client/cursor_client.h index 418c559..ecf67ee 100644 --- a/ui/aura/client/cursor_client.h +++ b/ui/aura/client/cursor_client.h @@ -24,6 +24,9 @@ class AURA_EXPORT CursorClient { // Gets whether the cursor is visible. virtual bool IsCursorVisible() const = 0; + // Sets the device scale factor of the cursor. + virtual void SetDeviceScaleFactor(float device_scale_factor) = 0; + protected: virtual ~CursorClient() {} }; diff --git a/ui/aura/client/drag_drop_client.h b/ui/aura/client/drag_drop_client.h index 25c662f..bb28184 100644 --- a/ui/aura/client/drag_drop_client.h +++ b/ui/aura/client/drag_drop_client.h @@ -48,11 +48,6 @@ class AURA_EXPORT DragDropClient { // Returns true if a drag and drop session is in progress. virtual bool IsDragDropInProgress() = 0; - - // Returns the current cursor according to the appropriate drag effect. This - // should only be called if IsDragDropInProgress() returns true. If it is - // called otherwise, the returned cursor is arbitrary. - virtual gfx::NativeCursor GetDragCursor() = 0; }; AURA_EXPORT void SetDragDropClient(RootWindow* root_window, diff --git a/ui/aura/desktop/desktop_cursor_client.cc b/ui/aura/desktop/desktop_cursor_client.cc index d44cb32..70bb4aa 100644 --- a/ui/aura/desktop/desktop_cursor_client.cc +++ b/ui/aura/desktop/desktop_cursor_client.cc @@ -27,4 +27,8 @@ bool DesktopCursorClient::IsCursorVisible() const { return root_window_->cursor_shown(); } +void DesktopCursorClient::SetDeviceScaleFactor(float device_scale_factor) { + // TODO(ben|erg): Use the device scale factor set here for the cursor. +} + } // namespace aura diff --git a/ui/aura/desktop/desktop_cursor_client.h b/ui/aura/desktop/desktop_cursor_client.h index a4315ed..9ce0526 100644 --- a/ui/aura/desktop/desktop_cursor_client.h +++ b/ui/aura/desktop/desktop_cursor_client.h @@ -24,6 +24,7 @@ class AURA_EXPORT DesktopCursorClient : public client::CursorClient { virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void ShowCursor(bool show) OVERRIDE; virtual bool IsCursorVisible() const OVERRIDE; + virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE; private: aura::RootWindow* root_window_; diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 7662cfe..b261a2a 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -15,7 +15,7 @@ #include "ui/aura/aura_switches.h" #include "ui/aura/client/activation_client.h" #include "ui/aura/client/capture_client.h" -#include "ui/aura/client/drag_drop_client.h" +#include "ui/aura/client/cursor_client.h" #include "ui/aura/client/event_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/display_manager.h" @@ -110,8 +110,6 @@ void CompositorLock::CancelLock() { root_window_ = NULL; } -bool RootWindow::hide_host_cursor_ = false; - RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds) : initial_bounds(a_initial_bounds), host(NULL) { @@ -246,11 +244,6 @@ gfx::Point RootWindow::GetHostOrigin() const { } void RootWindow::SetCursor(gfx::NativeCursor cursor) { - // If a drag is in progress, the DragDropClient should override the cursor. - client::DragDropClient* dnd_client = client::GetDragDropClient(this); - if (dnd_client && dnd_client->IsDragDropInProgress()) - cursor = dnd_client->GetDragCursor(); - last_cursor_ = cursor; // A lot of code seems to depend on NULL cursors actually showing an arrow, // so just pass everything along to the host. @@ -529,11 +522,20 @@ void RootWindow::OnCompositingAborted(ui::Compositor*) { void RootWindow::OnDeviceScaleFactorChanged( float device_scale_factor) { - if (cursor_shown_) + const bool cursor_is_in_bounds = + GetBoundsInScreen().Contains(Env::GetInstance()->last_mouse_location()); + if (cursor_is_in_bounds && cursor_shown_) ShowCursor(false); host_->OnDeviceScaleFactorChanged(device_scale_factor); Window::OnDeviceScaleFactorChanged(device_scale_factor); - if (cursor_shown_) + // Update the device scale factor of the cursor client only when the last + // mouse location is on this root window. + if (cursor_is_in_bounds) { + client::CursorClient* cursor_client = client::GetCursorClient(this); + if (cursor_client) + cursor_client->SetDeviceScaleFactor(device_scale_factor); + } + if (cursor_is_in_bounds && cursor_shown_) ShowCursor(true); } diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index cdc05c0..869802d 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -101,13 +101,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, static RootWindow* GetForAcceleratedWidget(gfx::AcceleratedWidget widget); - static void set_hide_host_cursor(bool hide) { - hide_host_cursor_ = hide; - } - static bool hide_host_cursor() { - return hide_host_cursor_; - } - ui::Compositor* compositor() { return compositor_.get(); } gfx::NativeCursor last_cursor() const { return last_cursor_; } Window* mouse_pressed_handler() { return mouse_pressed_handler_; } @@ -370,11 +363,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, scoped_ptr<RootWindowHost> host_; - // If set before the RootWindow is created, the cursor will be drawn within - // the Aura root window but hidden outside of it, and it'll remain hidden - // after the Aura window is closed. - static bool hide_host_cursor_; - // Used to schedule painting. base::WeakPtrFactory<RootWindow> schedule_paint_factory_; diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc index a0c416f..8edb6ba 100644 --- a/ui/aura/root_window_host_linux.cc +++ b/ui/aura/root_window_host_linux.cc @@ -17,8 +17,8 @@ #include "base/message_pump_aurax11.h" #include "base/stl_util.h" #include "base/stringprintf.h" -#include "grit/ui_resources.h" #include "ui/aura/client/capture_client.h" +#include "ui/aura/client/cursor_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/client/user_action_client.h" #include "ui/aura/env.h" @@ -26,7 +26,6 @@ #include "ui/base/cursor/cursor.h" #include "ui/base/events/event.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/ui_base_switches.h" #include "ui/base/view_prop.h" @@ -34,8 +33,6 @@ #include "ui/base/x/x11_util.h" #include "ui/compositor/layer.h" #include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" #include "ui/gfx/screen.h" #if defined(OS_CHROMEOS) @@ -53,8 +50,6 @@ namespace { const int kBackMouseButton = 8; const int kForwardMouseButton = 9; -const int kAnimatedCursorFrameDelayMs = 25; - // These are the same values that are used to calibrate touch events in // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) @@ -124,75 +119,6 @@ void CheckXEventForConsistency(XEvent* xevent) { #endif // defined(USE_XI2_MT) && !defined(NDEBUG) } -// 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: - // 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: - case ui::kCursorGrab: - case ui::kCursorGrabbing: - 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; -} - // Coalesce all pending motion events (touch or mouse) that are at the top of // the queue, and return the number eliminated, storing the last one in // |last_event|. @@ -354,200 +280,6 @@ bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { } // namespace -// A utility class that provides X Cursor for NativeCursors for which we have -// image resources. -class RootWindowHostLinux::ImageCursors { - public: - ImageCursors() : scale_factor_(0.0) { - } - - void Reload(float scale_factor) { - if (scale_factor_ == scale_factor) - return; - scale_factor_ = scale_factor; - UnloadAll(); - // The cursor's hot points are defined in chromeos cursor images at: - // http://folder/kuscher/projects/Chrome_OS/Pointers/focuspoint - LoadImageCursor(ui::kCursorNull, IDR_AURA_CURSOR_PTR, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorPointer, IDR_AURA_CURSOR_PTR, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorHand, IDR_AURA_CURSOR_HAND, - gfx::Point(9, 4), gfx::Point(19, 8)); - LoadImageCursor(ui::kCursorMove, IDR_AURA_CURSOR_MOVE, - gfx::Point(11, 11), gfx::Point(23, 23)); - LoadImageCursor(ui::kCursorNorthEastResize, - IDR_AURA_CURSOR_NORTH_EAST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorSouthWestResize, - IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorSouthEastResize, - IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, - gfx::Point(11, 11), gfx::Point(24, 23)); - LoadImageCursor(ui::kCursorNorthWestResize, - IDR_AURA_CURSOR_NORTH_WEST_RESIZE, - gfx::Point(11, 11), gfx::Point(24, 23)); - LoadImageCursor(ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE, - gfx::Point(11, 12), gfx::Point(23, 23)); - LoadImageCursor(ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE, - gfx::Point(11, 12), gfx::Point(23, 23)); - LoadImageCursor(ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM, - gfx::Point(12, 12), gfx::Point(24, 25)); - LoadImageCursor(ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS, - gfx::Point(8, 6), gfx::Point(15, 11)); - LoadImageCursor(ui::kCursorCell, IDR_AURA_CURSOR_CELL, - gfx::Point(11, 11), gfx::Point(24, 23)); - LoadImageCursor(ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR, - gfx::Point(12, 12), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorHelp, IDR_AURA_CURSOR_HELP, - gfx::Point(4, 4), gfx::Point(8, 9)); - LoadImageCursor(ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ, - gfx::Point(12, 11), gfx::Point(26, 23)); - LoadImageCursor(ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN, - gfx::Point(10, 10), gfx::Point(20, 20)); - LoadImageCursor(ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, - gfx::Point(10, 10), gfx::Point(20, 20)); - LoadImageCursor(ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE, - gfx::Point(11, 12), gfx::Point(23, 23)); - LoadImageCursor(ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorNorthSouthResize, - IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, - gfx::Point(11, 12), gfx::Point(23, 23)); - LoadImageCursor(ui::kCursorNorthEastSouthWestResize, - IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, - gfx::Point(12, 11), gfx::Point(25, 23)); - LoadImageCursor(ui::kCursorNorthWestSouthEastResize, - IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, - gfx::Point(11, 11), gfx::Point(24, 23)); - LoadImageCursor(ui::kCursorGrab, IDR_AURA_CURSOR_GRAB, - gfx::Point(8, 5), gfx::Point(16, 10)); - LoadImageCursor(ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, - gfx::Point(9, 9), gfx::Point(18, 18)); - LoadAnimatedCursor(ui::kCursorWait, IDR_THROBBER, 7, 7); - LoadAnimatedCursor(ui::kCursorProgress, IDR_THROBBER, 7, 7); - } - - ~ImageCursors() { - UnloadAll(); - } - - void UnloadAll() { - for (std::map<int, Cursor>::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); - } - } - - // Returns true if we have an image resource loaded for the |native_cursor|. - bool IsImageCursor(gfx::NativeCursor native_cursor) { - int type = native_cursor.native_type(); - return cursors_.find(type) != cursors_.end() || - animated_cursors_.find(type) != animated_cursors_.end(); - } - - // Gets the X Cursor corresponding to the |native_cursor|. - ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) { - int type = native_cursor.native_type(); - if (animated_cursors_.find(type) != animated_cursors_.end()) - return animated_cursors_[type].first; - DCHECK(cursors_.find(type) != cursors_.end()); - return cursors_[type]; - } - - private: - // Creates an X Cursor from an image resource and puts it in the cursor map. - void LoadImageCursor(int id, - int resource_id, - const gfx::Point& hot_1x, - const gfx::Point& hot_2x) { - const gfx::ImageSkia* image = - ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); - const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( - ui::GetScaleFactorFromScale(scale_factor_)); - const gfx::Point& hot = (scale_factor_ == 1) ? hot_1x : hot_2x; - 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 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(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 * scale_factor_; - x_image->yhot = hot_y * 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. - } - - // A map to hold all image cursors. It maps the cursor ID to the X Cursor. - std::map<int, Cursor> cursors_; - - // A map to hold all animated cursors. It maps the cursor ID to the pair of - // the X Cursor and the corresponding XcursorImages. We need a pointer to the - // images so that we can free them on destruction. - typedef std::map<int, std::pair<Cursor, XcursorImages*> > AnimatedCursorMap; - AnimatedCursorMap animated_cursors_; - - float scale_factor_; - - DISALLOW_COPY_AND_ASSIGN(ImageCursors); -}; - RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, const gfx::Rect& bounds) : delegate_(delegate), @@ -560,7 +292,6 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, bounds_(bounds), focus_when_shown_(false), pointer_barriers_(NULL), - image_cursors_(new ImageCursors), atom_cache_(xdisplay_, kAtomsToCache) { XSetWindowAttributes swa; memset(&swa, 0, sizeof(swa)); @@ -598,18 +329,7 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, XGetWindowAttributes(xdisplay_, x_root_window_, &attrs); x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height); - // 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_, xwindow_, - nodata, 8, 8); - invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, - &black, &black, 0, 0); - XFreePixmap(xdisplay_, blank); - - if (RootWindow::hide_host_cursor()) - XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); + invisible_cursor_ = ui::CreateInvisibleCursor(); // TODO(erg): We currently only request window deletion events. We also // should listen for activation events and anything else that GTK+ listens @@ -652,9 +372,6 @@ RootWindowHostLinux::~RootWindowHostLinux() { XDestroyWindow(xdisplay_, xwindow_); - // Clears XCursorCache. - ui::GetXCursor(ui::kCursorClearXCursorCache); - XFreeCursor(xdisplay_, invisible_cursor_); } @@ -664,6 +381,11 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { CheckXEventForConsistency(xev); switch (xev->type) { + case EnterNotify: { + ui::MouseEvent mouseenter_event(xev); + delegate_->OnHostMouseEvent(&mouseenter_event); + break; + } case Expose: delegate_->AsRootWindow()->ScheduleFullDraw(); break; @@ -915,9 +637,6 @@ gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { } void RootWindowHostLinux::Show() { - // The device scale factor is now accessible, so load cursors now. - image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); - if (!window_mapped_) { // Before we map the window, set size hints. Otherwise, some window managers // will ignore toplevel XMoveWindow commands. @@ -1006,7 +725,7 @@ void RootWindowHostLinux::ShowCursor(bool show) { if (show == cursor_shown_) return; cursor_shown_ = show; - SetCursorInternal(show ? current_cursor_ : ui::kCursorNone); + SetCursorInternal(show ? current_cursor_ : invisible_cursor_); } bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { @@ -1173,7 +892,6 @@ void RootWindowHostLinux::PostNativeEvent( void RootWindowHostLinux::OnDeviceScaleFactorChanged( float device_scale_factor) { - image_cursors_->Reload(device_scale_factor); } void RootWindowHostLinux::PrepareForShutdown() { @@ -1188,22 +906,7 @@ bool RootWindowHostLinux::IsWindowManagerPresent() { } void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { - // At times the cursor on the RootWindow is set before it is displayed. So - // make sure the image-cursors are initialized properly before setting it. - image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); - - ::Cursor xcursor; - if (image_cursors_->IsImageCursor(cursor)) - xcursor = image_cursors_->ImageCursorFromNative(cursor); - else if (cursor == ui::kCursorNone) - xcursor = invisible_cursor_; - else if (cursor == ui::kCursorCustom) - xcursor = cursor.platform(); - else if (delegate_->GetDeviceScaleFactor() == 1.0) - xcursor = ui::GetXCursor(CursorShapeFromNative(cursor)); - else - xcursor = image_cursors_->ImageCursorFromNative(ui::kCursorPointer); - XDefineCursor(xdisplay_, xwindow_, xcursor); + XDefineCursor(xdisplay_, xwindow_, cursor.platform()); } // static diff --git a/ui/aura/root_window_host_linux.h b/ui/aura/root_window_host_linux.h index 86c6ae4..18e88c0 100644 --- a/ui/aura/root_window_host_linux.h +++ b/ui/aura/root_window_host_linux.h @@ -101,9 +101,6 @@ class RootWindowHostLinux : public RootWindowHost, scoped_ptr<ui::ViewProp> prop_; - class ImageCursors; - scoped_ptr<ImageCursors> image_cursors_; - X11AtomCache atom_cache_; DISALLOW_COPY_AND_ASSIGN(RootWindowHostLinux); diff --git a/ui/aura/root_window_host_win.cc b/ui/aura/root_window_host_win.cc index a4b2e2d..11f0aee 100644 --- a/ui/aura/root_window_host_win.cc +++ b/ui/aura/root_window_host_win.cc @@ -24,6 +24,7 @@ namespace { const char* kRootWindowHostWinKey = "__AURA_ROOT_WINDOW_HOST_WIN__"; +// TODO(mazda): Move the cursor code to ui/base/cursor/cursor_loader_win.{cc,h}. const wchar_t* GetCursorId(gfx::NativeCursor native_cursor) { switch (native_cursor.native_type()) { case ui::kCursorNull: diff --git a/ui/aura/shared/compound_event_filter.cc b/ui/aura/shared/compound_event_filter.cc index 6ddda9b..7e14cf7 100644 --- a/ui/aura/shared/compound_event_filter.cc +++ b/ui/aura/shared/compound_event_filter.cc @@ -6,6 +6,7 @@ #include "ui/aura/client/activation_client.h" #include "ui/aura/client/cursor_client.h" +#include "ui/aura/client/drag_drop_client.h" #include "ui/aura/env.h" #include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" @@ -86,9 +87,17 @@ size_t CompoundEventFilter::GetFilterCount() const { // CompoundEventFilter, private: void CompoundEventFilter::UpdateCursor(Window* target, ui::MouseEvent* event) { - client::CursorClient* client = - client::GetCursorClient(target->GetRootWindow()); - if (client) { + // If drag and drop is in progress, let the drag drop client set the cursor + // instead of setting the cursor here. + aura::RootWindow* root_window = target->GetRootWindow(); + client::DragDropClient* drag_drop_client = + client::GetDragDropClient(root_window); + if (drag_drop_client && drag_drop_client->IsDragDropInProgress()) + return; + + client::CursorClient* cursor_client = + client::GetCursorClient(root_window); + if (cursor_client) { gfx::NativeCursor cursor = target->GetCursor(event->location()); if (event->flags() & ui::EF_IS_NON_CLIENT) { int window_component = @@ -96,7 +105,9 @@ void CompoundEventFilter::UpdateCursor(Window* target, ui::MouseEvent* event) { cursor = CursorForWindowComponent(window_component); } - client->SetCursor(cursor); + cursor_client->SetCursor(cursor); + cursor_client->SetDeviceScaleFactor( + root_window->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); } } @@ -181,7 +192,11 @@ ui::EventResult CompoundEventFilter::OnMouseEvent(ui::MouseEvent* event) { // It should also update the cursor for clicking and wheels for ChromeOS boot. // When ChromeOS is booted, it hides the mouse cursor but immediate mouse // operation will show the cursor. - if (event->type() == ui::ET_MOUSE_MOVED || + // We also update the cursor for mouse enter in case a mouse cursor is sent to + // outside of the root window and moved back for some reasons (e.g. running on + // on Desktop for testing, or a bug in pointer barrier). + if (event->type() == ui::ET_MOUSE_ENTERED || + event->type() == ui::ET_MOUSE_MOVED || event->type() == ui::ET_MOUSE_PRESSED || event->type() == ui::ET_MOUSEWHEEL) { SetCursorVisibilityOnEvent(window, event, true); diff --git a/ui/aura/shared/compound_event_filter_unittest.cc b/ui/aura/shared/compound_event_filter_unittest.cc index a74591c..4a7bad2 100644 --- a/ui/aura/shared/compound_event_filter_unittest.cc +++ b/ui/aura/shared/compound_event_filter_unittest.cc @@ -37,6 +37,9 @@ class TestVisibleClient : public aura::client::CursorClient { return visible_; } + virtual void SetDeviceScaleFactor(float scale_factor) OVERRIDE { + } + private: bool visible_; }; diff --git a/ui/base/cursor/cursor.cc b/ui/base/cursor/cursor.cc index e2811bf..223042e 100644 --- a/ui/base/cursor/cursor.cc +++ b/ui/base/cursor/cursor.cc @@ -8,17 +8,20 @@ namespace ui { Cursor::Cursor() : native_type_(0), - platform_cursor_(0) { + platform_cursor_(0), + device_scale_factor_(0.0f) { } Cursor::Cursor(int type) : native_type_(type), - platform_cursor_(0) { + platform_cursor_(0), + device_scale_factor_(0.0f) { } Cursor::Cursor(const Cursor& cursor) : native_type_(cursor.native_type_), - platform_cursor_(cursor.platform_cursor_) { + platform_cursor_(cursor.platform_cursor_), + device_scale_factor_(cursor.device_scale_factor_) { if (native_type_ == kCursorCustom) RefCustomCursor(); } @@ -29,22 +32,23 @@ Cursor::~Cursor() { } void Cursor::SetPlatformCursor(const PlatformCursor& platform) { - if (platform_cursor_) + if (native_type_ == kCursorCustom) UnrefCustomCursor(); - native_type_ = kCursorCustom; platform_cursor_ = platform; - RefCustomCursor(); + if (native_type_ == kCursorCustom) + RefCustomCursor(); } void Cursor::Assign(const Cursor& cursor) { if (*this == cursor) return; native_type_ = cursor.native_type_; - if (platform_cursor_) + if (native_type_ == kCursorCustom) UnrefCustomCursor(); platform_cursor_ = cursor.platform_cursor_; - if (platform_cursor_) + if (native_type_ == kCursorCustom) RefCustomCursor(); + device_scale_factor_ = cursor.device_scale_factor_; } } // namespace ui diff --git a/ui/base/cursor/cursor.h b/ui/base/cursor/cursor.h index 2383274..43c201d 100644 --- a/ui/base/cursor/cursor.h +++ b/ui/base/cursor/cursor.h @@ -102,16 +102,24 @@ class UI_EXPORT Cursor { int native_type() const { return native_type_; } PlatformCursor platform() const { return platform_cursor_; } + float device_scale_factor() const { + return device_scale_factor_; + } + void set_device_scale_factor(float device_scale_factor) { + device_scale_factor_ = device_scale_factor; + } bool operator==(int type) const { return native_type_ == type; } bool operator==(const Cursor& cursor) const { return native_type_ == cursor.native_type_ && - platform_cursor_ == cursor.platform_cursor_; + platform_cursor_ == cursor.platform_cursor_ && + device_scale_factor_ == cursor.device_scale_factor_; } bool operator!=(int type) const { return native_type_ != type; } bool operator!=(const Cursor& cursor) const { return native_type_ != cursor.native_type_ || - platform_cursor_ != cursor.platform_cursor_; + platform_cursor_ != cursor.platform_cursor_ || + device_scale_factor_ != cursor.device_scale_factor_; } void operator=(const Cursor& cursor) { @@ -125,6 +133,9 @@ class UI_EXPORT Cursor { int native_type_; PlatformCursor platform_cursor_; + + // The device scale factor for the cursor. + float device_scale_factor_; }; } // namespace ui diff --git a/ui/base/cursor/cursor_loader.h b/ui/base/cursor/cursor_loader.h new file mode 100644 index 0000000..48167e7 --- /dev/null +++ b/ui/base/cursor/cursor_loader.h @@ -0,0 +1,61 @@ +// 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. + +#ifndef UI_BASE_CURSOR_CURSOR_LOADER_H_ +#define UI_BASE_CURSOR_CURSOR_LOADER_H_ + +#include "base/logging.h" +#include "ui/base/ui_export.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/point.h" + +namespace ui { + +class UI_EXPORT CursorLoader { + public: + CursorLoader() : device_scale_factor_(0.0f) {} + virtual ~CursorLoader() {} + + // Returns the device scale factor used by the loader. + float device_scale_factor() const { + return device_scale_factor_; + } + + // Sets the device scale factor used by the loader. + void set_device_scale_factor(float device_scale_factor) { + device_scale_factor_ = device_scale_factor; + } + + // Creates a cursor from an image resource and puts it in the cursor map. + virtual void LoadImageCursor(int id, + int resource_id, + const gfx::Point& hot) = 0; + + // Creates an animated cursor from an image resource and puts it in the + // cursor map. The image is assumed to be a concatenation of animation frames + // from left to right. Also, each frame is assumed to be square + // (width == height). + // |frame_delay_ms| is the delay between frames in millisecond. + virtual void LoadAnimatedCursor(int id, + int resource_id, + const gfx::Point& hot, + int frame_delay_ms) = 0; + + // Unloads all the cursors. + virtual void UnloadAll() = 0; + + // Sets the platform cursor based on the native type of |cursor|. + virtual void SetPlatformCursor(gfx::NativeCursor* cursor) = 0; + + // Creates a CursorLoader. + static CursorLoader* Create(); + + private: + // The device scale factor used by the loader. + float device_scale_factor_; +}; + +} // namespace ui + +#endif // UI_BASE_CURSOR_CURSOR_LOADER_H_ diff --git a/ui/base/cursor/cursor_loader_win.cc b/ui/base/cursor/cursor_loader_win.cc new file mode 100644 index 0000000..8fc9adc --- /dev/null +++ b/ui/base/cursor/cursor_loader_win.cc @@ -0,0 +1,40 @@ +// 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_win.h" + +namespace ui { + +CursorLoader* CursorLoader::Create() { + return new CursorLoaderWin; +} + +CursorLoaderWin::CursorLoaderWin() { +} + +CursorLoaderWin::~CursorLoaderWin() { +} + +void CursorLoaderWin::LoadImageCursor(int id, + int resource_id, + const gfx::Point& hot) { + // NOTIMPLEMENTED(); +} + +void CursorLoaderWin::LoadAnimatedCursor(int id, + int resource_id, + const gfx::Point& hot, + int frame_delay_ms) { + // NOTIMPLEMENTED(); +} + +void CursorLoaderWin::UnloadAll() { + // NOTIMPLEMENTED(); +} + +void CursorLoaderWin::SetPlatformCursor(gfx::NativeCursor* cursor) { + // NOTIMPLEMENTED(); +} + +} // namespace ui diff --git a/ui/base/cursor/cursor_loader_win.h b/ui/base/cursor/cursor_loader_win.h new file mode 100644 index 0000000..6447283 --- /dev/null +++ b/ui/base/cursor/cursor_loader_win.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef UI_BASE_CURSOR_CURSOR_LOADER_WIN_H_ +#define UI_BASE_CURSOR_CURSOR_LOADER_WIN_H_ + +#include "base/compiler_specific.h" +#include "ui/base/cursor/cursor_loader.h" + +namespace ui { + +class CursorLoaderWin : public CursorLoader { + public: + CursorLoaderWin(); + virtual ~CursorLoaderWin(); + + // Overridden from CursorLoader: + virtual void LoadImageCursor(int id, + int resource_id, + const gfx::Point& hot) OVERRIDE; + virtual void LoadAnimatedCursor(int id, + int resource_id, + const gfx::Point& hot, + int frame_delay_ms) OVERRIDE; + virtual void UnloadAll() OVERRIDE; + virtual void SetPlatformCursor(gfx::NativeCursor* cursor) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(CursorLoaderWin); +}; + +} // namespace ui + +#endif // UI_BASE_CURSOR_CURSOR_LOADER_WIN_H_ diff --git a/ui/base/cursor/cursor_loader_x11.cc b/ui/base/cursor/cursor_loader_x11.cc new file mode 100644 index 0000000..dce19d4 --- /dev/null +++ b/ui/base/cursor/cursor_loader_x11.cc @@ -0,0 +1,203 @@ +// 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 { + +// 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() { +} + +CursorLoaderX11::~CursorLoaderX11() { + UnloadAll(); + // Clears XCursorCache. + ui::GetXCursor(ui::kCursorClearXCursorCache); +} + +void CursorLoaderX11::LoadImageCursor(int id, + int resource_id, + const gfx::Point& hot) { + const gfx::ImageSkia* image = + ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); + const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( + ui::GetScaleFactorFromScale(device_scale_factor())); + XcursorImage* x_image = + ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot); + cursors_[id] = ui::CreateReffedCustomXCursor(x_image); + // |image_rep| is owned by the resource bundle. So we do not need to free it. +} + +void CursorLoaderX11::LoadAnimatedCursor(int id, + int resource_id, + const gfx::Point& hot, + int frame_delay_ms) { + 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 frame = 0; frame < frame_count; ++frame) { + XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height); + for (int row = 0; row < frame_height; ++row) { + // Copy |row|'th row of |frame|'th frame. + memcpy(x_image->pixels + row * frame_width, + pixels + frame * frame_width + row * total_width, + frame_width * 4); + } + x_image->xhot = hot.x(); + x_image->yhot = hot.y(); + x_image->delay = frame_delay_ms; + x_images->images[frame] = 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::kCursorCustom) + xcursor = cursor->platform(); + else if (device_scale_factor() == 1.0f) + xcursor = ui::GetXCursor(CursorShapeFromNative(*cursor)); + else + xcursor = ImageCursorFromNative(ui::kCursorPointer); + + cursor->SetPlatformCursor(xcursor); +} + +bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) { + int type = native_cursor.native_type(); + return cursors_.count(type) || animated_cursors_.count(type); +} + +::Cursor CursorLoaderX11::ImageCursorFromNative( + gfx::NativeCursor native_cursor) { + int type = native_cursor.native_type(); + if (animated_cursors_.count(type)) + return animated_cursors_[type].first; + DCHECK(cursors_.find(type) != cursors_.end()); + return cursors_[type]; +} + +} diff --git a/ui/base/cursor/cursor_loader_x11.h b/ui/base/cursor/cursor_loader_x11.h new file mode 100644 index 0000000..32f0e1a --- /dev/null +++ b/ui/base/cursor/cursor_loader_x11.h @@ -0,0 +1,58 @@ +// 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. + +#ifndef UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ +#define UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ + +#include <X11/Xcursor/Xcursor.h> +#include <map> + +#include "base/compiler_specific.h" +#include "ui/base/cursor/cursor.h" +#include "ui/base/cursor/cursor_loader.h" + +namespace ui { + +class CursorLoaderX11 : public CursorLoader { + public: + CursorLoaderX11(); + virtual ~CursorLoaderX11(); + + // Overridden from CursorLoader: + virtual void LoadImageCursor(int id, + int resource_id, + const gfx::Point& hot) OVERRIDE; + virtual void LoadAnimatedCursor(int id, + int resource_id, + const gfx::Point& hot, + int frame_delay_ms) OVERRIDE; + virtual void UnloadAll() OVERRIDE; + virtual void SetPlatformCursor(gfx::NativeCursor* cursor) OVERRIDE; + + private: + // Returns true if we have an image resource loaded for the |native_cursor|. + bool IsImageCursor(gfx::NativeCursor native_cursor); + + // Gets the X Cursor corresponding to the |native_cursor|. + ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor); + + // A map to hold all image cursors. It maps the cursor ID to the X Cursor. + typedef std::map<int, ::Cursor> ImageCursorMap; + ImageCursorMap cursors_; + + // A map to hold all animated cursors. It maps the cursor ID to the pair of + // the X Cursor and the corresponding XcursorImages. We need a pointer to the + // images so that we can free them on destruction. + typedef std::map<int, std::pair< ::Cursor, XcursorImages*> > + AnimatedCursorMap; + AnimatedCursorMap animated_cursors_; + + ::Cursor invisible_cursor_; + + DISALLOW_COPY_AND_ASSIGN(CursorLoaderX11); +}; + +} // namespace ui + +#endif // UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index dff3298..1dd3a66 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -775,6 +775,10 @@ base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { case MotionNotify: return base::TimeDelta::FromMilliseconds(native_event->xmotion.time); break; + case EnterNotify: + case LeaveNotify: + return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time); + break; case GenericEvent: { double start, end; if (GetGestureTimes(native_event, &start, &end)) { diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc index efe05af..05f50ec 100644 --- a/ui/base/x/x11_util.cc +++ b/ui/base/x/x11_util.cc @@ -453,6 +453,28 @@ XcursorImage* SkBitmapToXcursorImage(const SkBitmap* bitmap, } #endif +void HideHostCursor() { + CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, + (CreateInvisibleCursor(), ui::GetXDisplay())); + XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()), + invisible_cursor.get()); +} + +::Cursor CreateInvisibleCursor() { + Display* xdisplay = ui::GetXDisplay(); + ::Cursor 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); + return invisible_cursor; +} + XID GetX11RootWindow() { return DefaultRootWindow(GetXDisplay()); } @@ -1352,6 +1374,25 @@ XScopedString::~XScopedString() { XFree(string_); } +XScopedCursor::XScopedCursor(::Cursor cursor, Display* display) + : cursor_(cursor), + display_(display) { +} + +XScopedCursor::~XScopedCursor() { + reset(0U); +} + +::Cursor XScopedCursor::get() const { + return cursor_; +} + +void XScopedCursor::reset(::Cursor cursor) { + if (cursor_) + XFreeCursor(display_, cursor_); + cursor_ = cursor; +} + // ---------------------------------------------------------------------------- // These functions are declared in x11_util_internal.h because they require // XLib.h to be included, and it conflicts with many other headers. diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h index 869ef7c..d6dc0c3 100644 --- a/ui/base/x/x11_util.h +++ b/ui/base/x/x11_util.h @@ -97,6 +97,12 @@ UI_EXPORT XcursorImage* SkBitmapToXcursorImage(const SkBitmap* bitmap, const gfx::Point& hotspot); #endif +// Hides the host cursor. +UI_EXPORT void HideHostCursor(); + +// Returns an invisible cursor. +UI_EXPORT ::Cursor CreateInvisibleCursor(); + // These functions do not cache their results -------------------------- // Get the X window id for the default root window @@ -319,6 +325,24 @@ class UI_EXPORT XScopedString { DISALLOW_COPY_AND_ASSIGN(XScopedString); }; +// Keeps track of a cursor returned by an X function and makes sure it's +// XFreeCursor'd. +class UI_EXPORT XScopedCursor { + public: + // Keeps track of |cursor| created with |display|. + XScopedCursor(::Cursor cursor, Display* display); + ~XScopedCursor(); + + ::Cursor get() const; + void reset(::Cursor cursor); + + private: + ::Cursor cursor_; + Display* display_; + + DISALLOW_COPY_AND_ASSIGN(XScopedCursor); +}; + } // namespace ui #endif // UI_BASE_X_X11_UTIL_H_ @@ -137,6 +137,11 @@ 'base/cocoa/window_size_constants.mm', 'base/cursor/cursor.cc', 'base/cursor/cursor.h', + 'base/cursor/cursor_loader.h', + 'base/cursor/cursor_loader_win.cc', + 'base/cursor/cursor_loader_win.h', + 'base/cursor/cursor_loader_x11.cc', + 'base/cursor/cursor_loader_x11.h', 'base/cursor/cursor_win.cc', 'base/cursor/cursor_x11.cc', 'base/dialogs/base_shell_dialog.cc', @@ -542,6 +547,8 @@ 'sources!': [ 'base/cursor/cursor.cc', 'base/cursor/cursor.h', + 'base/cursor/cursor_loader_x11.cc', + 'base/cursor/cursor_loader_x11.h', 'base/cursor/cursor_win.cc', 'base/cursor/cursor_x11.cc', 'base/native_theme/native_theme_aura.cc', diff --git a/webkit/glue/webcursor_aura.cc b/webkit/glue/webcursor_aura.cc index 2642c47..4510e96f 100644 --- a/webkit/glue/webcursor_aura.cc +++ b/webkit/glue/webcursor_aura.cc @@ -99,7 +99,7 @@ gfx::NativeCursor WebCursor::GetNativeCursor() { case WebCursorInfo::TypeGrabbing: return ui::kCursorGrabbing; case WebCursorInfo::TypeCustom: { - ui::Cursor cursor; + ui::Cursor cursor(ui::kCursorCustom); cursor.SetPlatformCursor(GetPlatformCursor()); return cursor; } |