Skip to content

Commit

Permalink
Enable custom cursor for software-composited cursor
Browse files Browse the repository at this point in the history
Changes:
1.Make ui::Cursor support |custom_bitmap| and |custom_cursor| which are
  set by exo pointer or web cursor.

2.Add GetBitmap() and GetHotspot() in ui::Cursor and merge the usage of
  ui::GetCursorBitmap().

3.Avoid overwriting custom type to default pointer when cursor
  compositing is enabled.

4.Also, remove the usage of CursorWindowController to match settings of
  the primary display when cursor compositing is disabled, because it
  was only used in mirror mode which now enables cursor compositing.

BUG=708378

Change-Id: I5dc3ef15adf00424fe62fc24cb005dfb5bed3f5b
Reviewed-on: https://chromium-review.googlesource.com/910229
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Robert Kroeger <rjkroege@chromium.org>
Reviewed-by: David Reveman <reveman@chromium.org>
Reviewed-by: Joe Downing <joedow@chromium.org>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Reviewed-by: Michael Spang <spang@chromium.org>
Commit-Queue: Weidong Guo <weidongg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550846}
  • Loading branch information
Weidong Guo authored and Commit Bot committed Apr 14, 2018
1 parent 3bce864 commit a8f5645
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 360 deletions.
141 changes: 52 additions & 89 deletions ash/display/cursor_window_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,7 @@ void CursorWindowController::UpdateContainer() {
if (display.is_valid())
SetDisplay(display);
} else {
aura::Window::Windows mirror_windows = Shell::Get()
->window_tree_host_manager()
->mirror_window_controller()
->GetAllRootWindows();
if (mirror_windows.empty()) {
SetContainer(nullptr);
return;
}
display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
SetContainer(mirror_windows[0]);
SetContainer(nullptr);
}
// Updates the hot point based on the current display.
UpdateCursorImage();
Expand Down Expand Up @@ -208,24 +199,20 @@ void CursorWindowController::SetDisplay(const display::Display& display) {
}

void CursorWindowController::UpdateLocation() {
gfx::Point point = aura::Env::GetInstance()->last_mouse_location();
if (!is_cursor_compositing_enabled_) {
Shell::GetPrimaryRootWindow()->GetHost()->ConvertDIPToPixels(&point);
} else {
point.Offset(-bounds_in_screen_.x(), -bounds_in_screen_.y());
}
if (!cursor_window_)
return;
gfx::Point point = aura::Env::GetInstance()->last_mouse_location();
point.Offset(-bounds_in_screen_.x(), -bounds_in_screen_.y());
point.Offset(-hot_point_.x(), -hot_point_.y());
gfx::Rect bounds = cursor_window_->bounds();
bounds.set_origin(point);
cursor_window_->SetBounds(bounds);
}

void CursorWindowController::SetCursor(gfx::NativeCursor cursor) {
if (cursor_type_ == cursor.native_type())
if (cursor_ == cursor)
return;
cursor_type_ = cursor.native_type();
cursor_ = cursor;
UpdateCursorImage();
UpdateCursorVisibility();
}
Expand Down Expand Up @@ -285,82 +272,58 @@ void CursorWindowController::SetBoundsInScreenAndRotation(
}

void CursorWindowController::UpdateCursorImage() {
float cursor_scale;
if (!is_cursor_compositing_enabled_) {
cursor_scale = display_.device_scale_factor();
} else {
// Use the original device scale factor instead of the display's, which
// might have been adjusted for the UI scale.
const float original_scale = Shell::Get()
->display_manager()
->GetDisplayInfo(display_.id())
.device_scale_factor();
// And use the nearest resource scale factor.
cursor_scale =
ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(original_scale));
}
int resource_id;
// TODO(hshi): support custom cursor set.
if (!ui::GetCursorDataFor(cursor_size_, cursor_type_, cursor_scale,
&resource_id, &hot_point_)) {
if (!is_cursor_compositing_enabled_)
return;
}
const gfx::ImageSkia* image =
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
if (!is_cursor_compositing_enabled_) {
gfx::ImageSkia rotated = *image;
switch (display_.rotation()) {
case display::Display::ROTATE_0:
break;
case display::Display::ROTATE_90:
rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
*image, SkBitmapOperations::ROTATION_90_CW);
hot_point_.SetPoint(rotated.width() - hot_point_.y(), hot_point_.x());
break;
case display::Display::ROTATE_180:
rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
*image, SkBitmapOperations::ROTATION_180_CW);
hot_point_.SetPoint(rotated.height() - hot_point_.x(),
rotated.width() - hot_point_.y());
break;
case display::Display::ROTATE_270:
rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
*image, SkBitmapOperations::ROTATION_270_CW);
hot_point_.SetPoint(hot_point_.y(), rotated.height() - hot_point_.x());
break;
}
// Note that mirror window's scale factor is always 1.0f, therefore we
// need to take 2x's image and paint as if it's 1x image.
const gfx::ImageSkiaRep& image_rep =
rotated.GetRepresentation(cursor_scale);
delegate_->SetCursorImage(
image_rep.pixel_size(),
gfx::ImageSkia::CreateFrom1xBitmap(image_rep.sk_bitmap()));

