Skip to content

Commit

Permalink
Aura: Adds custom cursors for drag and drop (second attempt:
Browse files Browse the repository at this point in the history
first attempt reverted due to build break:
http://codereview.chromium.org/10316019 )

BUG=121135
TEST=none


Review URL: https://chromiumcodereview.appspot.com/10378079

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136653 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
varunjain@chromium.org committed May 11, 2012
1 parent ce4f353 commit f54bd17
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 53 deletions.
2 changes: 1 addition & 1 deletion ash/drag_drop/drag_drop_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void DragDropController::DragUpdate(aura::Window* target,
drag_operation_);
int op = delegate->OnDragUpdated(e);
gfx::NativeCursor cursor = (op == ui::DragDropTypes::DRAG_NONE)?
ui::kCursorMove : ui::kCursorHand;
ui::kCursorNoDrop : ui::kCursorCopy;
Shell::GetRootWindow()->SetCursor(cursor);
}
}
Expand Down
3 changes: 2 additions & 1 deletion content/test/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ include_rules = [
# Testing utilities can access anything in content/
"+content",
"+media/base", # For ChannelLayout in WebRTC tests.
"+ui/base/resource/data_pack.h"
"+ui/aura/test/test_aura_initializer.h",
"+ui/base/resource/data_pack.h",
]
7 changes: 7 additions & 0 deletions content/test/content_test_suite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ui_base_paths.h"

#if defined(USE_AURA)
#include "ui/aura/test/test_aura_initializer.h"
#endif

#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
Expand Down Expand Up @@ -45,6 +49,9 @@ class TestInitializationListener : public testing::EmptyTestEventListener {

ContentTestSuite::ContentTestSuite(int argc, char** argv)
: base::TestSuite(argc, argv) {
#if defined(USE_AURA)
aura_initializer_.reset(new aura::test::TestAuraInitializer);
#endif
}

ContentTestSuite::~ContentTestSuite() {
Expand Down
14 changes: 13 additions & 1 deletion content/test/content_test_suite.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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.

Expand All @@ -10,6 +10,14 @@
#include "base/test/test_suite.h"
#include "base/win/scoped_com_initializer.h"

#if defined(USE_AURA)
namespace aura {
namespace test {
class TestAuraInitializer;
} // namespace test
} // namespace aura
#endif

class ContentTestSuite : public base::TestSuite {
public:
ContentTestSuite(int argc, char** argv);
Expand All @@ -21,6 +29,10 @@ class ContentTestSuite : public base::TestSuite {
private:
base::win::ScopedCOMInitializer com_initializer_;

#if defined(USE_AURA)
scoped_ptr<aura::test::TestAuraInitializer> aura_initializer_;
#endif

DISALLOW_COPY_AND_ASSIGN(ContentTestSuite);
};

Expand Down
35 changes: 35 additions & 0 deletions ui/aura/aura.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
'../ui.gyp:gfx_resources',
'../ui.gyp:ui',
'../ui.gyp:ui_resources',
'../ui.gyp:ui_resources_2x',
'../ui.gyp:ui_resources_standard',
],
'defines': [
'AURA_IMPLEMENTATION',
Expand Down Expand Up @@ -130,6 +132,7 @@
'../../testing/gtest.gyp:gtest',
'../ui.gyp:ui',
'aura',
'test_support_aura_pak',
],
'include_dirs': [
'..',
Expand All @@ -143,6 +146,8 @@
'test/event_generator.h',
'test/test_activation_client.cc',
'test/test_activation_client.h',
'test/test_aura_initializer.cc',
'test/test_aura_initializer.h',
'test/test_event_filter.cc',
'test/test_event_filter.h',
'test/test_screen.cc',
Expand All @@ -155,6 +160,36 @@
'test/test_window_delegate.h',
],
},
{
# We build a minimal set of resources required for test_support_aura.
'target_name': 'test_support_aura_pak',
'type': 'none',
'dependencies': [
'<(DEPTH)/ui/ui.gyp:ui_resources_standard',
],
'variables': {
'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
},
'actions': [
{
'action_name': 'repack_test_support_aura_pack',
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources_standard/ui_resources_standard.pak',
],
},
'inputs': [
'<(repack_path)',
'<@(pak_inputs)',
],
'outputs': [
'<(PRODUCT_DIR)/test_support_aura_resources.pak',
],
'action': ['python', '<(repack_path)', '<@(_outputs)',
'<@(pak_inputs)'],
},
],
},
{
'target_name': 'aura_demo',
'type': 'executable',
Expand Down
55 changes: 54 additions & 1 deletion ui/aura/root_window_host_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ui/aura/root_window_host_linux.h"

#include <X11/Xatom.h>
#include <X11/Xcursor/Xcursor.h>
#include <X11/cursorfont.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
Expand All @@ -14,17 +15,21 @@
#include "base/message_pump_x.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "grit/ui_resources_standard.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/user_gesture_client.h"
#include "ui/aura/dispatcher_linux.h"
#include "ui/aura/env.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/touch/touch_factory.h"
#include "ui/base/view_prop.h"
#include "ui/base/x/x11_util.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/image/image.h"

using std::max;
using std::min;
Expand Down Expand Up @@ -292,6 +297,51 @@ const char* kAtomList[] = {

} // namespace

// A utility class that provides X Cursor for NativeCursors for which we have
// image resources.
class RootWindowHostLinux::ImageCursors {
public:
ImageCursors() {
LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP);
LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY);
// TODO (varunjain): add more cursors once we have assets.
}

