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(
if (GetInputMethod())
GetInputMethod()->OnCaretBoundsChanged(this);
#if defined(USE_X11)
#if defined(USE_X11) || (defined(USE_OZONE) && !defined(OS_CHROMEOS))
const TextInputManager::TextSelection* selection =
GetTextInputManager()->GetTextSelection(focused_view);
if (selection->selected_text().length()) {
......@@ -2532,7 +2532,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged(
ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection);
clipboard_writer.WriteText(selection->selected_text());
}
#endif // defined(USE_X11)
#endif // defined(USE_X11) || (defined(USE_OZONE) && !defined(OS_CHROMEOS))
}
void RenderWidgetHostViewAura::SetPopupChild(
......
This diff is collapsed.
......@@ -100,6 +100,7 @@ jumbo_component("ozone_base") {
"//gpu/vulkan:buildflags",
"//ipc",
"//skia",
"//ui/base/clipboard:clipboard_types",
"//ui/display",
"//ui/display/types",
"//ui/display/util",
......
......@@ -8,6 +8,7 @@ include_rules = [
"-ui/base/ime/init",
"+ui/display",
"+ui/events",
"+ui/base/clipboard/clipboard_buffer.h",
"+ui/base/cursor",
"+ui/gfx",
"+ui/gl",
......
......@@ -19,8 +19,15 @@ WaylandClipboard::WaylandClipboard(
WaylandClipboard::~WaylandClipboard() = default;
void WaylandClipboard::OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) {
// TODO(https://crbug.com/921950): Implement primary selection.
if (buffer != ClipboardBuffer::kCopyPaste) {
std::move(callback).Run();
return;
}
if (!clipboard_data_source_) {
clipboard_data_source_ = data_device_manager_->CreateSource();
clipboard_data_source_->WriteToClipboard(data_map);
......@@ -30,9 +37,16 @@ void WaylandClipboard::OfferClipboardData(
}
void WaylandClipboard::RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type,
PlatformClipboard::DataMap* data_map,
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);
DCHECK(data_map);
......@@ -41,7 +55,11 @@ void WaylandClipboard::RequestClipboardData(
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_;
}
......@@ -53,7 +71,14 @@ void WaylandClipboard::SetSequenceNumberUpdateCb(
}
void WaylandClipboard::GetAvailableMimeTypes(
ClipboardBuffer buffer,
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());
}
......@@ -79,9 +104,13 @@ void WaylandClipboard::SetData(const std::string& contents,
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())
update_sequence_cb_.Run();
update_sequence_cb_.Run(buffer);
}
} // namespace ui
......@@ -26,21 +26,24 @@ class WaylandClipboard : public PlatformClipboard {
// PlatformClipboard.
void OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) override;
void RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type,
PlatformClipboard::DataMap* data_map,
PlatformClipboard::RequestDataClosure callback) override;
void GetAvailableMimeTypes(
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner() override;
bool IsSelectionOwner(ClipboardBuffer buffer) override;
void SetSequenceNumberUpdateCb(
PlatformClipboard::SequenceNumberUpdateCb cb) override;
void DataSourceCancelled();
void SetData(const std::string& contents, const std::string& mime_type);
void UpdateSequenceNumber();
void UpdateSequenceNumber(ClipboardBuffer buffer);
private:
// Holds a temporary instance of the client's clipboard content
......
......@@ -210,7 +210,8 @@ void WaylandDataDevice::OnDataOffer(void* data,
wl_data_offer* offer) {
auto* self = static_cast<WaylandDataDevice*>(data);
self->connection_->clipboard()->UpdateSequenceNumber();
self->connection_->clipboard()->UpdateSequenceNumber(
ClipboardBuffer::kCopyPaste);
DCHECK(!self->new_offer_);
self->new_offer_ = std::make_unique<WaylandDataOffer>(offer);
......
......@@ -51,16 +51,19 @@ class MockClipboardClient {
data_types_[mime_type] =
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,
PlatformClipboard::RequestDataClosure callback) {
delegate_->RequestClipboardData(mime_type, &data_types_,
std::move(callback));
delegate_->RequestClipboardData(ClipboardBuffer::kCopyPaste, mime_type,
&data_types_, std::move(callback));
}
bool IsSelectionOwner() { return delegate_->IsSelectionOwner(); }
bool IsSelectionOwner() {
return delegate_->IsSelectionOwner(ClipboardBuffer::kCopyPaste);
}
private:
PlatformClipboard* delegate_ = nullptr;
......
......@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_types.h"
......@@ -31,70 +32,52 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// PlatformClipboard:
void OfferClipboardData(
ClipboardBuffer buffer,
const PlatformClipboard::DataMap& data_map,
PlatformClipboard::OfferDataClosure callback) override;
void RequestClipboardData(
ClipboardBuffer buffer,
const std::string& mime_type,
PlatformClipboard::DataMap* data_map,
PlatformClipboard::RequestDataClosure callback) override;
void GetAvailableMimeTypes(
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner() override;
bool IsSelectionOwner(ClipboardBuffer buffer) override;
void SetSequenceNumberUpdateCb(
PlatformClipboard::SequenceNumberUpdateCb cb) override;
private:
struct SelectionState;
// XEventDispatcher:
bool DispatchXEvent(XEvent* xev) override;
bool OnSelectionRequest(XEvent* xev);
bool OnSelectionNotify(XEvent* xev);
bool OnSelectionRequest(const XSelectionRequestEvent& event);
bool OnSelectionNotify(const XSelectionEvent& event);
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
// sending XConvertSelection with target=TARGETS. After sending this, we
// will receive a SelectionNotify event with xselection.target=TARGETS which
// is processed in |OnSelectionNotify|.
void QueryTargets();
void QueryTargets(XAtom selection);
// Reads the contents of the remote clipboard by sending XConvertSelection
// with target=<mime-type>. After sending this, we will receive a
// SelectionNotify event with xselection.target=<mime-type> which is processed
// in |OnSelectionNotify|.
void ReadRemoteClipboard();
// 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_;
void ReadRemoteClipboard(XAtom selection);
// Local cache of atoms.
const XAtom atom_clipboard_;
......@@ -110,8 +93,19 @@ class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
// Input-only window used as a selection owner.
const XID x_window_;
// The time that this instance took ownership of the clipboard.
Time acquired_selection_timestamp_;
// 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_;
// 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);
};
......
......@@ -12,13 +12,17 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/optional.h"
#include "ui/base/clipboard/clipboard_buffer.h"
namespace ui {
// PlatformClipboard is an interface that allows Ozone backends to exchange
// data with other applications on the host system. The most familiar use for
// it is handling copy and paste operations.
// Allows Chrome controls and windows to exchange data with each other and other
// applications, e.g., to copy and paste.
//
// 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 {
public:
virtual ~PlatformClipboard() {}
......@@ -30,7 +34,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// SequenceNumberUpdateCb is a repeating callback, which can be used to tell
// 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.
//
......@@ -47,7 +52,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// OfferDataClosure should be invoked when the host clipboard implementation
// acknowledges that the "offer to clipboard" operation is performed.
using OfferDataClosure = base::OnceCallback<void()>;
virtual void OfferClipboardData(const DataMap& data_map,
virtual void OfferClipboardData(ClipboardBuffer buffer,
const DataMap& data_map,
OfferDataClosure callback) = 0;
// Reads data from host system clipboard given mime type. The data is
......@@ -57,7 +63,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// data has been read and stored into 'data_map'.
using RequestDataClosure =
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,
RequestDataClosure callback) = 0;
......@@ -68,7 +75,8 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// operations are known.
using GetMimeTypesClosure =
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
// data is this one; false otherwise.
......@@ -76,7 +84,7 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// 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
// 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.
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