// Use the original device scale factor instead of the display's, which
// might have been adjusted for the UI scale.
const float original_scale = Shell::Get()
->display_manager()
->GetDisplayInfo(display_.id())
.device_scale_factor();
// And use the nearest resource scale factor.
float cursor_scale =
ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(original_scale));

gfx::ImageSkia image;
if (cursor_.native_type() == ui::CursorType::kCustom) {
SkBitmap bitmap = cursor_.GetBitmap();
if (bitmap.isNull())
return;
image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
hot_point_ = cursor_.GetHotspot();
} else {
gfx::ImageSkia resized = *image;

// Rescale cursor size. This is used with the combination of accessibility
// large cursor. We don't need to care about the case where cursor
// compositing is disabled as we always use cursor compositing if
// accessibility large cursor is enabled.
if (cursor_size_ == ui::CursorSize::kLarge &&
large_cursor_size_in_dip_ != image->size().width()) {
float rescale = static_cast<float>(large_cursor_size_in_dip_) /
static_cast<float>(image->size().width());
resized = gfx::ImageSkiaOperations::CreateResizedImage(
*image, skia::ImageOperations::ResizeMethod::RESIZE_GOOD,
gfx::ScaleToCeiledSize(image->size(), rescale));
hot_point_ = gfx::ScaleToCeiledPoint(hot_point_, rescale);
int resource_id;
if (!ui::GetCursorDataFor(cursor_size_, cursor_.native_type(), cursor_scale,
&resource_id, &hot_point_)) {
return;
}
image =
*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
}

const gfx::ImageSkiaRep& image_rep =
resized.GetRepresentation(cursor_scale);
delegate_->SetCursorImage(
resized.size(),
gfx::ImageSkia(gfx::ImageSkiaRep(image_rep.sk_bitmap(), cursor_scale)));
hot_point_ = gfx::ConvertPointToDIP(cursor_scale, hot_point_);
gfx::ImageSkia resized = image;

// Rescale cursor size. This is used with the combination of accessibility
// large cursor. We don't need to care about the case where cursor
// compositing is disabled as we always use cursor compositing if
// accessibility large cursor is enabled.
if (cursor_size_ == ui::CursorSize::kLarge &&
large_cursor_size_in_dip_ != image.size().width()) {
float rescale = static_cast<float>(large_cursor_size_in_dip_) /
static_cast<float>(image.size().width());
resized = gfx::ImageSkiaOperations::CreateResizedImage(
image, skia::ImageOperations::ResizeMethod::RESIZE_GOOD,
gfx::ScaleToCeiledSize(image.size(), rescale));
hot_point_ = gfx::ScaleToCeiledPoint(hot_point_, rescale);
}

const gfx::ImageSkiaRep& image_rep = resized.GetRepresentation(cursor_scale);
delegate_->SetCursorImage(
resized.size(),
gfx::ImageSkia(gfx::ImageSkiaRep(image_rep.sk_bitmap(), cursor_scale)));
hot_point_ = gfx::ConvertPointToDIP(cursor_scale, hot_point_);

if (cursor_view_) {
cursor_view_->SetCursorImage(delegate_->cursor_image(), delegate_->size(),
hot_point_);
Expand All @@ -374,7 +337,7 @@ void CursorWindowController::UpdateCursorImage() {
}

void CursorWindowController::UpdateCursorVisibility() {
bool visible = (visible_ && cursor_type_ != ui::CursorType::kNone);
bool visible = (visible_ && cursor_.native_type() != ui::CursorType::kNone);
if (visible) {
if (cursor_view_)
cursor_view_->GetWidget()->Show();
Expand Down
9 changes: 4 additions & 5 deletions ash/display/cursor_window_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ class CursorWindowControllerTest;
class CursorWindowDelegate;

// Draws a mouse cursor on a given container window.
// When cursor compositing is disabled, CursorWindowController is responsible
// to scale and rotate the mouse cursor bitmap to match settings of the
// primary display.
// When cursor compositing is disabled, draw nothing as the native cursor is
// shown.
// When cursor compositing is enabled, just draw the cursor as-is.
class ASH_EXPORT CursorWindowController {
public:
Expand Down Expand Up @@ -94,8 +93,8 @@ class ASH_EXPORT CursorWindowController {
// The rotation of the container.
display::Display::Rotation rotation_ = display::Display::ROTATE_0;

// The native_type of the cursor, see definitions in cursor.h
ui::CursorType cursor_type_ = ui::CursorType::kNone;
// The native cursor, see definitions in cursor.h
gfx::NativeCursor cursor_ = ui::CursorType::kNone;

// The last requested cursor visibility.
bool visible_ = true;
Expand Down
2 changes: 1 addition & 1 deletion ash/display/cursor_window_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class CursorWindowControllerTest : public AshTestBase {
}

ui::CursorType GetCursorType() const {
return cursor_window_controller_->cursor_type_;
return cursor_window_controller_->cursor_.native_type();
}

const gfx::Point& GetCursorHotPoint() const {
Expand Down
Loading

0 comments on commit a8f5645

Please sign in to comment.