~ImageCursors() {
std::map<int, Cursor>::const_iterator it;
for (it = cursors_.begin(); it != cursors_.end(); ++it)
ui::UnrefCustomXCursor(it->second);
}

// Returns true if we have an image resource loaded for the |native_cursor|.
bool IsImageCursor(gfx::NativeCursor native_cursor) {
return cursors_.find(native_cursor.native_type()) != cursors_.end();
}

// Gets the X Cursor corresponding to the |native_cursor|.
::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) {
DCHECK(cursors_.find(native_cursor.native_type()) != cursors_.end());
return cursors_[native_cursor.native_type()];
}

private:
// Creates an X Cursor from an image resource and puts it in the cursor map.
void LoadImageCursor(int id, int resource_id) {
const SkBitmap* bitmap =
ui::ResourceBundle::GetSharedInstance().GetImageNamed(
resource_id).ToSkBitmap();

XcursorImage* image = ui::SkBitmapToXcursorImage(bitmap, gfx::Point(0, 0));
cursors_[id] = ui::CreateReffedCustomXCursor(image);
// |bitmap| is owned by the resource bundle. So we do not need to free it.
}

// A map to hold all image cursors. It maps the cursor ID to the X Cursor.
std::map<int, Cursor> cursors_;

DISALLOW_COPY_AND_ASSIGN(ImageCursors);
};

RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
: root_window_(NULL),
xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
Expand All @@ -301,7 +351,8 @@ RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
cursor_shown_(true),
bounds_(bounds),
focus_when_shown_(false),
pointer_barriers_(NULL) {
pointer_barriers_(NULL),
image_cursors_(new ImageCursors) {
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = None;
Expand Down Expand Up @@ -794,6 +845,8 @@ bool RootWindowHostLinux::IsWindowManagerPresent() {

void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
::Cursor xcursor =
image_cursors_->IsImageCursor(cursor) ?
image_cursors_->ImageCursorFromNative(cursor) :
cursor == ui::kCursorNone ?
invisible_cursor_ :
cursor == ui::kCursorCustom ?
Expand Down
3 changes: 3 additions & 0 deletions ui/aura/root_window_host_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class RootWindowHostLinux : public RootWindowHost,

scoped_ptr<ui::ViewProp> prop_;

class ImageCursors;
scoped_ptr<ImageCursors> image_cursors_;

DISALLOW_COPY_AND_ASSIGN(RootWindowHostLinux);
};

Expand Down
31 changes: 31 additions & 0 deletions ui/aura/test/test_aura_initializer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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/aura/test/test_aura_initializer.h"

#include "base/base_paths.h"
#include "base/path_service.h"
#include "ui/base/resource/resource_bundle.h"

namespace aura {
namespace test {

TestAuraInitializer::TestAuraInitializer() {
#if defined(OS_LINUX)
FilePath pak_file;
PathService::Get(base::DIR_MODULE, &pak_file);
pak_file = pak_file.Append(FILE_PATH_LITERAL(
"test_support_aura_resources.pak"));
ui::ResourceBundle::InitSharedInstanceWithPakFile(pak_file);
#endif
}

TestAuraInitializer::~TestAuraInitializer() {
#if defined(OS_LINUX)
ui::ResourceBundle::CleanupSharedInstance();
#endif
}

} // namespace test
} // namespace aura
28 changes: 28 additions & 0 deletions ui/aura/test/test_aura_initializer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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_AURA_TEST_TEST_AURA_INITIALIZER_H_
#define UI_AURA_TEST_TEST_AURA_INITIALIZER_H_
#pragma once

#include "base/basictypes.h"

namespace aura {
namespace test {

// Initializes various objects needed to run unit tests that use aura::*
// objects.
class TestAuraInitializer {
public:
TestAuraInitializer();
virtual ~TestAuraInitializer();

private:
DISALLOW_COPY_AND_ASSIGN(TestAuraInitializer);
};

} // namespace test
} // namespace aura

#endif // UI_AURA_TEST_TEST_AURA_INITIALIZER_H_
21 changes: 21 additions & 0 deletions ui/base/x/x11_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

#if defined(USE_AURA)
#include <X11/Xcursor/Xcursor.h>
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/skia_util.h"
#endif

#if defined(TOOLKIT_GTK)
Expand Down Expand Up @@ -411,6 +413,25 @@ void RefCustomXCursor(::Cursor cursor) {
void UnrefCustomXCursor(::Cursor cursor) {
XCustomCursorCache::GetInstance()->Unref(cursor);
}

XcursorImage* SkBitmapToXcursorImage(const SkBitmap* bitmap,
const gfx::Point& hotspot) {
DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
XcursorImage* image = XcursorImageCreate(bitmap->width(), bitmap->height());
image->xhot = hotspot.x();
image->yhot = hotspot.y();

if (bitmap->width() && bitmap->height()) {
bitmap->lockPixels();
gfx::ConvertSkiaToRGBA(
static_cast<const unsigned char*>(bitmap->getPixels()),
bitmap->width() * bitmap->height(),
reinterpret_cast<unsigned char*>(image->pixels));
bitmap->unlockPixels();
}

return image;
}
#endif

XID GetX11RootWindow() {
Expand Down
7 changes: 7 additions & 0 deletions ui/base/x/x11_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "base/basictypes.h"
#include "ui/base/events.h"
#include "ui/base/ui_export.h"
#include "ui/gfx/point.h"

typedef unsigned long Atom;
typedef unsigned long XID;
Expand All @@ -35,6 +36,7 @@ typedef struct _GtkWindow GtkWindow;
namespace gfx {
class Rect;
}
class SkBitmap;

namespace ui {

Expand Down Expand Up @@ -89,6 +91,11 @@ UI_EXPORT void RefCustomXCursor(::Cursor cursor);

// Decreases the refcount of the custom cursor, and destroys it if it reaches 0.
UI_EXPORT void UnrefCustomXCursor(::Cursor cursor);

// Creates a XcursorImage and copies the SkBitmap |bitmap| on it. |bitmap|
// should be non-null. Caller owns the returned object.
UI_EXPORT XcursorImage* SkBitmapToXcursorImage(const SkBitmap* bitmap,
const gfx::Point& hotspot);
#endif

// These functions do not cache their results --------------------------
Expand Down
Loading

0 comments on commit f54bd17

Please sign in to comment.