Commit 2b7551c5 authored by Antonio Gomes's avatar Antonio Gomes Committed by Commit Bot

[ozone/wayand] Implement cursor support

CL makes use of the existing BitmapCursorFactoryOzone implementation
to add pointer/mouse cursor support to Ozone/Wayland.

Implementation of wayland_cursor.cc|h is originally based on [1].

[1] https://github.com/01org/ozone-wayland/

TEST=chrome --mash/mus --ozone-platform=wayland

BUG=578890

Change-Id: Iccd0a23dd1329bfe32ac78af9379ba3fd739d63f
Reviewed-on: https://chromium-review.googlesource.com/644946
Commit-Queue: Antonio Gomes <tonikitoo@igalia.com>
Reviewed-by: default avatarMichael Spang <spang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#515990}
parent 6dd09a38
...@@ -20,6 +20,8 @@ source_set("wayland") { ...@@ -20,6 +20,8 @@ source_set("wayland") {
"ozone_platform_wayland.h", "ozone_platform_wayland.h",
"wayland_connection.cc", "wayland_connection.cc",
"wayland_connection.h", "wayland_connection.h",
"wayland_cursor.cc",
"wayland_cursor.h",
"wayland_keyboard.cc", "wayland_keyboard.cc",
"wayland_keyboard.h", "wayland_keyboard.h",
"wayland_object.cc", "wayland_object.cc",
...@@ -53,6 +55,7 @@ source_set("wayland") { ...@@ -53,6 +55,7 @@ source_set("wayland") {
"//skia", "//skia",
"//third_party/wayland:wayland_client", "//third_party/wayland:wayland_client",
"//third_party/wayland-protocols:xdg_shell_protocol", "//third_party/wayland-protocols:xdg_shell_protocol",
"//ui/base",
"//ui/base:ui_features", "//ui/base:ui_features",
"//ui/display/manager", "//ui/display/manager",
"//ui/events", "//ui/events",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ui/ozone/platform/wayland/ozone_platform_wayland.h" #include "ui/ozone/platform/wayland/ozone_platform_wayland.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/ui_features.h" #include "ui/base/ui_features.h"
#include "ui/display/manager/fake_display_delegate.h" #include "ui/display/manager/fake_display_delegate.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
...@@ -13,7 +14,6 @@ ...@@ -13,7 +14,6 @@
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_surface_factory.h" #include "ui/ozone/platform/wayland/wayland_surface_factory.h"
#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/public/cursor_factory_ozone.h"
#include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/input_controller.h"
#include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/ozone_platform.h"
...@@ -88,7 +88,7 @@ class OzonePlatformWayland : public OzonePlatform { ...@@ -88,7 +88,7 @@ class OzonePlatformWayland : public OzonePlatform {
std::make_unique<StubKeyboardLayoutEngine>()); std::make_unique<StubKeyboardLayoutEngine>());
#endif #endif
cursor_factory_.reset(new CursorFactoryOzone); cursor_factory_.reset(new BitmapCursorFactoryOzone);
overlay_manager_.reset(new StubOverlayManager); overlay_manager_.reset(new StubOverlayManager);
input_controller_ = CreateStubInputController(); input_controller_ = CreateStubInputController();
surface_factory_.reset(new WaylandSurfaceFactory(connection_.get())); surface_factory_.reset(new WaylandSurfaceFactory(connection_.get()));
...@@ -114,7 +114,7 @@ class OzonePlatformWayland : public OzonePlatform { ...@@ -114,7 +114,7 @@ class OzonePlatformWayland : public OzonePlatform {
private: private:
std::unique_ptr<WaylandConnection> connection_; std::unique_ptr<WaylandConnection> connection_;
std::unique_ptr<WaylandSurfaceFactory> surface_factory_; std::unique_ptr<WaylandSurfaceFactory> surface_factory_;
std::unique_ptr<CursorFactoryOzone> cursor_factory_; std::unique_ptr<BitmapCursorFactoryOzone> cursor_factory_;
std::unique_ptr<StubOverlayManager> overlay_manager_; std::unique_ptr<StubOverlayManager> overlay_manager_;
std::unique_ptr<InputController> input_controller_; std::unique_ptr<InputController> input_controller_;
std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
......
...@@ -116,6 +116,13 @@ WaylandOutput* WaylandConnection::PrimaryOutput() const { ...@@ -116,6 +116,13 @@ WaylandOutput* WaylandConnection::PrimaryOutput() const {
return output_list_.front().get(); return output_list_.front().get();
} }
void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location) {
if (!pointer_ || !pointer_->cursor())
return;
pointer_->cursor()->UpdateBitmap(bitmaps, location, serial_);
}
void WaylandConnection::OnDispatcherListChanged() { void WaylandConnection::OnDispatcherListChanged() {
StartProcessingEvents(); StartProcessingEvents();
} }
...@@ -239,6 +246,7 @@ void WaylandConnection::Capabilities(void* data, ...@@ -239,6 +246,7 @@ void WaylandConnection::Capabilities(void* data,
connection->pointer_ = std::make_unique<WaylandPointer>( connection->pointer_ = std::make_unique<WaylandPointer>(
pointer, base::Bind(&WaylandConnection::DispatchUiEvent, pointer, base::Bind(&WaylandConnection::DispatchUiEvent,
base::Unretained(connection))); base::Unretained(connection)));
connection->pointer_->set_connection(connection);
} }
} else if (connection->pointer_) { } else if (connection->pointer_) {
connection->pointer_.reset(); connection->pointer_.reset();
...@@ -253,6 +261,7 @@ void WaylandConnection::Capabilities(void* data, ...@@ -253,6 +261,7 @@ void WaylandConnection::Capabilities(void* data,
connection->keyboard_ = std::make_unique<WaylandKeyboard>( connection->keyboard_ = std::make_unique<WaylandKeyboard>(
keyboard, base::Bind(&WaylandConnection::DispatchUiEvent, keyboard, base::Bind(&WaylandConnection::DispatchUiEvent,
base::Unretained(connection))); base::Unretained(connection)));
connection->keyboard_->set_connection(connection);
} }
} else if (connection->keyboard_) { } else if (connection->keyboard_) {
connection->keyboard_.reset(); connection->keyboard_.reset();
......
...@@ -44,6 +44,12 @@ class WaylandConnection : public PlatformEventSource, ...@@ -44,6 +44,12 @@ class WaylandConnection : public PlatformEventSource,
const std::vector<std::unique_ptr<WaylandOutput>>& GetOutputList() const; const std::vector<std::unique_ptr<WaylandOutput>>& GetOutputList() const;
WaylandOutput* PrimaryOutput() const; WaylandOutput* PrimaryOutput() const;
void set_serial(uint32_t serial) { serial_ = serial; }
uint32_t serial() { return serial_; }
void SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location);
private: private:
void Flush(); void Flush();
void DispatchUiEvent(Event* event); void DispatchUiEvent(Event* event);
...@@ -90,6 +96,8 @@ class WaylandConnection : public PlatformEventSource, ...@@ -90,6 +96,8 @@ class WaylandConnection : public PlatformEventSource,
bool watching_ = false; bool watching_ = false;
base::MessagePumpLibevent::FileDescriptorWatcher controller_; base::MessagePumpLibevent::FileDescriptorWatcher controller_;
uint32_t serial_ = 0;
std::vector<std::unique_ptr<WaylandOutput>> output_list_; std::vector<std::unique_ptr<WaylandOutput>> output_list_;
DISALLOW_COPY_AND_ASSIGN(WaylandConnection); DISALLOW_COPY_AND_ASSIGN(WaylandConnection);
......
// 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.cc"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_pointer.h"
namespace ui {
namespace {
const uint32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
const SkColorType kColorType = kBGRA_8888_SkColorType;
} // namespace
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;
}
if (!CreateSHMBuffer(gfx::SkISizeToSize(size))) {
LOG(ERROR) << "Failed to create SHM buffer for Cursor Bitmap.";
wl_pointer_set_cursor(input_pointer_, serial, nullptr, 0, 0);
return;
}
// The |bitmap| contains ARGB image, so update our wl_buffer, which is
// backed by a SkSurface.
SkRect damage;
image.getBounds(&damage);
// Clear to transparent in case |image| is smaller than the canvas.
SkCanvas* canvas = sk_surface_->getCanvas();
canvas->clear(SK_ColorTRANSPARENT);
canvas->drawBitmapRect(image, damage, nullptr);
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());
}
bool WaylandCursor::CreateSHMBuffer(const gfx::Size& size) {
if (size == size_)
return true;
size_ = size;
SkImageInfo info = SkImageInfo::MakeN32Premul(size_.width(), size_.height());
int stride = info.minRowBytes();
size_t image_buffer_size = info.computeByteSize(stride);
if (image_buffer_size == SK_MaxSizeT)
return false;
if (shared_memory_->handle().GetHandle()) {
shared_memory_->Unmap();
shared_memory_->Close();
}
if (!shared_memory_->CreateAndMapAnonymous(image_buffer_size)) {
LOG(ERROR) << "Create and mmap failed.";
return false;
}
// TODO(tonikitoo): Use SharedMemory::requested_size instead of
// 'image_buffer_size'?
wl::Object<wl_shm_pool> pool;
pool.reset(wl_shm_create_pool(shm_, shared_memory_->handle().GetHandle(),
image_buffer_size));
buffer_.reset(wl_shm_pool_create_buffer(pool.get(), 0, size_.width(),
size_.height(), stride, kShmFormat));
sk_surface_ = SkSurface::MakeRasterDirect(
SkImageInfo::Make(size_.width(), size_.height(), kColorType,
kOpaque_SkAlphaType),
static_cast<uint8_t*>(shared_memory_->memory()), stride);
return true;
}
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
// 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.
#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_CURSOR_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_CURSOR_H_
#include <wayland-client.h>
#include <vector>
#include "base/macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
namespace base {
class SharedMemory;
}
namespace gfx {
class Point;
}
namespace ui {
class WaylandConnection;
// The WaylandCursor class wraps the actual visual representation
// (what users see drawn) of a wl_pointer.
//
// 'pointer' is the Wayland terminology for mouse/mice.
class WaylandCursor {
public:
WaylandCursor();
~WaylandCursor();
void Init(wl_pointer* pointer, WaylandConnection* connection);
// Updates wl_pointer's visual representation with the given bitmap
// image set, at the hotspot specified by 'location'.
void UpdateBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location,
uint32_t serial);
private:
bool CreateSHMBuffer(const gfx::Size& size);
void HideCursor(uint32_t serial);
wl_shm* shm_ = nullptr; // Owned by WaylandConnection.
wl_pointer* input_pointer_ = nullptr; // Owned by WaylandPointer.
wl::Object<wl_buffer> buffer_;
wl::Object<wl_surface> pointer_surface_;
std::unique_ptr<base::SharedMemory> shared_memory_;
sk_sp<SkSurface> sk_surface_;
gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(WaylandCursor);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_CURSOR_H_
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/ozone/layout/keyboard_layout_engine.h" #include "ui/events/ozone/layout/keyboard_layout_engine.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/platform/wayland/wayland_window.h"
#if BUILDFLAG(USE_XKBCOMMON) #if BUILDFLAG(USE_XKBCOMMON)
...@@ -87,6 +88,7 @@ void WaylandKeyboard::Key(void* data, ...@@ -87,6 +88,7 @@ void WaylandKeyboard::Key(void* data,
uint32_t key, uint32_t key,
uint32_t state) { uint32_t state) {
WaylandKeyboard* keyboard = static_cast<WaylandKeyboard*>(data); WaylandKeyboard* keyboard = static_cast<WaylandKeyboard*>(data);
keyboard->connection_->set_serial(serial);
DomCode dom_code = DomCode dom_code =
KeycodeConverter::NativeKeycodeToDomCode(key + kXkbKeycodeOffset); KeycodeConverter::NativeKeycodeToDomCode(key + kXkbKeycodeOffset);
......
...@@ -10,11 +10,17 @@ ...@@ -10,11 +10,17 @@
namespace ui { namespace ui {
class WaylandConnection;
class WaylandKeyboard { class WaylandKeyboard {
public: public:
WaylandKeyboard(wl_keyboard* keyboard, const EventDispatchCallback& callback); WaylandKeyboard(wl_keyboard* keyboard, const EventDispatchCallback& callback);
virtual ~WaylandKeyboard(); virtual ~WaylandKeyboard();
void set_connection(WaylandConnection* connection) {
connection_ = connection;
}
private: private:
// wl_keyboard_listener // wl_keyboard_listener
static void Keymap(void* data, static void Keymap(void* data,
...@@ -49,6 +55,7 @@ class WaylandKeyboard { ...@@ -49,6 +55,7 @@ class WaylandKeyboard {
int32_t rate, int32_t rate,
int32_t delay); int32_t delay);
WaylandConnection* connection_ = nullptr;
wl::Object<wl_keyboard> obj_; wl::Object<wl_keyboard> obj_;
EventDispatchCallback callback_; EventDispatchCallback callback_;
uint8_t modifiers_ = 0; uint8_t modifiers_ = 0;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <wayland-client.h> #include <wayland-client.h>
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/platform/wayland/wayland_window.h"
// TODO(forney): Handle version 5 of wl_pointer. // TODO(forney): Handle version 5 of wl_pointer.
...@@ -23,6 +24,8 @@ WaylandPointer::WaylandPointer(wl_pointer* pointer, ...@@ -23,6 +24,8 @@ WaylandPointer::WaylandPointer(wl_pointer* pointer,
}; };
wl_pointer_add_listener(obj_.get(), &listener, this); wl_pointer_add_listener(obj_.get(), &listener, this);
cursor_.reset(new WaylandCursor);
} }
WaylandPointer::~WaylandPointer() {} WaylandPointer::~WaylandPointer() {}
...@@ -100,6 +103,7 @@ void WaylandPointer::Button(void* data, ...@@ -100,6 +103,7 @@ void WaylandPointer::Button(void* data,
if (state == WL_POINTER_BUTTON_STATE_PRESSED) { if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
type = ET_MOUSE_PRESSED; type = ET_MOUSE_PRESSED;
pointer->flags_ |= flag; pointer->flags_ |= flag;
pointer->connection_->set_serial(serial);
} else { } else {
type = ET_MOUSE_RELEASED; type = ET_MOUSE_RELEASED;
pointer->flags_ &= ~flag; pointer->flags_ &= ~flag;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ui/events/ozone/evdev/event_dispatch_callback.h" #include "ui/events/ozone/evdev/event_dispatch_callback.h"
#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/point_f.h"
#include "ui/ozone/platform/wayland/wayland_cursor.h"
#include "ui/ozone/platform/wayland/wayland_object.h" #include "ui/ozone/platform/wayland/wayland_object.h"
namespace ui { namespace ui {
...@@ -16,6 +17,13 @@ class WaylandPointer { ...@@ -16,6 +17,13 @@ class WaylandPointer {
WaylandPointer(wl_pointer* pointer, const EventDispatchCallback& callback); WaylandPointer(wl_pointer* pointer, const EventDispatchCallback& callback);
virtual ~WaylandPointer(); virtual ~WaylandPointer();
void set_connection(WaylandConnection* connection) {
connection_ = connection;
cursor_->Init(obj_.get(), connection_);
}
WaylandCursor* cursor() { return cursor_.get(); }
private: private:
// wl_pointer_listener // wl_pointer_listener
static void Enter(void* data, static void Enter(void* data,
...@@ -45,6 +53,8 @@ class WaylandPointer { ...@@ -45,6 +53,8 @@ class WaylandPointer {
uint32_t axis, uint32_t axis,
wl_fixed_t value); wl_fixed_t value);
WaylandConnection* connection_ = nullptr;
std::unique_ptr<WaylandCursor> cursor_;
wl::Object<wl_pointer> obj_; wl::Object<wl_pointer> obj_;
EventDispatchCallback callback_; EventDispatchCallback callback_;
gfx::PointF location_; gfx::PointF location_;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/ozone/events_ozone.h" #include "ui/events/ozone/events_ozone.h"
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
...@@ -163,7 +164,18 @@ void WaylandWindow::Restore() { ...@@ -163,7 +164,18 @@ void WaylandWindow::Restore() {
} }
void WaylandWindow::SetCursor(PlatformCursor cursor) { void WaylandWindow::SetCursor(PlatformCursor cursor) {
NOTIMPLEMENTED(); scoped_refptr<BitmapCursorOzone> bitmap =
BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
if (bitmap_ == bitmap)
return;
bitmap_ = bitmap;
if (bitmap_) {
connection_->SetCursorBitmap(bitmap_->bitmaps(), bitmap_->hotspot());
} else {
connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point());
}
} }
void WaylandWindow::MoveCursorTo(const gfx::Point& location) { void WaylandWindow::MoveCursorTo(const gfx::Point& location) {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_ #ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_ #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
#include "base/memory/ref_counted.h"
#include "ui/events/platform/platform_event_dispatcher.h" #include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -13,6 +14,7 @@ ...@@ -13,6 +14,7 @@
namespace ui { namespace ui {
class BitmapCursorOzone;
class PlatformWindowDelegate; class PlatformWindowDelegate;
class WaylandConnection; class WaylandConnection;
class XDGSurfaceWrapper; class XDGSurfaceWrapper;
...@@ -87,6 +89,9 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { ...@@ -87,6 +89,9 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
// know anything about the version. // know anything about the version.
std::unique_ptr<XDGSurfaceWrapper> xdg_surface_; std::unique_ptr<XDGSurfaceWrapper> xdg_surface_;
// The current cursor bitmap (immutable).
scoped_refptr<BitmapCursorOzone> bitmap_;
gfx::Rect bounds_; gfx::Rect bounds_;
gfx::Rect pending_bounds_; gfx::Rect pending_bounds_;
bool has_pointer_focus_ = false; bool has_pointer_focus_ = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment