// Copyright 2016 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/platform_window/x11/x11_cursor_ozone.h" #include #include #include "base/logging.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/geometry/point.h" namespace ui { namespace { // Converts a SKBitmap to unpremul alpha. SkBitmap ConvertSkBitmapToUnpremul(const SkBitmap& bitmap) { DCHECK_NE(bitmap.alphaType(), kUnpremul_SkAlphaType); SkImageInfo image_info = SkImageInfo::MakeN32(bitmap.width(), bitmap.height(), kUnpremul_SkAlphaType); SkBitmap converted_bitmap; converted_bitmap.allocPixels(image_info); bitmap.readPixels(image_info, converted_bitmap.getPixels(), image_info.minRowBytes(), 0, 0); return converted_bitmap; } // Creates an XCursorImage for cursor bitmap. XcursorImage* CreateXCursorImage(const SkBitmap& bitmap, const gfx::Point& hotspot) { // X11 expects bitmap with unpremul alpha. If bitmap is premul then convert, // otherwise semi-transparent parts of cursor will look strange. if (bitmap.alphaType() != kUnpremul_SkAlphaType) { SkBitmap converted_bitmap = ConvertSkBitmapToUnpremul(bitmap); return SkBitmapToXcursorImage(&converted_bitmap, hotspot); } else { return SkBitmapToXcursorImage(&bitmap, hotspot); } } } // namespace X11CursorOzone::X11CursorOzone(const SkBitmap& bitmap, const gfx::Point& hotspot) { XcursorImage* image = CreateXCursorImage(bitmap, hotspot); xcursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image); XcursorImageDestroy(image); } X11CursorOzone::X11CursorOzone(const std::vector& bitmaps, const gfx::Point& hotspot, int frame_delay_ms) { // Initialize an XCursorImage for each frame, store all of them in // XCursorImages and load the cursor from that. XcursorImages* images = XcursorImagesCreate(bitmaps.size()); images->nimage = bitmaps.size(); for (size_t frame = 0; frame < bitmaps.size(); ++frame) { XcursorImage* x_image = CreateXCursorImage(bitmaps[frame], hotspot); x_image->delay = frame_delay_ms; images->images[frame] = x_image; } xcursor_ = XcursorImagesLoadCursor(gfx::GetXDisplay(), images); XcursorImagesDestroy(images); } scoped_refptr X11CursorOzone::CreateInvisible() { scoped_refptr invisible_ = new X11CursorOzone(); invisible_->xcursor_ = CreateInvisibleCursor(); return invisible_; } X11CursorOzone::X11CursorOzone() {} X11CursorOzone::~X11CursorOzone() { XFreeCursor(gfx::GetXDisplay(), xcursor_); } } // namespace ui