blob: 0be77eeacba878f650c86a5b157848c244bde192 [file] [log] [blame]
// Copyright 2017 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/ozone/platform/wayland/wayland_cursor.h"
#include <sys/mman.h>
#include <vector>
#include "base/memory/shared_memory.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/skia_util.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_pointer.h"
#include "ui/ozone/platform/wayland/wayland_util.h"
namespace ui {
WaylandCursor::WaylandCursor() : shared_memory_(new base::SharedMemory()) {}
void WaylandCursor::Init(wl_pointer* pointer, WaylandConnection* connection) {
if (input_pointer_ == pointer)
return;
input_pointer_ = pointer;
DCHECK(connection);
shm_ = connection->shm();
pointer_surface_.reset(
wl_compositor_create_surface(connection->compositor()));
}
WaylandCursor::~WaylandCursor() {
pointer_surface_.reset();
buffer_.reset();
if (shared_memory_->handle().GetHandle()) {
shared_memory_->Unmap();
shared_memory_->Close();
}
}
void WaylandCursor::UpdateBitmap(const std::vector<SkBitmap>& cursor_image,
const gfx::Point& location,
uint32_t serial) {
if (!input_pointer_)
return;
if (!cursor_image.size()) {
HideCursor(serial);
return;
}
const SkBitmap& image = cursor_image[0];
SkISize size = image.dimensions();
if (size.isEmpty()) {
HideCursor(serial);
return;
}
gfx::Size image_size = gfx::SkISizeToSize(size);
if (image_size != size_) {
wl_buffer* buffer =
wl::CreateSHMBuffer(image_size, shared_memory_.get(), shm_);
if (!buffer) {
LOG(ERROR) << "Failed to create SHM buffer for Cursor Bitmap.";
wl_pointer_set_cursor(input_pointer_, serial, nullptr, 0, 0);
return;
}
buffer_.reset(buffer);
size_ = image_size;
}
wl::DrawBitmapToSHMB(size_, *shared_memory_, image);
wl_pointer_set_cursor(input_pointer_, serial, pointer_surface_.get(),
location.x(), location.y());
wl_surface_attach(pointer_surface_.get(), buffer_.get(), 0, 0);
wl_surface_damage(pointer_surface_.get(), 0, 0, size_.width(),
size_.height());
wl_surface_commit(pointer_surface_.get());
}
void WaylandCursor::HideCursor(uint32_t serial) {
size_ = gfx::Size();
wl_pointer_set_cursor(input_pointer_, serial, nullptr, 0, 0);
buffer_.reset();
if (shared_memory_->handle().GetHandle()) {
shared_memory_->Unmap();
shared_memory_->Close();
}
}
} // namespace ui