Commit 60d58405 authored by Alexander Dunaev's avatar Alexander Dunaev Committed by Commit Bot

[ozone/x11] Implemented support for multiple selection buffers.

The base Clipboard interface supports different types of clipboards, such as
primary selection on X11 or drag on OS X.  Ozone didn't support this concept
at all, which made it impossible to use more than one clipboard.

This CL adds support of multiple clipboards at the Ozone level and implements
the selection clipboard for Ozone/X11.

R=dcheng@chromium.org, msisov@igalia.com, rjkroege@chromium.org

Bug: 973295
Change-Id: I05ed4aa93517d80e1c789a2a09d249a2b923546d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1781142Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Reviewed-by: default avatarMaksim Sisov <msisov@igalia.com>
Commit-Queue: Alexander Dunaev <adunaev@igalia.com>
Cr-Commit-Position: refs/heads/master@{#695913}
parent 05fbe65e
...@@ -2524,7 +2524,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged( ...@@ -2524,7 +2524,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged(
if (GetInputMethod()) if (GetInputMethod())
GetInputMethod()->OnCaretBoundsChanged(this); GetInputMethod()->OnCaretBoundsChanged(this);
#if defined(USE_X11) #if defined(USE_X11) || (defined(USE_OZONE) && !defined(OS_CHROMEOS))
const TextInputManager::TextSelection* selection = const TextInputManager::TextSelection* selection =
GetTextInputManager()->GetTextSelection(focused_view); GetTextInputManager()->GetTextSelection(focused_view);
if (selection->selected_text().length()) { if (selection->selected_text().length()) {
...@@ -2532,7 +2532,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged( ...@@ -2532,7 +2532,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged(
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection); ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection);
clipboard_writer.WriteText(selection->selected_text()); clipboard_writer.WriteText(selection->selected_text());
} }
#endif // defined(USE_X11) #endif // defined(USE_X11) || (defined(USE_OZONE) && !defined(OS_CHROMEOS))
} }
void RenderWidgetHostViewAura::SetPopupChild( void RenderWidgetHostViewAura::SetPopupChild(
......
This diff is collapsed.
...@@ -100,6 +100,7 @@ jumbo_component("ozone_base") { ...@@ -100,6 +100,7 @@ jumbo_component("ozone_base") {
"//gpu/vulkan:buildflags", "//gpu/vulkan:buildflags",
"//ipc", "//ipc",
"//skia", "//skia",
"//ui/base/clipboard:clipboard_types",
"//ui/display", "//ui/display",
"//ui/display/types", "//ui/display/types",
"//ui/display/util", "//ui/display/util",
......
...@@ -8,6 +8,7 @@ include_rules = [ ...@@ -8,6 +8,7 @@ include_rules = [
"-ui/base/ime/init", "-ui/base/ime/init",
"+ui/display", "+ui/display",
"+ui/events", "+ui/events",
"+ui/base/clipboard/clipboard_buffer.h",
"+ui/base/cursor", "+ui/base/cursor",
"+ui/gfx", "+ui/gfx",
"+ui/gl", "+ui/gl",
......
...@@ -19,8 +19,15 @@ WaylandClipboard::WaylandClipboard( ...@@ -19,8 +19,15 @@ WaylandClipboard::WaylandClipboard(
WaylandClipboard::~WaylandClipboard() = default; WaylandClipboard::~WaylandClipboard() = default;
void WaylandClipboard::OfferClipboardData( void WaylandClipboard::OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map, const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) { PlatformClipboard::OfferDataClosure callback) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste) {
std::move(callback).Run();
return;
}
if (!clipboard_data_source_) { if (!clipboard_data_source_) {
clipboard_data_source_ = data_device_manager_->CreateSource(); clipboard_data_source_ = data_device_manager_->CreateSource();
clipboard_data_source_->WriteToClipboard(data_map); clipboard_data_source_->WriteToClipboard(data_map);
...@@ -30,9 +37,16 @@ void WaylandClipboard::OfferClipboardData( ...@@ -30,9 +37,16 @@ void WaylandClipboard::OfferClipboardData(
} }
void WaylandClipboard::RequestClipboardData( void WaylandClipboard::RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type, const std::string& mime_type,
PlatformClipboard::DataMap* data_map, PlatformClipboard::DataMap* data_map,
PlatformClipboard::RequestDataClosure callback) { PlatformClipboard::RequestDataClosure callback) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste) {
std::move(callback).Run({});
return;
}
read_clipboard_closure_ = std::move(callback); read_clipboard_closure_ = std::move(callback);
DCHECK(data_map); DCHECK(data_map);
...@@ -41,7 +55,11 @@ void WaylandClipboard::RequestClipboardData( ...@@ -41,7 +55,11 @@ void WaylandClipboard::RequestClipboardData(
SetData({}, mime_type); SetData({}, mime_type);
} }
bool WaylandClipboard::IsSelectionOwner() { bool WaylandClipboard::IsSelectionOwner(ClipboardBuffer buffer) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste)
return false;
return !!clipboard_data_source_; return !!clipboard_data_source_;
} }
...@@ -53,7 +71,14 @@ void WaylandClipboard::SetSequenceNumberUpdateCb( ...@@ -53,7 +71,14 @@ void WaylandClipboard::SetSequenceNumberUpdateCb(
} }
void WaylandClipboard::GetAvailableMimeTypes( void WaylandClipboard::GetAvailableMimeTypes(
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) { PlatformClipboard::GetMimeTypesClosure callback) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste) {
std::move(callback).Run({});
return;
}
std::move(callback).Run(data_device_->GetAvailableMimeTypes()); std::move(callback).Run(data_device_->GetAvailableMimeTypes());
} }
...@@ -79,9 +104,13 @@ void WaylandClipboard::SetData(const std::string& contents, ...@@ -79,9 +104,13 @@ void WaylandClipboard::SetData(const std::string& contents,
data_map_ = nullptr; data_map_ = nullptr;
} }
void WaylandClipboard::UpdateSequenceNumber() { void WaylandClipboard::UpdateSequenceNumber(ClipboardBuffer buffer) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste)
return;
if (!update_sequence_cb_.is_null()) if (!update_sequence_cb_.is_null())
update_sequence_cb_.Run(); update_sequence_cb_.Run(buffer);
} }
} // namespace ui } // namespace ui
...@@ -26,21 +26,24 @@ class WaylandClipboard : public PlatformClipboard { ...@@ -26,21 +26,24 @@ class WaylandClipboard : public PlatformClipboard {
// PlatformClipboard. // PlatformClipboard.
void OfferClipboardData( void OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map, const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) override; PlatformClipboard::OfferDataClosure callback) override;
void RequestClipboardData( void RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type, const std::string& mime_type,
PlatformClipboard::DataMap* data_map, PlatformClipboard::DataMap* data_map,
PlatformClipboard::RequestDataClosure callback) override; PlatformClipboard::RequestDataClosure callback) override;
void GetAvailableMimeTypes( void GetAvailableMimeTypes(
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override; PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner() override; bool IsSelectionOwner(ClipboardBuffer buffer) override;
void SetSequenceNumberUpdateCb( void SetSequenceNumberUpdateCb(
PlatformClipboard::SequenceNumberUpdateCb cb) override; PlatformClipboard::SequenceNumberUpdateCb cb) override;
void DataSourceCancelled(); void DataSourceCancelled();
void SetData(const std::string& contents, const std::string& mime_type); void SetData(const std::string& contents, const std::string& mime_type);
void UpdateSequenceNumber(); void UpdateSequenceNumber(ClipboardBuffer buffer);
private: private:
// Holds a temporary instance of the client's clipboard content // Holds a temporary instance of the client's clipboard content
......
...@@ -210,7 +210,8 @@ void WaylandDataDevice::OnDataOffer(void* data, ...@@ -210,7 +210,8 @@ void WaylandDataDevice::OnDataOffer(void* data,
wl_data_offer* offer) { wl_data_offer* offer) {
auto* self = static_cast<WaylandDataDevice*>(data); auto* self = static_cast<WaylandDataDevice*>(data);
self->connection_->clipboard()->UpdateSequenceNumber(); self->connection_->clipboard()->UpdateSequenceNumber(
ClipboardBuffer::kCopyPaste);
DCHECK(!self->new_offer_); DCHECK(!self->new_offer_);
self->new_offer_ = std::make_unique<WaylandDataOffer>(offer); self->new_offer_ = std::make_unique<WaylandDataOffer>(offer);
......
...@@ -51,16 +51,19 @@ class MockClipboardClient { ...@@ -51,16 +51,19 @@ class MockClipboardClient {
data_types_[mime_type] = data_types_[mime_type] =
std::vector<uint8_t>(object_data, object_data + object_map.size()); std::vector<uint8_t>(object_data, object_data + object_map.size());
delegate_->OfferClipboardData(data_types_, std::move(callback)); delegate_->OfferClipboardData(ClipboardBuffer::kCopyPaste, data_types_,
std::move(callback));
} }
void ReadData(const std::string& mime_type, void ReadData(const std::string& mime_type,
PlatformClipboard::RequestDataClosure callback) { PlatformClipboard::RequestDataClosure callback) {
delegate_->RequestClipboardData(mime_type, &data_types_, delegate_->RequestClipboardData(ClipboardBuffer::kCopyPaste, mime_type,
std::move(callback)); &data_types_, std::move(callback));
} }
bool IsSelectionOwner() { return delegate_->IsSelectionOwner(); } bool IsSelectionOwner() {
return delegate_->IsSelectionOwner(ClipboardBuffer::kCopyPaste);
}
private: private:
PlatformClipboard* delegate_ = nullptr; PlatformClipboard* delegate_ = nullptr;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/containers/flat_map.h"
#include "ui/events/platform/x11/x11_event_source.h" #include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_types.h" #include "ui/gfx/x/x11_types.h"
...@@ -31,70 +32,52 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher { ...@@ -31,70 +32,52 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// PlatformClipboard: // PlatformClipboard:
void OfferClipboardData( void OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map, const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) override; PlatformClipboard::OfferDataClosure callback) override;
void RequestClipboardData( void RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type, const std::string& mime_type,
PlatformClipboard::DataMap* data_map, PlatformClipboard::DataMap* data_map,
PlatformClipboard::RequestDataClosure callback) override; PlatformClipboard::RequestDataClosure callback) override;
void GetAvailableMimeTypes( void GetAvailableMimeTypes(
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override; PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner() override; bool IsSelectionOwner(ClipboardBuffer buffer) override;
void SetSequenceNumberUpdateCb( void SetSequenceNumberUpdateCb(
PlatformClipboard::SequenceNumberUpdateCb cb) override; PlatformClipboard::SequenceNumberUpdateCb cb) override;
private: private:
struct SelectionState;
// XEventDispatcher: // XEventDispatcher:
bool DispatchXEvent(XEvent* xev) override; bool DispatchXEvent(XEvent* xev) override;
bool OnSelectionRequest(XEvent* xev); bool OnSelectionRequest(const XSelectionRequestEvent& event);
bool OnSelectionNotify(XEvent* xev); bool OnSelectionNotify(const XSelectionEvent& event);
bool OnSetSelectionOwnerNotify(XEvent* xev); bool OnSetSelectionOwnerNotify(XEvent* xev);
// Returns an X atom for a clipboard buffer type.
XAtom SelectionAtomForBuffer(ClipboardBuffer buffer) const;
// Returns a clipboard buffer type for an X atom for a selection name of the
// system clipboard buffer.
ClipboardBuffer BufferForSelectionAtom(XAtom selection) const;
// Returns the state for the given selection;
SelectionState& GetSelectionState(XAtom selection);
// Queries the current clipboard owner for what mime types are available by // Queries the current clipboard owner for what mime types are available by
// sending XConvertSelection with target=TARGETS. After sending this, we // sending XConvertSelection with target=TARGETS. After sending this, we
// will receive a SelectionNotify event with xselection.target=TARGETS which // will receive a SelectionNotify event with xselection.target=TARGETS which
// is processed in |OnSelectionNotify|. // is processed in |OnSelectionNotify|.
void QueryTargets(); void QueryTargets(XAtom selection);
// Reads the contents of the remote clipboard by sending XConvertSelection // Reads the contents of the remote clipboard by sending XConvertSelection
// with target=<mime-type>. After sending this, we will receive a // with target=<mime-type>. After sending this, we will receive a
// SelectionNotify event with xselection.target=<mime-type> which is processed // SelectionNotify event with xselection.target=<mime-type> which is processed
// in |OnSelectionNotify|. // in |OnSelectionNotify|.
void ReadRemoteClipboard(); void ReadRemoteClipboard(XAtom selection);
// Notifies whenever clipboard sequence number is changed.
PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
// DataMap we keep from |OfferClipboardData| to service remote requests for
// the clipboard.
PlatformClipboard::DataMap offer_data_map_;
// DataMap from |RequestClipboardData| that we write remote clipboard contents
// to before calling the completion callback.
PlatformClipboard::DataMap* request_data_map_ = nullptr;
// Mime types supported by remote clipboard.
std::vector<std::string> mime_types_;
// Data most recently read from remote clipboard.
std::vector<unsigned char> data_;
// Mime type of most recently read data from remote clipboard.
std::string data_mime_type_;
// If XFixes is unavailable, this clipboard window will not register to
// receive events and no processing will take place.
// TODO(joelhockey): Make clipboard work without xfixes.
bool using_xfixes_ = false;
// The event base returned by XFixesQueryExtension().
int xfixes_event_base_;
// Callbacks are stored when we haven't already prefetched the remote
// clipboard.
PlatformClipboard::GetMimeTypesClosure get_available_mime_types_callback_;
PlatformClipboard::RequestDataClosure request_clipboard_data_callback_;
// Local cache of atoms. // Local cache of atoms.
const XAtom atom_clipboard_; const XAtom atom_clipboard_;
...@@ -110,8 +93,19 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher { ...@@ -110,8 +93,19 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// Input-only window used as a selection owner. // Input-only window used as a selection owner.
const XID x_window_; const XID x_window_;
// The time that this instance took ownership of the clipboard. // If XFixes is unavailable, this clipboard window will not register to
Time acquired_selection_timestamp_; // receive events and no processing will take place.
// TODO(joelhockey): Make clipboard work without xfixes.
bool using_xfixes_ = false;
// The event base returned by XFixesQueryExtension().
int xfixes_event_base_;
// Notifies whenever clipboard sequence number is changed.
PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
// State of selections served by this instance.
base::flat_map<XAtom, std::unique_ptr<SelectionState>> selection_state_;
DISALLOW_COPY_AND_ASSIGN(X11ClipboardOzone); DISALLOW_COPY_AND_ASSIGN(X11ClipboardOzone);
}; };
......
...@@ -12,13 +12,17 @@ ...@@ -12,13 +12,17 @@
#include "base/component_export.h" #include "base/component_export.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "ui/base/clipboard/clipboard_buffer.h"
namespace ui { namespace ui {
// PlatformClipboard is an interface that allows Ozone backends to exchange // Allows Chrome controls and windows to exchange data with each other and other
// data with other applications on the host system. The most familiar use for // applications, e.g., to copy and paste.
// it is handling copy and paste operations.
// //
// In environments that have multiple clipboards (like Linux X11 or OS X, see
// ui::ClipboardBuffer), the implementation should provide a separate data
// buffer for each system clipboard. When data is requested or offered, the
// caller specifies which buffer to use by providing the |buffer| parameter.
class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
public: public:
virtual ~PlatformClipboard() {} virtual ~PlatformClipboard() {}
...@@ -30,7 +34,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { ...@@ -30,7 +34,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// SequenceNumberUpdateCb is a repeating callback, which can be used to tell // SequenceNumberUpdateCb is a repeating callback, which can be used to tell
// a client of the PlatformClipboard to increment clipboard's sequence number // a client of the PlatformClipboard to increment clipboard's sequence number
using SequenceNumberUpdateCb = base::RepeatingCallback<void()>; using SequenceNumberUpdateCb =
base::RepeatingCallback<void(ClipboardBuffer buffer)>;
// Offers a given clipboard data 'data_map' to the host system clipboard. // Offers a given clipboard data 'data_map' to the host system clipboard.
// //
...@@ -47,7 +52,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { ...@@ -47,7 +52,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// OfferDataClosure should be invoked when the host clipboard implementation // OfferDataClosure should be invoked when the host clipboard implementation
// acknowledges that the "offer to clipboard" operation is performed. // acknowledges that the "offer to clipboard" operation is performed.
using OfferDataClosure = base::OnceCallback<void()>; using OfferDataClosure = base::OnceCallback<void()>;
virtual void OfferClipboardData(const DataMap& data_map, virtual void OfferClipboardData(ClipboardBuffer buffer,
const DataMap& data_map,
OfferDataClosure callback) = 0; OfferDataClosure callback) = 0;
// Reads data from host system clipboard given mime type. The data is // Reads data from host system clipboard given mime type. The data is
...@@ -57,7 +63,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { ...@@ -57,7 +63,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// data has been read and stored into 'data_map'. // data has been read and stored into 'data_map'.
using RequestDataClosure = using RequestDataClosure =
base::OnceCallback<void(const base::Optional<std::vector<uint8_t>>&)>; base::OnceCallback<void(const base::Optional<std::vector<uint8_t>>&)>;
virtual void RequestClipboardData(const std::string& mime_type, virtual void RequestClipboardData(ClipboardBuffer buffer,
const std::string& mime_type,
DataMap* data_map, DataMap* data_map,
RequestDataClosure callback) = 0; RequestDataClosure callback) = 0;
...@@ -68,7 +75,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { ...@@ -68,7 +75,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// operations are known. // operations are known.
using GetMimeTypesClosure = using GetMimeTypesClosure =
base::OnceCallback<void(const std::vector<std::string>&)>; base::OnceCallback<void(const std::vector<std::string>&)>;
virtual void GetAvailableMimeTypes(GetMimeTypesClosure callback) = 0; virtual void GetAvailableMimeTypes(ClipboardBuffer buffer,
GetMimeTypesClosure callback) = 0;
// Returns true if the current application writing data to the host clipboard // Returns true if the current application writing data to the host clipboard
// data is this one; false otherwise. // data is this one; false otherwise.
...@@ -76,7 +84,7 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { ...@@ -76,7 +84,7 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// It can be relevant to know this information in case the client wants to // It can be relevant to know this information in case the client wants to
// caches the clipboard data, and wants to know if it is possible to use // caches the clipboard data, and wants to know if it is possible to use
// the cached data in order to reply faster to read-clipboard operations. // the cached data in order to reply faster to read-clipboard operations.
virtual bool IsSelectionOwner() = 0; virtual bool IsSelectionOwner(ClipboardBuffer buffer) = 0;
// See comment above SequenceNumberUpdateCb. Can be called once. // See comment above SequenceNumberUpdateCb. Can be called once.
virtual void SetSequenceNumberUpdateCb(SequenceNumberUpdateCb cb) = 0; virtual void SetSequenceNumberUpdateCb(SequenceNumberUpdateCb cb) = 0;
......
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