This patch migrates clipboard related patches from 94.
References:
https://review.tizen.org/gerrit/280878/
https://review.tizen.org/gerrit/280951/
https://review.tizen.org/gerrit/278392/
Change-Id: I1c6f744a642602fb49036b6391fe1d1f7ed62d51
Signed-off-by: Ayush Kumar <ayush.k123@samsung.com>
int password_input_minlength,
int input_maxlength
#endif
+#if BUILDFLAG(IS_EFL)
+ ,
+ bool is_content_editable
+#endif
) {
// The last gesture most likely caused the focus change. The focus reason will
// be incorrect if the focus was triggered without a user gesture.
input_method->CancelComposition(this);
has_composition_text_ = false;
-#if BUILDFLAG(IS_TIZEN_TV)
+#if defined(USE_EFL)
if (offscreen_helper_) {
- offscreen_helper_->FocusedNodeChanged(editable, is_radio_or_checkbox,
- password_input_minlength,
- input_maxlength);
+ offscreen_helper_->FocusedNodeChanged(
+ editable
+#if BUILDFLAG(IS_TIZEN_TV)
+ ,
+ is_radio_or_checkbox, password_input_minlength, input_maxlength
+#endif
+ ,
+ is_content_editable);
}
#endif
int password_input_minlength,
int input_maxlength
#endif
+#if defined(USE_EFL)
+ ,
+ bool is_content_editable
+#endif
) override;
void OnSynchronizedDisplayPropertiesChanged(bool rotation = false) override;
int password_input_minlength,
int input_maxlength
#endif
+#if BUILDFLAG(IS_EFL)
+ ,
+ bool is_content_editable
+#endif
) {
}
params->is_radio_or_checkbox_input_node, params->password_input_minlength,
params->input_maxlength
#endif
+#if BUILDFLAG(IS_EFL)
+ ,
+ params->is_content_editable
+#endif
);
FocusedNodeDetails details = {frame->has_focused_editable_element(),
struct FocusedNodeChangedParams {
bool is_radio_or_checkbox_input_node;
int32 password_input_minlength;
+ bool is_content_editable;
int32 input_maxlength;
};
mojom::blink::FocusType::kNone, nullptr));
}
+#if BUILDFLAG(IS_EFL)
+static bool IsContentEditable(Element* element) {
+ element->GetDocument().UpdateStyleAndLayoutTree();
+ return IsEditable(*element);
+}
+#endif
+
void Document::SendFocusNotification(Element* new_focused_element,
mojom::blink::FocusType focus_type) {
if (!GetPage())
params->input_maxlength = InputElementMaxLength(new_focused_element);
}
#endif
+#if BUILDFLAG(IS_EFL)
+ if (new_focused_element)
+ params->is_content_editable = IsContentEditable(new_focused_element);
+#endif
GetFrame()->GetLocalFrameHostRemote().FocusedElementChanged(
is_editable, element_bounds_in_dips, focus_type, std::move(params));
}
void FakeLocalFrameHost::FocusedElementChanged(
bool is_editable_element,
const gfx::Rect& bounds_in_frame_widget,
- blink::mojom::FocusType focus_type) {}
+ blink::mojom::FocusType focus_type,
+ mojom::blink::FocusedNodeChangedParamsPtr params) {}
-void FakeLocalFrameHost::TextSelectionChanged(const WTF::String& text,
- uint32_t offset,
- const gfx::Range& range) {}
void FakeLocalFrameHost::ShowPopupMenu(
mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client,
const gfx::Rect& bounds,
void UpdateFaviconURL(
WTF::Vector<blink::mojom::blink::FaviconURLPtr> favicon_urls) override;
void DownloadURL(mojom::blink::DownloadURLParamsPtr params) override;
- void FocusedElementChanged(bool is_editable_element,
- const gfx::Rect& bounds_in_frame_widget,
- blink::mojom::FocusType focus_type) override;
+ void FocusedElementChanged(
+ bool is_editable_element,
+ const gfx::Rect& bounds_in_frame_widget,
+ blink::mojom::FocusType focus_type,
+ mojom::blink::FocusedNodeChangedParamsPtr params) override;
void TextSelectionChanged(const WTF::String& text,
uint32_t offset,
const gfx::Range& range) override;
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
+#include "ui/base/clipboard/clipboard_helper_efl.h"
#include "ui/display/screen.h"
#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/geometry/dip_util.h"
int password_input_minlength,
int input_maxlength
#endif
-) {
+ ,
+ bool is_content_editable) {
+ is_content_editable_ = is_content_editable;
+#if defined(USE_WAYLAND)
+ ClipboardHelperEfl::GetInstance()->SetContentEditable(is_content_editable);
+#endif
#if BUILDFLAG(IS_TIZEN_TV)
radio_or_checkbox_focused_ = is_radio_or_checkbox;
int password_input_minlength,
int input_maxlength
#endif
- );
+ ,
+ bool is_content_editable);
// |snapshot_area| is relative coordinate system based on Webview.
// (0,0) is top left corner.
void SetFocusInOutCallbacks(const OnFocusCallback& on_focus_in,
const OnFocusCallback& on_focus_out);
+ bool IsFocusedNodeContentEditable() const { return is_content_editable_; }
+
private:
static void OnParentViewResize(void* data, Evas*, Evas_Object*, void*);
static void EvasObjectImagePixelsGetCallback(void*, Evas_Object*);
OnFocusCallback on_focus_in_callback_;
OnFocusCallback on_focus_out_callback_;
+
+ bool is_content_editable_ = false;
};
} // namespace content
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "ui/base/clipboard/clipboard_helper_efl.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
return false;
}
- if (selection_on_empty_form_control_) {
+ if (selection_on_empty_form_control_ &&
+ (!ClipboardHelperEfl::GetInstance()->CanPasteFromSystemClipboard() ||
+ selection_change_reason_ == Reason::Tap)) {
ClearSelection();
return false;
}
#if !defined(USE_AURA)
RenderWidgetHostViewEfl* rwhv =
static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
- if (params.selection_text.empty() && !(rwhv && !rwhv->IsLastAvailableTextEmpty())) {
+ if (params.selection_text.empty() &&
+ !(rwhv && !rwhv->IsLastAvailableTextEmpty()) &&
+ !ClipboardHelperEfl::GetInstance()->CanPasteFromSystemClipboard()) {
long_mouse_press_ = false;
return false;
}
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_helper_efl.h"
#include "ui/gfx/geometry/size.h"
namespace ui {
namespace {
-const char kPlainTextFormat[] = "text";
-const char kHTMLFormat[] = "html";
+const char kPlainTextFormat[] = "text/plain";
+const char kHTMLFormat[] = "text/html";
const char kRTFFormat[] = "rtf";
const char kBitmapFormat[] = "bitmap";
const char kWebKitSmartPasteFormat[] = "webkit_smart";
const char kMimeTypeWebCustomData[] = "chromium/x-web-custom-data";
} // namespace
-// Clipboard factory method.
-Clipboard* Clipboard::Create() {
- return new ClipboardEfl;
-}
-
-ClipboardEfl::FormatType::FormatType() {
-}
-
-Clipboard::FormatType::FormatType(const std::string& native_format)
- : data_(native_format) {
-}
-
-Clipboard::FormatType::~FormatType() {
-}
-
-std::string Clipboard::FormatType::Serialize() const {
- return data_;
-}
-
-// static
-Clipboard::FormatType Clipboard::FormatType::Deserialize(
- const std::string& serialization) {
- return FormatType(serialization);
-}
-
-bool Clipboard::FormatType::Equals(const FormatType& other) const {
- return data_ == other.data_;
-}
-
ClipboardEfl::ClipboardEfl() {
DCHECK(CalledOnValidThread());
}
DCHECK(CalledOnValidThread());
}
-// Main entry point used to write several values in the clipboard.
-void ClipboardEfl::WriteObjects(ClipboardType type, const ObjectMap& objects) {
+void ClipboardEfl::WritePortableAndPlatformRepresentations(
+ ClipboardBuffer buffer,
+ const ObjectMap& objects,
+ std::vector<Clipboard::PlatformRepresentation> platform_representations,
+ std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
+ DCHECK(IsSupportedClipboardBuffer(buffer));
- for (ObjectMap::const_iterator iter = objects.begin();
- iter != objects.end(); ++iter) {
- DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
- }
+ DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
}
void ClipboardEfl::OnPreShutdown() {}
-uint64_t ClipboardEfl::GetSequenceNumber(ClipboardType /* type */) const {
+DataTransferEndpoint* ClipboardEfl::GetSource(ClipboardBuffer buffer) const {
+ return NULL;
+}
+
+const ClipboardSequenceNumberToken& ClipboardEfl::GetSequenceNumber(
+ ClipboardBuffer /* type */) const {
DCHECK(CalledOnValidThread());
// TODO: implement this. For now this interface will advertise
// that the clipboard never changes. That's fine as long as we
// don't rely on this signal.
- return 0;
+ return ui::ClipboardSequenceNumberToken();
}
-bool ClipboardEfl::IsFormatAvailable(const Clipboard::FormatType& format,
- ClipboardType /* clipboard_type */) const {
+bool ClipboardEfl::IsFormatAvailable(
+ const ClipboardFormatType& format,
+ ClipboardBuffer /* clipboard_type */,
+ const DataTransferEndpoint* data_dst) const {
DCHECK(CalledOnValidThread());
- int count = ClipboardHelperEfl::GetInstance()->NumberOfItems();
-
- int type = ELM_SEL_FORMAT_NONE;
- std::string clipboard_data;
-
- for (int i = 0; i < count; i++) {
- bool ret = ClipboardHelperEfl::GetInstance()->RetrieveClipboardItem(i, &type, &clipboard_data);
- if (!ret)
- continue;
-
- switch (type) {
- case ELM_SEL_FORMAT_TEXT: {
- if (GetPlainTextFormatType().Equals(format))
- return true;
- break;
- }
- case ELM_SEL_FORMAT_HTML: {
- if (GetHtmlFormatType().Equals(format))
- return true;
- break;
- }
- case ELM_SEL_FORMAT_IMAGE: {
- if (GetBitmapFormatType().Equals(format))
- return true;
- break;
- }
- // If we support more ELM formats, we shall add it here.
- }
- }
- return false;
+ return ClipboardHelperEfl::GetInstance()->IsFormatAvailable(format);
}
-void ClipboardEfl::Clear(ClipboardType /* type */) {
+void ClipboardEfl::Clear(ClipboardBuffer /* type */) {
ClipboardHelperEfl::GetInstance()->Clear();
}
-void ClipboardEfl::ReadAvailableTypes(ClipboardType type, std::vector<string16>* types,
- bool* contains_filenames) const {
+void ClipboardEfl::ReadAvailableTypes(
+ ClipboardBuffer type,
+ const DataTransferEndpoint* data_dst,
+ std::vector<std::u16string>* types) const {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
+ DCHECK_EQ(type, ClipboardBuffer::kCopyPaste);
- if (!types || !contains_filenames) {
+ if (!types) {
NOTREACHED();
return;
}
types->clear();
- *contains_filenames = false;
- if (IsFormatAvailable(GetPlainTextFormatType(), type))
- types->push_back(base::UTF8ToUTF16(GetPlainTextFormatType().ToString()));
- if (IsFormatAvailable(GetHtmlFormatType(), type))
- types->push_back(base::UTF8ToUTF16(GetHtmlFormatType().ToString()));
- if (IsFormatAvailable(GetBitmapFormatType(), type))
- types->push_back(base::UTF8ToUTF16(GetBitmapFormatType().ToString()));
+ if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), type, data_dst))
+ types->push_back(base::UTF8ToUTF16(kMimeTypeText));
+ if (IsFormatAvailable(ClipboardFormatType::HtmlType(), type, data_dst))
+ types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
+
+ if (IsFormatAvailable(ClipboardFormatType::RtfType(), type, data_dst))
+ types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
+ if (IsFormatAvailable(ClipboardFormatType::BitmapType(), type, data_dst))
+ types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
}
-void ClipboardEfl::ReadText(ClipboardType type, string16* result) const {
+void ClipboardEfl::ReadText(ClipboardBuffer type,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* result) const {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
+ DCHECK_EQ(type, ClipboardBuffer::kCopyPaste);
std::string utf8;
- ReadAsciiText(type, &utf8);
+ ReadAsciiText(type, data_dst, &utf8);
*result = base::UTF8ToUTF16(utf8);
}
-void ClipboardEfl::ReadAsciiText(ClipboardType type, std::string* result) const {
+void ClipboardEfl::ReadAsciiText(ClipboardBuffer type,
+ const DataTransferEndpoint* data_dst,
+ std::string* result) const {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- int count = ClipboardHelperEfl::GetInstance()->NumberOfItems();
-
- int format = ELM_SEL_FORMAT_NONE;
- std::string clipboard_data;
-
- for (int i = 0; i < count; i++) {
- if (!ClipboardHelperEfl::GetInstance()->RetrieveClipboardItem(i, &format, &clipboard_data))
- continue;
-
- if (format == ELM_SEL_FORMAT_TEXT) {
- result->clear();
- result->assign(clipboard_data);
- break;
- }
- }
+ DCHECK_EQ(type, ClipboardBuffer::kCopyPaste);
+ ClipboardHelperEfl::GetInstance()->RetrieveClipboardItem(
+ result, ClipboardDataTypeEfl::PLAIN_TEXT);
}
-void ClipboardEfl::ReadHTML(ClipboardType type, string16* markup,
- std::string* src_url, uint32_t* fragment_start,
- uint32_t* fragment_end) const {
+void ClipboardEfl::ReadHTML(ClipboardBuffer type,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* markup,
+ std::string* src_url,
+ uint32_t* fragment_start,
+ uint32_t* fragment_end) const {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- int count = ClipboardHelperEfl::GetInstance()->NumberOfItems();
- if (src_url)
- src_url->clear();
+ DCHECK_EQ(type, ClipboardBuffer::kCopyPaste);
// This is supposed to contain context for html parsing.
// We set 0 and markup->size() respectively, which is same as other platforms.
+ src_url->clear();
+ markup->clear();
*fragment_start = 0;
*fragment_end = 0;
- int format = ELM_SEL_FORMAT_NONE;
std::string clipboard_data;
-
- for (int i = 0; i < count; i++) {
- if (!ClipboardHelperEfl::GetInstance()->RetrieveClipboardItem(i, &format, &clipboard_data))
- continue;
-
- if (format == ELM_SEL_FORMAT_HTML) {
- markup->clear();
- markup->assign(base::UTF8ToUTF16(clipboard_data));
- *fragment_end = static_cast<uint32_t>(markup->size());
- break;
- }
+ if (ClipboardHelperEfl::GetInstance()->RetrieveClipboardItem(
+ &clipboard_data, ClipboardDataTypeEfl::MARKUP)) {
+ *markup = base::UTF8ToUTF16(clipboard_data);
+ *fragment_end = markup->size();
}
}
-void ClipboardEfl::ReadRTF(ClipboardType type, std::string* result) const {
+void ClipboardEfl::ReadSvg(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* result) const {
NOTIMPLEMENTED();
}
-SkBitmap ClipboardEfl::ReadImage(ClipboardType type) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
+void ClipboardEfl::ReadRTF(ClipboardBuffer type,
+ const DataTransferEndpoint* data_dst,
+ std::string* result) const {
NOTIMPLEMENTED();
-
- return SkBitmap();
}
-void ClipboardEfl::ReadBookmark(string16* title, std::string* url) const {
+void ClipboardEfl::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
NOTIMPLEMENTED();
}
-void ClipboardEfl::ReadCustomData(ClipboardType clipboard_type,
- const string16& type,
- string16* result) const {
+void ClipboardEfl::ReadBookmark(const DataTransferEndpoint* data_dst,
+ std::u16string* title,
+ std::string* url) const {
NOTIMPLEMENTED();
}
-void ClipboardEfl::ReadData(const FormatType& format, std::string* result) const {
- DCHECK(CalledOnValidThread());
+void ClipboardEfl::ReadCustomData(ClipboardBuffer clipboard_type,
+ const std::u16string& type,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* result) const {
NOTIMPLEMENTED();
}
-// static
-Clipboard::FormatType Clipboard::GetFormatType(const std::string& format_string) {
- return FormatType::Deserialize(format_string);
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kWebKitSmartPasteFormat));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kHTMLFormat));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kRTFFormat));
- return type;
+void ClipboardEfl::ReadFilenames(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::vector<ui::FileInfo>* result) const {
+ NOTIMPLEMENTED();
}
-// static
-const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kBitmapFormat));
- return type;
+void ClipboardEfl::ReadData(const ClipboardFormatType& format,
+ const DataTransferEndpoint* data_dst,
+ std::string* result) const {
+ NOTIMPLEMENTED();
}
-// static
-const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
- return type;
+void ClipboardEfl::WriteText(const char* text_data, size_t text_len) {
+ ClipboardHelperEfl::GetInstance()->SetData(std::string(text_data, text_len),
+ ClipboardDataTypeEfl::PLAIN_TEXT);
}
-// static
-const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
- return type;
+void ClipboardEfl::WriteHTML(const char* markup_data,
+ size_t markup_len,
+ const char* url_data,
+ size_t url_len) {
+ ClipboardHelperEfl::GetInstance()->SetData(
+ std::string(markup_data, markup_len), ClipboardDataTypeEfl::MARKUP);
}
-void ClipboardEfl::WriteText(const char* text_data, size_t text_len) {
- ClipboardHelperEfl::GetInstance()->
- SetData(std::string(text_data, text_len), ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_PLAIN_TEXT);
+void ClipboardEfl::WriteSvg(const char* markup_data, size_t markup_len) {
+ NOTIMPLEMENTED();
}
-void ClipboardEfl::WriteHTML(const char* markup_data, size_t markup_len,
- const char* url_data, size_t url_len) {
- ClipboardHelperEfl::GetInstance()->
- SetData(std::string(markup_data, markup_len), ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_MARKUP);
+void ClipboardEfl::WriteFilenames(std::vector<ui::FileInfo> filenames) {
+ NOTIMPLEMENTED();
}
void ClipboardEfl::WriteRTF(const char* rtf_data, size_t data_len) {
NOTIMPLEMENTED();
}
-void ClipboardEfl::WriteData(const FormatType& format, const char* data_data, size_t data_len) {
+void ClipboardEfl::WriteData(const ClipboardFormatType& format,
+ const char* data_data,
+ size_t data_len) {
NOTIMPLEMENTED();
}
+std::vector<std::u16string> ClipboardEfl::GetStandardFormats(
+ ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst) const {
+ NOTIMPLEMENTED();
+}
} //namespace ui
ClipboardEfl();
~ClipboardEfl() override;
+ ClipboardEfl(const ClipboardEfl&) = delete;
+ ClipboardEfl& operator=(const ClipboardEfl&) = delete;
+
// Clipboard overrides:
void OnPreShutdown() override;
-
- uint64_t GetSequenceNumber(ClipboardType type) const override;
+ DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
- ClipboardType type) const override;
- void Clear(ClipboardType type) override;
- void ReadAvailableTypes(ClipboardType type,
- std::vector<std::u16string>* types,
- bool* contains_filenames) const override;
- void ReadText(ClipboardType type, std::u16string* result) const override;
- void WriteObjects(ClipboardType type, const ObjectMap& objects) override;
- void ReadAsciiText(ClipboardType type, std::string* result) const override;
- void ReadHTML(ClipboardType type,
+ ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst) const override;
+ void Clear(ClipboardBuffer buffer) override;
+ void ReadAvailableTypes(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::vector<std::u16string>* types) const override;
+ void ReadText(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* result) const override;
+ void ReadAsciiText(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::string* result) const override;
+ void ReadHTML(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
std::u16string* markup,
std::string* src_url,
uint32_t* fragment_start,
uint32_t* fragment_end) const override;
- void ReadRTF(ClipboardType type, std::string* result) const override;
- SkBitmap ReadImage(ClipboardType type) const override;
- void ReadBookmark(std::u16string* title, std::string* url) const override;
- void ReadCustomData(ClipboardType clipboard_type,
+ void ReadSvg(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::u16string* result) const override;
+ void ReadRTF(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
+ void ReadCustomData(ClipboardBuffer buffer,
const std::u16string& type,
+ const DataTransferEndpoint* data_dst,
std::u16string* result) const override;
+ void ReadFilenames(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ std::vector<ui::FileInfo>* result) const override;
+ void ReadBookmark(const DataTransferEndpoint* data_dst,
+ std::u16string* title,
+ std::string* url) const override;
void ReadData(const ClipboardFormatType& format,
+ const DataTransferEndpoint* data_dst,
std::string* result) const override;
+#if defined(USE_OZONE)
+ bool IsSelectionBufferAvailable() const override { return false; }
+#endif
+ void WritePortableAndPlatformRepresentations(
+ ClipboardBuffer buffer,
+ const ObjectMap& objects,
+ std::vector<Clipboard::PlatformRepresentation> platform_representations,
+ std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
-
void WriteHTML(const char* markup_data,
size_t markup_len,
const char* url_data,
size_t url_len) override;
-
+ void WriteSvg(const char* markup_data, size_t markup_len) override;
void WriteRTF(const char* rtf_data, size_t data_len) override;
-
+ void WriteFilenames(std::vector<ui::FileInfo> filenames) override;
void WriteBookmark(const char* title_data,
size_t title_len,
const char* url_data,
size_t url_len) override;
-
void WriteWebSmartPaste() override;
-
void WriteBitmap(const SkBitmap& bitmap) override;
-
void WriteData(const ClipboardFormatType& format,
const char* data_data,
size_t data_len) override;
+ std::vector<std::u16string> GetStandardFormats(
+ ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst) const override;
};
} // namespace ui
-// Copyright 2014 Samsung Electronics. All rights reseoved.
+// Copyright 2018 Samsung Electronics. 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/base/clipboard/clipboard_helper_efl.h"
-
-#include <Evas.h>
-#include <Ecore_Evas.h>
-#include "ecore_x_wayland_wrapper.h"
-#include <Elementary.h>
-#if defined(WAYLAND_BRINGUP)
-#include <map>
-#endif
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#endif
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/notreached.h"
-#include "base/strings/utf_string_conversions.h"
-
-#if defined(WAYLAND_BRINGUP)
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-namespace {
-
-#if defined(WAYLAND_BRINGUP)
-static std::map<std::string, std::string> s_clipboard;
-#endif
-
-enum ClipType {
- CLIP_TYPE_PRIMARY,
- CLIP_TYPE_SECONDARY,
- CLIP_TYPE_CLIPBOARD,
- CLIP_TYPE_XDND,
- CLIP_TYPE_MAX,
-};
-
-struct ClipData {
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Selection selection;
- void (*request)(Ecore_X_Window window, const char* pTarget);
-#endif
-
- Elm_Sel_Format format;
- Elm_Sel_Format requestedFormat;
- int bufferLength;
-
- ClipboardHelperEfl* clipboardHelper;
-
- // TODO: Add proper delegate class for clipboard related functionality
- // EWK needs.
- EWebView* webView;
-};
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-typedef int (*ClipNotifyHandler)(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData);
-#endif
-
-enum {
- ATOM_TARGETS = 0,
- ATOM_ATOM,
- ATOM_LISTING_ATOMS = ATOM_ATOM,
- ATOM_TEXT_URI,
- ATOM_TEXT_URILIST,
- ATOM_TEXT_X_VCARD,
- ATOM_IMAGE_PNG,
- ATOM_IMAGE_JPEG,
- ATOM_IMAGE_BMP,
- ATOM_IMAGE_GIF,
- ATOM_IMAGE_TIFF,
- ATOM_IMAGE_SVG,
- ATOM_IMAGE_XPM,
- ATOM_IMAGE_TGA,
- ATOM_IMAGE_PPM,
- ATOM_XELM,
- ATOM_TEXT_HTML_UTF8,
- ATOM_TEXT_HTML,
- ATOM_STRING_UTF8,
- ATOM_STRING,
- ATOM_TEXT,
- ATOM_TEXT_PLAIN_UTF8,
- ATOM_TEXT_PLAIN,
- ATOM_FORMAT_NONE,
- ATOM_MAX,
-};
-
-struct AtomData {
- const char* pName;
- Elm_Sel_Format formats;
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- ClipNotifyHandler notify;
- Ecore_X_Atom atom;
-#endif
-};
-
-AtomData atomList[ATOM_MAX];
-ClipData clipList[CLIP_TYPE_MAX];
-
-Eina_Bool propertyChangeCallback(void* data, int type, void* event) {
- ClipboardHelperEfl* clipboardHelper = static_cast<ClipboardHelperEfl*>(data);
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Event_Window_Property* ev = (Ecore_X_Event_Window_Property*)event;
-
- if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
- clipboardHelper->UpdateClipboardWindowState(ev);
-#else
- NOTIMPLEMENTED();
-#endif
-
- return EINA_TRUE;
-}
-
-const char kCbhmMessageHide[] = "cbhm_hide";
-const char kCbhmMessageSetItem[] = "SET_ITEM";
-const char kCbhmMessageShow0[] = "show0";
-const char kCbhmMessageShow1[] = "show1";
-
-const char kCbhmAtomClipboardCount[] = "CBHM_cCOUNT";
-const char kCbhmAtomElmMarkup[] = "application/x-elementary-markup";
-const char kCbhmAtomError[] = "CBHM_ERROR";
-const char kCbhmAtomItem[] = "CBHM_ITEM";
-const char kCbhmAtomMessage[] = "CBHM_MSG";
-const char kCbhmAtomTextHtml[] = "text/html;charset=utf-8";
-const char kCbhmAtomTextUriList[] = "text/uri-list";
-const char kCbhmAtomUTF8String[] = "UTF8_STRING";
-const char kCbhmAtomXWindow[] = "CBHM_XWIN";
-
-const int kDataUnitSize8 = 8;
-const int kDataUnitSize16 = 16;
-const int kDataUnitSize32 = 32;
-} // namespace
-
-ClipboardHelperEfl* ClipboardHelperEfl::GetInstance() {
- return base::Singleton<ClipboardHelperEfl>::get();
-}
-
-ClipboardHelperEfl::ClipboardHelperEfl() {
- m_selectionClearHandler = 0;
- m_selectionNotifyHandler = 0;
- property_change_handler_ = 0;
- clipboard_window_opened_ = false;
-}
-
-void ClipboardHelperEfl::SetData(const std::string& data,
- ClipboardDataType type) {
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Atom data_type = 0;
-
- switch (type) {
- case CLIPBOARD_DATA_TYPE_PLAIN_TEXT:
- case CLIPBOARD_DATA_TYPE_URI_LIST:
- case CLIPBOARD_DATA_TYPE_URL:
- data_type = ecore_x_atom_get(kCbhmAtomUTF8String);
- break;
- case CLIPBOARD_DATA_TYPE_IMAGE:
- data_type = ecore_x_atom_get(kCbhmAtomTextUriList);
- break;
- case CLIPBOARD_DATA_TYPE_MARKUP:
- data_type = ecore_x_atom_get(kCbhmAtomTextHtml);
- default:
- NOTIMPLEMENTED();
- }
-#else
- std::string data_type;
+#include "clipboard_helper_efl.h"
+Elm_Sel_Format ClipboardFormatToElm(ClipboardDataTypeEfl type) {
switch (type) {
- case CLIPBOARD_DATA_TYPE_PLAIN_TEXT:
- case CLIPBOARD_DATA_TYPE_URI_LIST:
- case CLIPBOARD_DATA_TYPE_URL:
- data_type = kCbhmAtomUTF8String;
- break;
- case CLIPBOARD_DATA_TYPE_IMAGE:
- data_type = kCbhmAtomTextUriList;
- break;
- case CLIPBOARD_DATA_TYPE_MARKUP:
- data_type = kCbhmAtomTextHtml;
- break;
- default:
- NOTREACHED();
- }
-#endif
- SetClipboardItem(data_type, data);
-}
-
-void ClipboardHelperEfl::Clear() {
- NOTIMPLEMENTED();
-}
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-Ecore_X_Window ClipboardHelperEfl::GetCbhmWindow() {
- Ecore_X_Atom xAtomCbhm = ecore_x_atom_get(kCbhmAtomXWindow);
- Ecore_X_Window xCbhmWin = 0;
-
- unsigned char* buf = 0;
- int property_size = 0;
- int property_array_size = ecore_x_window_prop_property_get(
- 0, xAtomCbhm, XA_WINDOW, 0, &buf, &property_size);
-
- if (property_array_size && property_size)
- memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
-
- if (buf)
- free(buf);
-
- return xCbhmWin;
-}
-#endif
-
-bool ClipboardHelperEfl::SendCbhmMessage(const std::string& message) {
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Window cbhm_win = GetCbhmWindow();
- Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(kCbhmAtomMessage);
-
- if (!cbhm_win || !atom_cbhm_item)
- return false;
- Ecore_X_Window xwin = ecore_x_window_focus_get();
- XClientMessageEvent messageEvent;
- memset(&messageEvent, 0, sizeof(messageEvent));
- messageEvent.type = ClientMessage;
- messageEvent.display = static_cast<Display*>(ecore_x_display_get());
- messageEvent.window = xwin;
- messageEvent.message_type = atom_cbhm_item;
- messageEvent.format = 8; /* data should be viewed as byte */
- snprintf(messageEvent.data.b, sizeof(messageEvent.data.b), "%s",
- message.c_str());
-
- XSendEvent(static_cast<Display*>(ecore_x_display_get()), cbhm_win, false,
- NoEventMask, reinterpret_cast<XEvent*>(&messageEvent));
-
- ecore_x_sync();
-#else
- NOTIMPLEMENTED();
-#endif
-
- return true;
-}
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-bool ClipboardHelperEfl::SetClipboardItem(Ecore_X_Atom data_type,
- const std::string& data) {
- if (data.empty())
- return false;
-
- Ecore_X_Window cbhm_win = GetCbhmWindow();
- Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(kCbhmAtomItem);
-
- size_t data_start_index = 0;
- const char prefix[] = "file://";
- if (data.compare(0, sizeof(prefix) - 1, prefix) == 0)
- data_start_index = sizeof(prefix) - 1;
-
- ecore_x_sync();
- ecore_x_window_prop_property_set(
- cbhm_win, atom_cbhm_item, data_type, 8,
- const_cast<char*>(data.c_str()) + data_start_index,
- data.length() - data_start_index + 1);
- ecore_x_sync();
-
- if (SendCbhmMessage(kCbhmMessageSetItem))
- return true;
-
- return false;
-}
-#else
-bool ClipboardHelperEfl::SetClipboardItem(const std::string& data_type,
- const std::string& data) {
- s_clipboard[data_type] = data;
-
- if (SendCbhmMessage(kCbhmMessageSetItem))
- return true;
-
- return false;
-}
-#endif
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-std::string ClipboardHelperEfl::GetCbhmReply(Ecore_X_Window xwin,
- Ecore_X_Atom property,
- Ecore_X_Atom* data_type) {
- if (!property)
- return std::string();
-
- ecore_x_sync();
-
- Ecore_X_Atom type;
- int data_unit_size = 0;
- long unsigned int data_length = 0;
- long unsigned int bytes = 0;
- unsigned char* data = 0;
-
- int result = XGetWindowProperty(
- static_cast<Display*>(ecore_x_display_get()), xwin, property, 0, LONG_MAX,
- False, ecore_x_window_prop_any_type(), reinterpret_cast<Atom*>(&type),
- &data_unit_size, &data_length, &bytes, &data);
-
- if (result != Success)
- return std::string();
-
- if (!data_length) {
- XFree(data);
- return std::string();
- }
-
- std::string cbhm_data;
-
- switch (data_unit_size) {
- case kDataUnitSize8:
- cbhm_data = std::string(reinterpret_cast<const char*>(data), data_length);
- break;
- case kDataUnitSize16:
-#if !defined(EWK_BRINGUP) // FIXME: m94 bringup
- cbhm_data = base::UTF16ToUTF8(std::u16string(
- reinterpret_cast<const base::char16*>(data), data_length));
-#endif
- break;
- case kDataUnitSize32:
- break;
+ case ClipboardDataTypeEfl::PLAIN_TEXT:
+ case ClipboardDataTypeEfl::URI_LIST:
+ case ClipboardDataTypeEfl::URL:
+ return ELM_SEL_FORMAT_TEXT;
+ case ClipboardDataTypeEfl::IMAGE:
+ return ELM_SEL_FORMAT_IMAGE;
+ case ClipboardDataTypeEfl::MARKUP:
+ return ELM_SEL_FORMAT_HTML;
default:
- NOTREACHED();
- break;
- }
-
- XFree(data);
-
- if (data_type)
- *data_type = type;
-
- return cbhm_data;
-}
-#endif
-
-bool ClipboardHelperEfl::RetrieveClipboardItem(int index,
- int* format,
- std::string* data) {
- if (!data)
- return false;
-
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Window cbhm_win = GetCbhmWindow();
- std::ostringstream cbhm_item;
- cbhm_item << kCbhmAtomItem << index;
-
- Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(cbhm_item.str().c_str());
- Ecore_X_Atom atom_item_type = 0;
-
- std::string result = GetCbhmReply(cbhm_win, atom_cbhm_item, &atom_item_type);
- if (result.empty() || atom_item_type == ecore_x_atom_get(kCbhmAtomError))
- return false;
-
- // TODO: Other formats need to be added here.
- if ((atom_item_type == ecore_x_atom_get(kCbhmAtomUTF8String)) ||
- (atom_item_type == ecore_x_atom_get(kCbhmAtomElmMarkup))) {
- *format = ELM_SEL_FORMAT_TEXT;
- data->swap(result);
- if (atom_item_type == ecore_x_atom_get(kCbhmAtomElmMarkup))
- *data =
- std::string(evas_textblock_text_markup_to_utf8(NULL, data->c_str()));
- return true;
- } else if (atom_item_type == ecore_x_atom_get(kCbhmAtomTextHtml)) {
- *format = ELM_SEL_FORMAT_HTML;
- data->swap(result);
- return true;
- }
-#else
- if (s_clipboard.size() < static_cast<unsigned int>(index))
- return false;
-
- std::map<std::string, std::string>::iterator clipboardElem =
- s_clipboard.begin();
- std::advance(clipboardElem, index);
-
- if (clipboardElem->first == kCbhmAtomUTF8String ||
- clipboardElem->first == kCbhmAtomElmMarkup) {
- *format = ELM_SEL_FORMAT_TEXT;
- *data = clipboardElem->second;
- if (clipboardElem->first == kCbhmAtomElmMarkup)
- *data =
- std::string(evas_textblock_text_markup_to_utf8(NULL, data->c_str()));
- return true;
- } else if (clipboardElem->first == kCbhmAtomTextHtml) {
- *format = ELM_SEL_FORMAT_HTML;
- *data = clipboardElem->second;
- return true;
- } else if (clipboardElem->first == kCbhmAtomTextUriList) {
- *format = ELM_SEL_FORMAT_IMAGE;
- *data = clipboardElem->second;
- return true;
+ return ELM_SEL_FORMAT_TEXT;
}
-#endif
- return false;
-}
-
-int ClipboardHelperEfl::NumberOfItems() {
-// 1. Get CBHM Ecore_X_Window.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Atom x_atom;
- x_atom = ecore_x_atom_get(kCbhmAtomXWindow);
- if (!x_atom)
- return 0;
-
- unsigned char* data = 0;
- int number_of_windows = 0;
- int result = ecore_x_window_prop_property_get(0, x_atom, XA_WINDOW, 0, &data,
- &number_of_windows);
-
- Ecore_X_Window x_window = 0;
- if (result && number_of_windows)
- memcpy(&x_window, data, sizeof(Ecore_X_Window));
-
- if (data)
- free(data);
-
- if (!x_window)
- return 0;
-
- ecore_x_sync();
-
- // 2. Get number of clipboard items.
- x_atom = ecore_x_atom_get(kCbhmAtomClipboardCount);
- if (!x_atom)
- return 0;
-
- Display* display = static_cast<Display*>(ecore_x_display_get());
-
- Ecore_X_Atom type;
- int format;
- long unsigned number_of_items = 0;
- long unsigned bytes = 0;
- unsigned char* data_in_format = 0;
- result = XGetWindowProperty(display, x_window, x_atom, 0, LONG_MAX, False,
- ecore_x_window_prop_any_type(),
- reinterpret_cast<Atom*>(&type), &format,
- &number_of_items, &bytes, &data_in_format);
- if (result != Success)
- return 0;
-
- if (!number_of_items) {
- XFree(data_in_format);
- return 0;
- }
-
- if (!data_in_format)
- return 0;
-
- char* end;
- errno = 0;
- long int count =
- strtol(reinterpret_cast<const char*>(data_in_format), &end, 10);
- if ((end == reinterpret_cast<const char*>(data_in_format) ||
- *end != '\0') /* not a number */
- || ((count == LONG_MIN || count == LONG_MAX) &&
- ERANGE == errno) /* out of range */) {
- DLOG(ERROR) << "String to int conversion failed.";
- return 0;
- }
- return count;
-#else
- return s_clipboard.size();
-#endif
-}
-
-static void pasteSelectedClipboardItem(std::string data,
- std::string type,
- EWebView* webview) {
-#if 0
- content::SelectionControllerEfl* controller = webview->GetSelectionController();
- if (controller)
- controller->HideHandleAndContextMenu();
-
- webview->ExecuteEditCommand(type.c_str(), data.c_str());
- ClipboardHelperEfl::connectClipboardWindow();
-#endif
-}
-
-static Eina_Bool clearClip(void* data, int type, void* event) {
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Event_Selection_Clear* clearEvent =
- (Ecore_X_Event_Selection_Clear*)event;
- Ecore_X_Window window = clearEvent->win;
-
- ClipType clipType = CLIP_TYPE_SECONDARY;
- clipList[clipType].requestedFormat =
- static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_IMAGE);
-
- ecore_x_selection_secondary_request(window, ECORE_X_SELECTION_TARGET_TARGETS);
-#else
- s_clipboard.clear();
-#endif
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool notifyClip(void* data, int type, void* event) {
- EWebView* webview = static_cast<EWebView*>(data);
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Event_Selection_Notify* notifytEvent =
- (Ecore_X_Event_Selection_Notify*)event;
-
- int i = 0;
- for (i = 0; i < CLIP_TYPE_MAX; i++) {
- if (clipList[i].selection == notifytEvent->selection)
- break;
- }
-
- ClipData* clipData = clipList + i;
- clipData->webView = webview;
- for (i = 0; i < ATOM_MAX; i++) {
- if (!strcmp(notifytEvent->target, atomList[i].pName) && atomList[i].notify)
- atomList[i].notify(clipData, notifytEvent);
- }
-#else
- NOTIMPLEMENTED();
-#endif
- return ECORE_CALLBACK_PASS_ON;
-}
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-static int notifyTarget(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- Ecore_X_Atom dataType = 0;
-
- if (clipData->clipboardHelper->getSelectedCbhmItem(&dataType)) {
- const char* pHtmlAtomName = "text/html;charset=utf-8";
- Ecore_X_Atom htmlType = ecore_x_atom_get(pHtmlAtomName);
-
- if (dataType == htmlType) {
- clipData->request(notifyData->win, pHtmlAtomName);
- return ECORE_CALLBACK_PASS_ON;
- }
- }
-
- Ecore_X_Selection_Data_Targets* pTargets =
- (Ecore_X_Selection_Data_Targets*)(notifyData->data);
- Ecore_X_Atom* pAtomList = (Ecore_X_Atom*)(pTargets->data.data);
-
- int i, j = 0;
- for (j = (ATOM_LISTING_ATOMS + 1); j < ATOM_MAX; j++) {
- if (!(atomList[j].formats & clipData->requestedFormat))
- continue;
- for (i = 0; i < pTargets->data.length; i++) {
- if ((atomList[j].atom == pAtomList[i]) && (atomList[j].notify)) {
- if ((j == ATOM_XELM) &&
- (!(clipData->requestedFormat & ELM_SEL_FORMAT_MARKUP)))
- continue;
- goto FOUND;
- }
- }
- }
-
- return ECORE_CALLBACK_PASS_ON;
-
-FOUND:
- clipData->request(notifyData->win, atomList[j].pName);
- return ECORE_CALLBACK_PASS_ON;
-}
-#endif
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-static int notifyText(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
- pasteSelectedClipboardItem(std::string((char*)pData->data), "InsertText",
- clipData->webView);
- return 0;
-}
-
-static int notifyImage(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- return 0;
-}
-
-static int notifyUri(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
- pasteSelectedClipboardItem(
- std::string(reinterpret_cast<char*>(pData->data), pData->length),
- "InsertImage", clipData->webView);
- return 0;
-}
-
-static int notifyEdje(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- return 0;
-}
-
-static int notifyHtml(ClipData* clipData,
- Ecore_X_Event_Selection_Notify* notifyData) {
- Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
- pasteSelectedClipboardItem(
- std::string(reinterpret_cast<char*>(pData->data), pData->length),
- "InsertHTML", clipData->webView);
- return 0;
-}
-#endif
-
-void ClipboardHelperEfl::initializeAtomList() {
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- atomList[ATOM_TARGETS].pName = "TARGETS";
- atomList[ATOM_TARGETS].formats = ELM_SEL_FORMAT_TARGETS;
- atomList[ATOM_TARGETS].notify = notifyTarget;
- atomList[ATOM_TARGETS].atom = 0;
-
- atomList[ATOM_ATOM].pName = "ATOM";
- atomList[ATOM_ATOM].formats = ELM_SEL_FORMAT_TARGETS;
- atomList[ATOM_ATOM].notify = notifyTarget;
- atomList[ATOM_ATOM].atom = 0;
-
- atomList[ATOM_XELM].pName = "application/x-elementary-markup";
- atomList[ATOM_XELM].formats = ELM_SEL_FORMAT_MARKUP;
- atomList[ATOM_XELM].notify = notifyEdje;
- atomList[ATOM_XELM].atom = 0;
-
- atomList[ATOM_TEXT_URI].pName = "text/uri";
- atomList[ATOM_TEXT_URI].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_TEXT_URI].notify = notifyUri;
- atomList[ATOM_TEXT_URI].atom = 0;
-
- atomList[ATOM_TEXT_URILIST].pName = "text/uri-list";
- atomList[ATOM_TEXT_URILIST].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_TEXT_URILIST].notify = notifyUri;
- atomList[ATOM_TEXT_URILIST].atom = 0;
-
- atomList[ATOM_TEXT_X_VCARD].pName = "text/x-vcard";
- atomList[ATOM_TEXT_X_VCARD].formats = ELM_SEL_FORMAT_VCARD;
- atomList[ATOM_TEXT_X_VCARD].notify = 0;
- atomList[ATOM_TEXT_X_VCARD].atom = 0;
-
- atomList[ATOM_IMAGE_PNG].pName = "image/png";
- atomList[ATOM_IMAGE_PNG].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_PNG].notify = notifyImage;
- atomList[ATOM_IMAGE_PNG].atom = 0;
-
- atomList[ATOM_IMAGE_JPEG].pName = "image/jpeg";
- atomList[ATOM_IMAGE_JPEG].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_JPEG].notify = notifyImage;
- atomList[ATOM_IMAGE_JPEG].atom = 0;
-
- atomList[ATOM_IMAGE_BMP].pName = "image/x-ms-bmp";
- atomList[ATOM_IMAGE_BMP].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_BMP].notify = notifyImage;
- atomList[ATOM_IMAGE_BMP].atom = 0;
-
- atomList[ATOM_IMAGE_GIF].pName = "image/gif";
- atomList[ATOM_IMAGE_GIF].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_GIF].notify = notifyImage;
- atomList[ATOM_IMAGE_GIF].atom = 0;
-
- atomList[ATOM_IMAGE_TIFF].pName = "image/tiff";
- atomList[ATOM_IMAGE_TIFF].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_TIFF].notify = notifyImage;
- atomList[ATOM_IMAGE_TIFF].atom = 0;
-
- atomList[ATOM_IMAGE_SVG].pName = "image/svg+xml";
- atomList[ATOM_IMAGE_SVG].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_SVG].notify = notifyImage;
- atomList[ATOM_IMAGE_SVG].atom = 0;
-
- atomList[ATOM_IMAGE_XPM].pName = "image/x-xpixmap";
- atomList[ATOM_IMAGE_XPM].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_XPM].notify = notifyImage;
- atomList[ATOM_IMAGE_XPM].atom = 0;
-
- atomList[ATOM_IMAGE_TGA].pName = "image/x-tga";
- atomList[ATOM_IMAGE_TGA].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_TGA].notify = notifyImage;
- atomList[ATOM_IMAGE_TGA].atom = 0;
-
- atomList[ATOM_IMAGE_PPM].pName = "image/x-portable-pixmap";
- atomList[ATOM_IMAGE_PPM].formats = ELM_SEL_FORMAT_IMAGE;
- atomList[ATOM_IMAGE_PPM].notify = notifyImage;
- atomList[ATOM_IMAGE_PPM].atom = 0;
-
- atomList[ATOM_TEXT_HTML_UTF8].pName = "text/html;charset=utf-8";
- atomList[ATOM_TEXT_HTML_UTF8].formats = ELM_SEL_FORMAT_HTML;
- atomList[ATOM_TEXT_HTML_UTF8].notify = notifyHtml;
- atomList[ATOM_TEXT_HTML_UTF8].atom = 0;
-
- atomList[ATOM_TEXT_HTML].pName = "text/html";
- atomList[ATOM_TEXT_HTML].formats = ELM_SEL_FORMAT_HTML;
- atomList[ATOM_TEXT_HTML].notify = notifyHtml;
- atomList[ATOM_TEXT_HTML].atom = 0;
-
- atomList[ATOM_STRING_UTF8].pName = "UTF8_STRING";
- atomList[ATOM_STRING_UTF8].formats = static_cast<Elm_Sel_Format>(
- ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
- atomList[ATOM_STRING_UTF8].notify = notifyText;
- atomList[ATOM_STRING_UTF8].atom = 0;
-
- atomList[ATOM_STRING].pName = "STRING";
- atomList[ATOM_STRING].formats = static_cast<Elm_Sel_Format>(
- ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
- atomList[ATOM_STRING].notify = notifyText;
- atomList[ATOM_STRING].atom = 0;
-
- atomList[ATOM_TEXT].pName = "TEXT";
- atomList[ATOM_TEXT].formats = static_cast<Elm_Sel_Format>(
- ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
- atomList[ATOM_TEXT].notify = 0;
- atomList[ATOM_TEXT].atom = 0;
-
- atomList[ATOM_TEXT_PLAIN_UTF8].pName = "text/plain;charset=utf-8";
- atomList[ATOM_TEXT_PLAIN_UTF8].formats = static_cast<Elm_Sel_Format>(
- ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
- atomList[ATOM_TEXT_PLAIN_UTF8].notify = 0;
- atomList[ATOM_TEXT_PLAIN_UTF8].atom = 0;
-
- atomList[ATOM_TEXT_PLAIN].pName = "text/plain";
- atomList[ATOM_TEXT_PLAIN].formats = static_cast<Elm_Sel_Format>(
- ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
- atomList[ATOM_TEXT_PLAIN].notify = notifyText;
- atomList[ATOM_TEXT_PLAIN].atom = 0;
-
- atomList[ATOM_FORMAT_NONE].pName = "NONE";
- atomList[ATOM_FORMAT_NONE].formats = ELM_SEL_FORMAT_NONE;
- atomList[ATOM_FORMAT_NONE].notify = notifyText;
- atomList[ATOM_FORMAT_NONE].atom = 0;
-
- clipList[CLIP_TYPE_PRIMARY].selection = ECORE_X_SELECTION_PRIMARY;
- clipList[CLIP_TYPE_PRIMARY].request = ecore_x_selection_primary_request;
- clipList[CLIP_TYPE_PRIMARY].bufferLength = 0;
-
- clipList[CLIP_TYPE_SECONDARY].selection = ECORE_X_SELECTION_SECONDARY;
- clipList[CLIP_TYPE_SECONDARY].request = ecore_x_selection_secondary_request;
- clipList[CLIP_TYPE_SECONDARY].bufferLength = 0;
-
- clipList[CLIP_TYPE_CLIPBOARD].selection = ECORE_X_SELECTION_CLIPBOARD;
- clipList[CLIP_TYPE_CLIPBOARD].request = ecore_x_selection_clipboard_request;
- clipList[CLIP_TYPE_CLIPBOARD].bufferLength = 0;
-
- clipList[CLIP_TYPE_XDND].selection = ECORE_X_SELECTION_XDND;
- clipList[CLIP_TYPE_XDND].request = ecore_x_selection_xdnd_request;
- clipList[CLIP_TYPE_XDND].bufferLength = 0;
-
- for (int i = 0; i < ATOM_MAX; i++)
- atomList[i].atom = ecore_x_atom_get(atomList[i].pName);
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-void ClipboardHelperEfl::clearClipboardHandler() {
- if (m_selectionClearHandler) {
- ecore_event_handler_del(m_selectionClearHandler);
- m_selectionClearHandler = 0;
- }
-
- if (m_selectionNotifyHandler) {
- ecore_event_handler_del(m_selectionNotifyHandler);
- m_selectionNotifyHandler = 0;
- }
-
- if (property_change_handler_) {
- ecore_event_handler_del(property_change_handler_);
- property_change_handler_ = 0;
- }
- clipboard_window_opened_ = false;
-}
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-bool ClipboardHelperEfl::getSelectedCbhmItem(Ecore_X_Atom* pDataType) {
- Ecore_X_Window cbhmWin = GetCbhmWindow();
- Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_SELECTED_ITEM");
- Ecore_X_Atom atomItemType = 0;
-
- std::string result = GetCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
-
- if (result.empty())
- return false;
-
- if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
- return false;
-
- if (pDataType)
- *pDataType = atomItemType;
-
- return true;
-}
-#endif
-
-void ClipboardHelperEfl::OpenClipboardWindow(EWebView* view,
- bool richly_editable) {
- clearClipboardHandler();
- initializeAtomList();
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- property_change_handler_ = ecore_event_handler_add(
- ECORE_X_EVENT_WINDOW_PROPERTY, propertyChangeCallback, this);
- m_selectionClearHandler =
- ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, clearClip, view);
- m_selectionNotifyHandler =
- ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, notifyClip, view);
-#else
- NOTIMPLEMENTED();
-#endif
-
- if (richly_editable)
- SendCbhmMessage(kCbhmMessageShow1);
- else
- SendCbhmMessage(kCbhmMessageShow0);
-
- connectClipboardWindow();
-#if 0
- view->SmartCallback<EWebViewCallbacks::ClipboardOpened>().call(0);
-#endif
-}
-
-void ClipboardHelperEfl::connectClipboardWindow() {
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- ecore_x_selection_secondary_set(ecore_x_window_focus_get(), "", 1);
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-bool ClipboardHelperEfl::IsClipboardWindowOpened() {
- return clipboard_window_opened_;
-}
-
-void ClipboardHelperEfl::CloseClipboardWindow() {
- SendCbhmMessage(kCbhmMessageHide);
-}
-
-// TODO: Webview and Rendering TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
-void ClipboardHelperEfl::UpdateClipboardWindowState(
- Ecore_X_Event_Window_Property* ev) {
- Ecore_X_Illume_Clipboard_State state =
- ecore_x_e_illume_clipboard_state_get(ev->win);
-
- if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
- clearClipboardHandler();
- else if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
- clipboard_window_opened_ = true;
}
-#endif
-// Copyright 2014 Samsung Electronics. All rights reseoved.
+// Copyright 2016 Samsung Electronics. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CLIPBOARD_HELPER_EFL_H_
#define CLIPBOARD_HELPER_EFL_H_
-#include <string>
-#include <Ecore.h>
-#include "ecore_x_wayland_wrapper.h"
+#include <Elementary.h>
-#include "base/memory/singleton.h"
-
-// This class is based on ClipboardHelper class in WK2/Tizen.
-// Coding Style has been changed as per Chromium coding style.
-
-// TODO: Get some documentation how this works with CBHM.
-// CBHM is an application/daemon running in Tizen device.
-// This helper class interacts with CBHM using Ecore/X message passing API.
-// There are a few magic strings in implementation.
-class EWebView;
-template <typename T> struct DefaultSingletonTraits;
-class ClipboardHelperEfl {
- public:
- enum ClipboardDataType {
- CLIPBOARD_DATA_TYPE_PLAIN_TEXT,
- CLIPBOARD_DATA_TYPE_URI_LIST,
- CLIPBOARD_DATA_TYPE_URL,
- CLIPBOARD_DATA_TYPE_MARKUP,
- CLIPBOARD_DATA_TYPE_IMAGE
- };
- static ClipboardHelperEfl* GetInstance();
-
- void SetData(const std::string& data, ClipboardDataType type);
- void Clear();
- static int NumberOfItems();
- bool RetrieveClipboardItem(int index, int* format, std::string* data);
- void OpenClipboardWindow(EWebView* view, bool richly_editable);
- void CloseClipboardWindow();
- bool IsClipboardWindowOpened();
- // TODO: Webview TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- bool getSelectedCbhmItem(Ecore_X_Atom* pDataType);
- void UpdateClipboardWindowState(Ecore_X_Event_Window_Property* ev);
-#endif
- static void connectClipboardWindow();
-
- private:
- ClipboardHelperEfl();
-
- ClipboardHelperEfl(const ClipboardHelperEfl&) = delete;
- ClipboardHelperEfl& operator=(const ClipboardHelperEfl&) = delete;
-
- friend struct base::DefaultSingletonTraits<ClipboardHelperEfl>;
-
- // TODO: Webview TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- Ecore_X_Window GetCbhmWindow();
-#endif
- bool SendCbhmMessage(const std::string& message);
- // TODO: Webview TG will implement following for Wayland.
-#if !defined(WAYLAND_BRINGUP)
- bool SetClipboardItem(Ecore_X_Atom data_type, const std::string& data);
- std::string GetCbhmReply(Ecore_X_Window xwin, Ecore_X_Atom property, Ecore_X_Atom* data_type);
+#if defined(USE_WAYLAND)
+#include "ui/base/clipboard/clipboard_helper_efl_wayland.h"
#else
- bool SetClipboardItem(const std::string& data_type, const std::string& data);
+#include "ui/base/clipboard/clipboard_helper_efl_X11.h"
#endif
- void clearClipboardHandler();
- void initializeAtomList();
- Ecore_Event_Handler* m_selectionClearHandler;
- Ecore_Event_Handler* m_selectionNotifyHandler;
- Ecore_Event_Handler* property_change_handler_;
- bool clipboard_window_opened_;
-};
+enum class ClipboardDataTypeEfl { PLAIN_TEXT, URI_LIST, URL, MARKUP, IMAGE };
+
+Elm_Sel_Format ClipboardFormatToElm(ClipboardDataTypeEfl type);
#endif /* CLIPBOARD_HELPER_EFL_H_ */
--- /dev/null
+// Copyright 2014 Samsung Electronics. All rights reseoved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "clipboard_helper_efl.h"
+
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include "ecore_x_wayland_wrapper.h"
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace {
+
+enum ClipType {
+ CLIP_TYPE_PRIMARY,
+ CLIP_TYPE_SECONDARY,
+ CLIP_TYPE_CLIPBOARD,
+ CLIP_TYPE_XDND,
+ CLIP_TYPE_MAX,
+};
+
+struct ClipData {
+ Ecore_X_Selection selection;
+ void (*request)(Ecore_X_Window window, const char* pTarget);
+ Elm_Sel_Format format;
+ Elm_Sel_Format requestedFormat;
+ int bufferLength;
+
+ ClipboardHelperEfl* clipboardHelper;
+
+ // TODO: Add proper delegate class for clipboard related functionality
+ // EWK needs.
+ EWebView* webView;
+};
+
+typedef int (*ClipNotifyHandler)(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData);
+
+enum {
+ ATOM_TARGETS = 0,
+ ATOM_ATOM,
+ ATOM_LISTING_ATOMS = ATOM_ATOM,
+ ATOM_TEXT_URI,
+ ATOM_TEXT_URILIST,
+ ATOM_TEXT_X_VCARD,
+ ATOM_IMAGE_PNG,
+ ATOM_IMAGE_JPEG,
+ ATOM_IMAGE_BMP,
+ ATOM_IMAGE_GIF,
+ ATOM_IMAGE_TIFF,
+ ATOM_IMAGE_SVG,
+ ATOM_IMAGE_XPM,
+ ATOM_IMAGE_TGA,
+ ATOM_IMAGE_PPM,
+ ATOM_XELM,
+ ATOM_TEXT_HTML_UTF8,
+ ATOM_TEXT_HTML,
+ ATOM_STRING_UTF8,
+ ATOM_STRING,
+ ATOM_TEXT,
+ ATOM_TEXT_PLAIN_UTF8,
+ ATOM_TEXT_PLAIN,
+ ATOM_FORMAT_NONE,
+ ATOM_MAX,
+};
+
+struct AtomData {
+ const char* pName;
+ Elm_Sel_Format formats;
+ ClipNotifyHandler notify;
+ Ecore_X_Atom atom;
+};
+
+AtomData atomList[ATOM_MAX];
+ClipData clipList[CLIP_TYPE_MAX];
+
+Eina_Bool propertyChangeCallback(void* data, int type, void* event) {
+ ClipboardHelperEfl* clipboardHelper = static_cast<ClipboardHelperEfl*>(data);
+ Ecore_X_Event_Window_Property* ev = (Ecore_X_Event_Window_Property*)event;
+
+ if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
+ clipboardHelper->UpdateClipboardWindowState(ev);
+
+ return EINA_TRUE;
+}
+
+const char kCbhmMessageHide[] = "cbhm_hide";
+const char kCbhmMessageSetItem[] = "SET_ITEM";
+const char kCbhmMessageShow0[] = "show0";
+const char kCbhmMessageShow1[] = "show1";
+
+const char kCbhmAtomClipboardCount[] = "CBHM_cCOUNT";
+const char kCbhmAtomElmMarkup[] = "application/x-elementary-markup";
+const char kCbhmAtomError[] = "CBHM_ERROR";
+const char kCbhmAtomItem[] = "CBHM_ITEM";
+const char kCbhmAtomMessage[] = "CBHM_MSG";
+const char kCbhmAtomTextHtml[] = "text/html;charset=utf-8";
+const char kCbhmAtomTextUriList[] = "text/uri-list";
+const char kCbhmAtomUTF8String[] = "UTF8_STRING";
+const char kCbhmAtomXWindow[] = "CBHM_XWIN";
+
+const int kDataUnitSize8 = 8;
+const int kDataUnitSize16 = 16;
+const int kDataUnitSize32 = 32;
+} // namespace
+
+ClipboardHelperEfl* ClipboardHelperEfl::GetInstance() {
+ return base::Singleton<ClipboardHelperEfl>::get();
+}
+
+ClipboardHelperEfl::ClipboardHelperEfl() {
+ m_selectionClearHandler = 0;
+ m_selectionNotifyHandler = 0;
+ property_change_handler_ = 0;
+ clipboard_window_opened_ = false;
+}
+
+void ClipboardHelperEfl::SetData(const std::string& data,
+ ClipboardDataTypeEfl type) {
+ Ecore_X_Atom data_type = 0;
+
+ switch (type) {
+ case ClipboardDataTypeEfl::PLAIN_TEXT:
+ case ClipboardDataTypeEfl::URI_LIST:
+ case ClipboardDataTypeEfl::URL:
+ data_type = ecore_x_atom_get(kCbhmAtomUTF8String);
+ break;
+ case ClipboardDataTypeEfl::IMAGE:
+ data_type = ecore_x_atom_get(kCbhmAtomTextUriList);
+ break;
+ case ClipboardDataTypeEfl::MARKUP:
+ data_type = ecore_x_atom_get(kCbhmAtomTextHtml);
+ default:
+ NOTIMPLEMENTED();
+ }
+ SetClipboardItem(data_type, data);
+}
+
+void ClipboardHelperEfl::Clear() {
+ NOTIMPLEMENTED();
+}
+
+Ecore_X_Window ClipboardHelperEfl::GetCbhmWindow() {
+ Ecore_X_Atom xAtomCbhm = ecore_x_atom_get(kCbhmAtomXWindow);
+ Ecore_X_Window xCbhmWin = 0;
+
+ unsigned char* buf = 0;
+ int property_size = 0;
+ int property_array_size = ecore_x_window_prop_property_get(
+ 0, xAtomCbhm, XA_WINDOW, 0, &buf, &property_size);
+
+ if (property_array_size && property_size)
+ memcpy(&xCbhmWin, buf, sizeof(Ecore_X_Window));
+
+ if (buf)
+ free(buf);
+
+ return xCbhmWin;
+}
+
+bool ClipboardHelperEfl::SendCbhmMessage(const std::string& message) {
+ Ecore_X_Window cbhm_win = GetCbhmWindow();
+ Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(kCbhmAtomMessage);
+
+ if (!cbhm_win || !atom_cbhm_item)
+ return false;
+ Ecore_X_Window xwin = ecore_x_window_focus_get();
+ XClientMessageEvent messageEvent;
+ memset(&messageEvent, 0, sizeof(messageEvent));
+ messageEvent.type = ClientMessage;
+ messageEvent.display = static_cast<Display*>(ecore_x_display_get());
+ messageEvent.window = xwin;
+ messageEvent.message_type = atom_cbhm_item;
+ messageEvent.format = 8; /* data should be viewed as byte */
+ snprintf(messageEvent.data.b, sizeof(messageEvent.data.b), "%s",
+ message.c_str());
+
+ XSendEvent(static_cast<Display*>(ecore_x_display_get()), cbhm_win, false,
+ NoEventMask, reinterpret_cast<XEvent*>(&messageEvent));
+
+ ecore_x_sync();
+
+ return true;
+}
+
+bool ClipboardHelperEfl::SetClipboardItem(Ecore_X_Atom data_type,
+ const std::string& data) {
+ if (data.empty())
+ return false;
+
+ Ecore_X_Window cbhm_win = GetCbhmWindow();
+ Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(kCbhmAtomItem);
+
+ size_t data_start_index = 0;
+ const char prefix[] = "file://";
+ if (data.compare(0, sizeof(prefix) - 1, prefix) == 0)
+ data_start_index = sizeof(prefix) - 1;
+
+ ecore_x_sync();
+ ecore_x_window_prop_property_set(
+ cbhm_win, atom_cbhm_item, data_type, 8,
+ const_cast<char*>(data.c_str()) + data_start_index,
+ data.length() - data_start_index + 1);
+ ecore_x_sync();
+
+ if (SendCbhmMessage(kCbhmMessageSetItem))
+ return true;
+
+ return false;
+}
+
+std::string ClipboardHelperEfl::GetCbhmReply(Ecore_X_Window xwin,
+ Ecore_X_Atom property,
+ Ecore_X_Atom* data_type) {
+ if (!property)
+ return std::string();
+
+ ecore_x_sync();
+
+ Ecore_X_Atom type;
+ int data_unit_size = 0;
+ long unsigned int data_length = 0;
+ long unsigned int bytes = 0;
+ unsigned char* data = 0;
+
+ int result = XGetWindowProperty(
+ static_cast<Display*>(ecore_x_display_get()), xwin, property, 0, LONG_MAX,
+ False, ecore_x_window_prop_any_type(), reinterpret_cast<Atom*>(&type),
+ &data_unit_size, &data_length, &bytes, &data);
+
+ if (result != Success)
+ return std::string();
+
+ if (!data_length) {
+ XFree(data);
+ return std::string();
+ }
+
+ std::string cbhm_data;
+
+ switch (data_unit_size) {
+ case kDataUnitSize8:
+ cbhm_data = std::string(reinterpret_cast<const char*>(data), data_length);
+ break;
+ case kDataUnitSize16:
+ cbhm_data = base::UTF16ToUTF8(
+ std::u16string(reinterpret_cast<const char16_t*>(data), data_length));
+ break;
+ case kDataUnitSize32:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ XFree(data);
+
+ if (data_type)
+ *data_type = type;
+
+ return cbhm_data;
+}
+
+bool ClipboardHelperEfl::RetrieveClipboardItem(int index,
+ Elm_Sel_Format* format,
+ std::string* data) {
+ if (!data)
+ return false;
+
+ Ecore_X_Window cbhm_win = GetCbhmWindow();
+ std::ostringstream cbhm_item;
+ cbhm_item << kCbhmAtomItem << index;
+
+ Ecore_X_Atom atom_cbhm_item = ecore_x_atom_get(cbhm_item.str().c_str());
+ Ecore_X_Atom atom_item_type = 0;
+
+ std::string result = GetCbhmReply(cbhm_win, atom_cbhm_item, &atom_item_type);
+ if (result.empty() || atom_item_type == ecore_x_atom_get(kCbhmAtomError))
+ return false;
+
+ // TODO: Other formats need to be added here.
+ if ((atom_item_type == ecore_x_atom_get(kCbhmAtomUTF8String)) ||
+ (atom_item_type == ecore_x_atom_get(kCbhmAtomElmMarkup))) {
+ *format = ELM_SEL_FORMAT_TEXT;
+ data->swap(result);
+ if (atom_item_type == ecore_x_atom_get(kCbhmAtomElmMarkup)) {
+ char* temp_text = evas_textblock_text_markup_to_utf8(NULL, data->c_str());
+ if (!temp_text) {
+ LOG(ERROR) << "evas_textblock_text_markup_to_utf8 failed - incorrect "
+ << "result from RetrieveClipboardItem";
+ return false;
+ }
+ *data = std::string(temp_text);
+ free(temp_text);
+ }
+ return true;
+ } else if (atom_item_type == ecore_x_atom_get(kCbhmAtomTextHtml)) {
+ *format = ELM_SEL_FORMAT_HTML;
+ data->swap(result);
+ return true;
+ }
+ return false;
+}
+
+int ClipboardHelperEfl::NumberOfItems() {
+ // 1. Get CBHM Ecore_X_Window.
+ Ecore_X_Atom x_atom;
+ x_atom = ecore_x_atom_get(kCbhmAtomXWindow);
+ if (!x_atom)
+ return 0;
+
+ unsigned char* data = 0;
+ int number_of_windows = 0;
+ int result = ecore_x_window_prop_property_get(0, x_atom, XA_WINDOW, 0, &data,
+ &number_of_windows);
+
+ Ecore_X_Window x_window = 0;
+ if (result && number_of_windows)
+ memcpy(&x_window, data, sizeof(Ecore_X_Window));
+
+ if (data)
+ free(data);
+
+ if (!x_window)
+ return 0;
+
+ ecore_x_sync();
+
+ // 2. Get number of clipboard items.
+ x_atom = ecore_x_atom_get(kCbhmAtomClipboardCount);
+ if (!x_atom)
+ return 0;
+
+ Display* display = static_cast<Display*>(ecore_x_display_get());
+
+ Ecore_X_Atom type;
+ int format;
+ long unsigned number_of_items = 0;
+ long unsigned bytes = 0;
+ unsigned char* data_in_format = 0;
+ result = XGetWindowProperty(display, x_window, x_atom, 0, LONG_MAX, False,
+ ecore_x_window_prop_any_type(),
+ reinterpret_cast<Atom*>(&type), &format,
+ &number_of_items, &bytes, &data_in_format);
+ if (result != Success)
+ return 0;
+
+ if (!number_of_items) {
+ XFree(data_in_format);
+ return 0;
+ }
+
+ if (!data_in_format)
+ return 0;
+
+ char* end;
+ errno = 0;
+ long int count =
+ strtol(reinterpret_cast<const char*>(data_in_format), &end, 10);
+ if ((end == reinterpret_cast<const char*>(data_in_format) ||
+ *end != '\0') /* not a number */
+ || ((count == LONG_MIN || count == LONG_MAX) &&
+ ERANGE == errno) /* out of range */) {
+ LOG(ERROR) << "String to int conversion failed.";
+ return 0;
+ }
+ return count;
+}
+
+static void pasteSelectedClipboardItem(std::string data,
+ std::string type,
+ EWebView* webview) {
+#if 0
+ content::SelectionControllerEfl* controller = webview->GetSelectionController();
+ if (controller)
+ controller->HideHandleAndContextMenu();
+
+ webview->ExecuteEditCommand(type.c_str(), data.c_str());
+ ClipboardHelperEfl::connectClipboardWindow();
+#endif
+}
+
+static Eina_Bool clearClip(void* data, int type, void* event) {
+ Ecore_X_Event_Selection_Clear* clearEvent =
+ (Ecore_X_Event_Selection_Clear*)event;
+ Ecore_X_Window window = clearEvent->win;
+
+ ClipType clipType = CLIP_TYPE_SECONDARY;
+ clipList[clipType].requestedFormat =
+ static_cast<Elm_Sel_Format>(ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_IMAGE);
+
+ ecore_x_selection_secondary_request(window, ECORE_X_SELECTION_TARGET_TARGETS);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool notifyClip(void* data, int type, void* event) {
+ EWebView* webview = static_cast<EWebView*>(data);
+ Ecore_X_Event_Selection_Notify* notifytEvent =
+ (Ecore_X_Event_Selection_Notify*)event;
+
+ int i = 0;
+ for (i = 0; i < CLIP_TYPE_MAX; i++) {
+ if (clipList[i].selection == notifytEvent->selection)
+ break;
+ }
+
+ ClipData* clipData = clipList + i;
+ clipData->webView = webview;
+ for (i = 0; i < ATOM_MAX; i++) {
+ if (!strcmp(notifytEvent->target, atomList[i].pName) && atomList[i].notify)
+ atomList[i].notify(clipData, notifytEvent);
+ }
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static int notifyTarget(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ Ecore_X_Atom dataType = 0;
+
+ if (clipData->clipboardHelper->getSelectedCbhmItem(&dataType)) {
+ const char* pHtmlAtomName = "text/html;charset=utf-8";
+ Ecore_X_Atom htmlType = ecore_x_atom_get(pHtmlAtomName);
+
+ if (dataType == htmlType) {
+ clipData->request(notifyData->win, pHtmlAtomName);
+ return ECORE_CALLBACK_PASS_ON;
+ }
+ }
+
+ Ecore_X_Selection_Data_Targets* pTargets =
+ (Ecore_X_Selection_Data_Targets*)(notifyData->data);
+ Ecore_X_Atom* pAtomList = (Ecore_X_Atom*)(pTargets->data.data);
+
+ int i, j = 0;
+ for (j = (ATOM_LISTING_ATOMS + 1); j < ATOM_MAX; j++) {
+ if (!(atomList[j].formats & clipData->requestedFormat))
+ continue;
+ for (i = 0; i < pTargets->data.length; i++) {
+ if ((atomList[j].atom == pAtomList[i]) && (atomList[j].notify)) {
+ if ((j == ATOM_XELM) &&
+ (!(clipData->requestedFormat & ELM_SEL_FORMAT_MARKUP)))
+ continue;
+ goto FOUND;
+ }
+ }
+ }
+
+ return ECORE_CALLBACK_PASS_ON;
+
+FOUND:
+ clipData->request(notifyData->win, atomList[j].pName);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static int notifyText(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
+ pasteSelectedClipboardItem(std::string((char*)pData->data), "InsertText",
+ clipData->webView);
+ return 0;
+}
+
+static int notifyImage(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ return 0;
+}
+
+static int notifyUri(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
+ pasteSelectedClipboardItem(
+ std::string(reinterpret_cast<char*>(pData->data), pData->length),
+ "InsertImage", clipData->webView);
+ return 0;
+}
+
+static int notifyEdje(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ return 0;
+}
+
+static int notifyHtml(ClipData* clipData,
+ Ecore_X_Event_Selection_Notify* notifyData) {
+ Ecore_X_Selection_Data* pData = (Ecore_X_Selection_Data*)notifyData->data;
+ pasteSelectedClipboardItem(
+ std::string(reinterpret_cast<char*>(pData->data), pData->length),
+ "InsertHTML", clipData->webView);
+ return 0;
+}
+
+void ClipboardHelperEfl::initializeAtomList() {
+ atomList[ATOM_TARGETS].pName = "TARGETS";
+ atomList[ATOM_TARGETS].formats = ELM_SEL_FORMAT_TARGETS;
+ atomList[ATOM_TARGETS].notify = notifyTarget;
+ atomList[ATOM_TARGETS].atom = 0;
+
+ atomList[ATOM_ATOM].pName = "ATOM";
+ atomList[ATOM_ATOM].formats = ELM_SEL_FORMAT_TARGETS;
+ atomList[ATOM_ATOM].notify = notifyTarget;
+ atomList[ATOM_ATOM].atom = 0;
+
+ atomList[ATOM_XELM].pName = "application/x-elementary-markup";
+ atomList[ATOM_XELM].formats = ELM_SEL_FORMAT_MARKUP;
+ atomList[ATOM_XELM].notify = notifyEdje;
+ atomList[ATOM_XELM].atom = 0;
+
+ atomList[ATOM_TEXT_URI].pName = "text/uri";
+ atomList[ATOM_TEXT_URI].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_TEXT_URI].notify = notifyUri;
+ atomList[ATOM_TEXT_URI].atom = 0;
+
+ atomList[ATOM_TEXT_URILIST].pName = "text/uri-list";
+ atomList[ATOM_TEXT_URILIST].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_TEXT_URILIST].notify = notifyUri;
+ atomList[ATOM_TEXT_URILIST].atom = 0;
+
+ atomList[ATOM_TEXT_X_VCARD].pName = "text/x-vcard";
+ atomList[ATOM_TEXT_X_VCARD].formats = ELM_SEL_FORMAT_VCARD;
+ atomList[ATOM_TEXT_X_VCARD].notify = 0;
+ atomList[ATOM_TEXT_X_VCARD].atom = 0;
+
+ atomList[ATOM_IMAGE_PNG].pName = "image/png";
+ atomList[ATOM_IMAGE_PNG].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_PNG].notify = notifyImage;
+ atomList[ATOM_IMAGE_PNG].atom = 0;
+
+ atomList[ATOM_IMAGE_JPEG].pName = "image/jpeg";
+ atomList[ATOM_IMAGE_JPEG].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_JPEG].notify = notifyImage;
+ atomList[ATOM_IMAGE_JPEG].atom = 0;
+
+ atomList[ATOM_IMAGE_BMP].pName = "image/x-ms-bmp";
+ atomList[ATOM_IMAGE_BMP].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_BMP].notify = notifyImage;
+ atomList[ATOM_IMAGE_BMP].atom = 0;
+
+ atomList[ATOM_IMAGE_GIF].pName = "image/gif";
+ atomList[ATOM_IMAGE_GIF].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_GIF].notify = notifyImage;
+ atomList[ATOM_IMAGE_GIF].atom = 0;
+
+ atomList[ATOM_IMAGE_TIFF].pName = "image/tiff";
+ atomList[ATOM_IMAGE_TIFF].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_TIFF].notify = notifyImage;
+ atomList[ATOM_IMAGE_TIFF].atom = 0;
+
+ atomList[ATOM_IMAGE_SVG].pName = "image/svg+xml";
+ atomList[ATOM_IMAGE_SVG].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_SVG].notify = notifyImage;
+ atomList[ATOM_IMAGE_SVG].atom = 0;
+
+ atomList[ATOM_IMAGE_XPM].pName = "image/x-xpixmap";
+ atomList[ATOM_IMAGE_XPM].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_XPM].notify = notifyImage;
+ atomList[ATOM_IMAGE_XPM].atom = 0;
+
+ atomList[ATOM_IMAGE_TGA].pName = "image/x-tga";
+ atomList[ATOM_IMAGE_TGA].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_TGA].notify = notifyImage;
+ atomList[ATOM_IMAGE_TGA].atom = 0;
+
+ atomList[ATOM_IMAGE_PPM].pName = "image/x-portable-pixmap";
+ atomList[ATOM_IMAGE_PPM].formats = ELM_SEL_FORMAT_IMAGE;
+ atomList[ATOM_IMAGE_PPM].notify = notifyImage;
+ atomList[ATOM_IMAGE_PPM].atom = 0;
+
+ atomList[ATOM_TEXT_HTML_UTF8].pName = "text/html;charset=utf-8";
+ atomList[ATOM_TEXT_HTML_UTF8].formats = ELM_SEL_FORMAT_HTML;
+ atomList[ATOM_TEXT_HTML_UTF8].notify = notifyHtml;
+ atomList[ATOM_TEXT_HTML_UTF8].atom = 0;
+
+ atomList[ATOM_TEXT_HTML].pName = "text/html";
+ atomList[ATOM_TEXT_HTML].formats = ELM_SEL_FORMAT_HTML;
+ atomList[ATOM_TEXT_HTML].notify = notifyHtml;
+ atomList[ATOM_TEXT_HTML].atom = 0;
+
+ atomList[ATOM_STRING_UTF8].pName = "UTF8_STRING";
+ atomList[ATOM_STRING_UTF8].formats = static_cast<Elm_Sel_Format>(
+ ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
+ atomList[ATOM_STRING_UTF8].notify = notifyText;
+ atomList[ATOM_STRING_UTF8].atom = 0;
+
+ atomList[ATOM_STRING].pName = "STRING";
+ atomList[ATOM_STRING].formats = static_cast<Elm_Sel_Format>(
+ ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
+ atomList[ATOM_STRING].notify = notifyText;
+ atomList[ATOM_STRING].atom = 0;
+
+ atomList[ATOM_TEXT].pName = "TEXT";
+ atomList[ATOM_TEXT].formats = static_cast<Elm_Sel_Format>(
+ ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
+ atomList[ATOM_TEXT].notify = 0;
+ atomList[ATOM_TEXT].atom = 0;
+
+ atomList[ATOM_TEXT_PLAIN_UTF8].pName = "text/plain;charset=utf-8";
+ atomList[ATOM_TEXT_PLAIN_UTF8].formats = static_cast<Elm_Sel_Format>(
+ ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
+ atomList[ATOM_TEXT_PLAIN_UTF8].notify = 0;
+ atomList[ATOM_TEXT_PLAIN_UTF8].atom = 0;
+
+ atomList[ATOM_TEXT_PLAIN].pName = "text/plain";
+ atomList[ATOM_TEXT_PLAIN].formats = static_cast<Elm_Sel_Format>(
+ ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML);
+ atomList[ATOM_TEXT_PLAIN].notify = notifyText;
+ atomList[ATOM_TEXT_PLAIN].atom = 0;
+
+ atomList[ATOM_FORMAT_NONE].pName = "NONE";
+ atomList[ATOM_FORMAT_NONE].formats = ELM_SEL_FORMAT_NONE;
+ atomList[ATOM_FORMAT_NONE].notify = notifyText;
+ atomList[ATOM_FORMAT_NONE].atom = 0;
+
+ clipList[CLIP_TYPE_PRIMARY].selection = ECORE_X_SELECTION_PRIMARY;
+ clipList[CLIP_TYPE_PRIMARY].request = ecore_x_selection_primary_request;
+ clipList[CLIP_TYPE_PRIMARY].bufferLength = 0;
+
+ clipList[CLIP_TYPE_SECONDARY].selection = ECORE_X_SELECTION_SECONDARY;
+ clipList[CLIP_TYPE_SECONDARY].request = ecore_x_selection_secondary_request;
+ clipList[CLIP_TYPE_SECONDARY].bufferLength = 0;
+
+ clipList[CLIP_TYPE_CLIPBOARD].selection = ECORE_X_SELECTION_CLIPBOARD;
+ clipList[CLIP_TYPE_CLIPBOARD].request = ecore_x_selection_clipboard_request;
+ clipList[CLIP_TYPE_CLIPBOARD].bufferLength = 0;
+
+ clipList[CLIP_TYPE_XDND].selection = ECORE_X_SELECTION_XDND;
+ clipList[CLIP_TYPE_XDND].request = ecore_x_selection_xdnd_request;
+ clipList[CLIP_TYPE_XDND].bufferLength = 0;
+
+ for (int i = 0; i < ATOM_MAX; i++)
+ atomList[i].atom = ecore_x_atom_get(atomList[i].pName);
+}
+
+void ClipboardHelperEfl::clearClipboardHandler() {
+ if (m_selectionClearHandler) {
+ ecore_event_handler_del(m_selectionClearHandler);
+ m_selectionClearHandler = 0;
+ }
+
+ if (m_selectionNotifyHandler) {
+ ecore_event_handler_del(m_selectionNotifyHandler);
+ m_selectionNotifyHandler = 0;
+ }
+
+ if (property_change_handler_) {
+ ecore_event_handler_del(property_change_handler_);
+ property_change_handler_ = 0;
+ }
+ clipboard_window_opened_ = false;
+}
+
+bool ClipboardHelperEfl::getSelectedCbhmItem(Ecore_X_Atom* pDataType) {
+ Ecore_X_Window cbhmWin = GetCbhmWindow();
+ Ecore_X_Atom atomCbhmItem = ecore_x_atom_get("CBHM_SELECTED_ITEM");
+ Ecore_X_Atom atomItemType = 0;
+
+ std::string result = GetCbhmReply(cbhmWin, atomCbhmItem, &atomItemType);
+
+ if (result.empty())
+ return false;
+
+ if (atomItemType == ecore_x_atom_get("CBHM_ERROR"))
+ return false;
+
+ if (pDataType)
+ *pDataType = atomItemType;
+
+ return true;
+}
+
+void ClipboardHelperEfl::OpenClipboardWindow(EWebView* view,
+ bool richly_editable) {
+ clearClipboardHandler();
+ initializeAtomList();
+ property_change_handler_ = ecore_event_handler_add(
+ ECORE_X_EVENT_WINDOW_PROPERTY, propertyChangeCallback, this);
+ m_selectionClearHandler =
+ ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, clearClip, view);
+ m_selectionNotifyHandler =
+ ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, notifyClip, view);
+
+ if (richly_editable)
+ SendCbhmMessage(kCbhmMessageShow1);
+ else
+ SendCbhmMessage(kCbhmMessageShow0);
+
+ connectClipboardWindow();
+#if 0
+ view->SmartCallback<EWebViewCallbacks::ClipboardOpened>().call(0);
+#endif
+}
+
+void ClipboardHelperEfl::connectClipboardWindow() {
+ ecore_x_selection_secondary_set(ecore_x_window_focus_get(), "", 1);
+}
+
+bool ClipboardHelperEfl::IsClipboardWindowOpened() {
+ return clipboard_window_opened_;
+}
+
+void ClipboardHelperEfl::CloseClipboardWindow() {
+ SendCbhmMessage(kCbhmMessageHide);
+}
+
+void ClipboardHelperEfl::UpdateClipboardWindowState(
+ Ecore_X_Event_Window_Property* ev) {
+ Ecore_X_Illume_Clipboard_State state =
+ ecore_x_e_illume_clipboard_state_get(ev->win);
+
+ if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
+ clearClipboardHandler();
+ else if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
+ clipboard_window_opened_ = true;
+}
+
+bool ClipboardHelperEfl::IsFormatAvailable(
+ const ui::ClipboardFormatType& format) {
+ int count = NumberOfItems();
+
+ Elm_Sel_Format type = ELM_SEL_FORMAT_NONE;
+ std::string clipboard_data;
+
+ for (int i = 0; i < count; i++) {
+ bool ret = RetrieveClipboardItem(i, &type, &clipboard_data);
+ if (!ret)
+ continue;
+
+ switch (type) {
+ case ELM_SEL_FORMAT_TEXT:
+ if (ui::ClipboardFormatType::PlainTextType() == format)
+ return true;
+ break;
+ case ELM_SEL_FORMAT_HTML:
+ if (ui::ClipboardFormatType::HtmlType() == format)
+ return true;
+ break;
+ case ELM_SEL_FORMAT_IMAGE:
+ if (ui::ClipboardFormatType::BitmapType() == format)
+ return true;
+ break;
+ // If we support more ELM formats, we shall add it here.
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool ClipboardHelperEfl::RetrieveClipboardItem(std::string* result,
+ ClipboardDataTypeEfl format) {
+ int count = NumberOfItems();
+
+ Elm_Sel_Format elm_format = ELM_SEL_FORMAT_NONE;
+ Elm_Sel_Format desired_format(ClipboardFormatToElm(format));
+
+ for (int i = 0; i < count; i++) {
+ std::string clipboard_data;
+ if (!RetrieveClipboardItem(i, &elm_format, &clipboard_data))
+ continue;
+
+ if (elm_format == desired_format) {
+ *result = clipboard_data;
+ return true;
+ }
+ }
+ return false;
+}
--- /dev/null
+// Copyright 2014 Samsung Electronics. All rights reseoved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CLIPBOARD_HELPER_EFL_X11_H_
+#define CLIPBOARD_HELPER_EFL_X11_H_
+
+#include <Ecore.h>
+#include <Elementary.h>
+#include <string>
+#include "ecore_x_wayland_wrapper.h"
+
+#include "base/component_export.h"
+#include "base/memory/singleton.h"
+#include "ui/base/clipboard/clipboard.h"
+
+// This class is based on ClipboardHelper class in WK2/Tizen.
+// Coding Style has been changed as per Chromium coding style.
+
+// TODO: Get some documentation how this works with CBHM.
+// CBHM is an application/daemon running in Tizen device.
+// This helper class interacts with CBHM using Ecore/X message passing API.
+// There are a few magic strings in implementation.
+class EWebView;
+enum class ClipboardDataTypeEfl;
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+class COMPONENT_EXPORT(UI_BASE) ClipboardHelperEfl {
+ public:
+ static ClipboardHelperEfl* GetInstance();
+
+ void SetData(const std::string& data, ClipboardDataTypeEfl type);
+ void Clear();
+ static int NumberOfItems();
+ bool CanPasteFromSystemClipboard() {
+ return ClipboardHelperEfl::NumberOfItems() > 0;
+ }
+ bool CanPasteFromClipboardApp() {
+ return ClipboardHelperEfl::NumberOfItems() > 0;
+ }
+ bool IsFormatAvailable(const ui::ClipboardFormatType& format);
+ bool RetrieveClipboardItem(std::string* result, ClipboardDataTypeEfl format);
+ void OpenClipboardWindow(EWebView* view, bool richly_editable);
+ void CloseClipboardWindow();
+ bool IsClipboardWindowOpened();
+ bool getSelectedCbhmItem(Ecore_X_Atom* pDataType);
+ void UpdateClipboardWindowState(Ecore_X_Event_Window_Property* ev);
+ static void connectClipboardWindow();
+
+ private:
+ ClipboardHelperEfl();
+ ClipboardHelperEfl(const ClipboardHelperEfl&) = delete;
+ ClipboardHelperEfl& operator=(const ClipboardHelperEfl&) = delete;
+ friend struct base::DefaultSingletonTraits<ClipboardHelperEfl>;
+
+ Ecore_X_Window GetCbhmWindow();
+ bool SendCbhmMessage(const std::string& message);
+ bool SetClipboardItem(Ecore_X_Atom data_type, const std::string& data);
+ std::string GetCbhmReply(Ecore_X_Window xwin,
+ Ecore_X_Atom property,
+ Ecore_X_Atom* data_type);
+ void clearClipboardHandler();
+ void initializeAtomList();
+ bool RetrieveClipboardItem(int index,
+ Elm_Sel_Format* format,
+ std::string* data);
+
+ Ecore_Event_Handler* m_selectionClearHandler;
+ Ecore_Event_Handler* m_selectionNotifyHandler;
+ Ecore_Event_Handler* property_change_handler_;
+ bool clipboard_window_opened_;
+};
+
+#endif /* CLIPBOARD_HELPER_EFL_X11_H_ */
--- /dev/null
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "clipboard_helper_efl.h"
+
+#include <Ecore_Wl2.h>
+
+#include "base/base64.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/strings/escape.h"
+#include "chromium_impl/build/tizen_version.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "tizen/system_info.h"
+
+namespace {
+const char* const kCbhmDBusObjpath = "/org/tizen/cbhm/dbus";
+const char* const kCbhmDbusInterface = "org.tizen.cbhm.dbus";
+const std::string kFileScheme("file://");
+const std::string kHTMLImageFromClipboardAppFront("<img src=\"file://");
+const std::string::size_type kHTMLImageFromClipboardAppFrontLength =
+ kHTMLImageFromClipboardAppFront.length();
+const std::string kHTMLImageFromClipboardAppEnd("\">");
+const std::string kDataURIImagePrefix("<img alt=\"\" src=\"data:image;base64,");
+const std::string kDataURIImageSuffix("\">");
+} // namespace
+
+ClipboardHelperEfl* ClipboardHelperEfl::GetInstance() {
+ return base::Singleton<ClipboardHelperEfl>::get();
+}
+
+ClipboardHelperEfl::ClipboardHelperEfl() {
+ CbhmEldbusInit();
+}
+
+ClipboardHelperEfl::~ClipboardHelperEfl() {
+ CbhmEldbusDeinit();
+}
+
+bool ClipboardHelperEfl::IsFormatAvailable(
+ const ui::ClipboardFormatType& format) const {
+ // Poor man's format check.
+ std::string format_text(format.ToString());
+ if (format_text.find("text/plain") != std::string::npos) {
+ return !clipboard_text().empty();
+ } else if (format_text.find("text/html") != std::string::npos) {
+ return !clipboard_html().empty();
+ }
+ return false;
+}
+
+void ClipboardHelperEfl::SetData(const std::string& data,
+ ClipboardDataTypeEfl type) {
+ if (!source_widget_) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::SetData "
+ "elm_cnp_selection_set with NULL widget";
+ return;
+ }
+
+ Elm_Sel_Format data_format = ClipboardFormatToElm(type);
+
+ if (data.length() > 204800) {
+ // EFL silently truncates data passed through clipboard at 204800 bytes.
+ // See: http://suprem.sec.samsung.net/jira/browse/TSAM-12220
+ LOG(WARNING) << "[CLIPBOARD] EFL silently truncates clipboard "
+ "data over 204800 bytes - length of data: "
+ << data.length();
+ }
+ // TODO(g.ludwikowsk): change if-else to a switch
+ if (data_format == ELM_SEL_FORMAT_TEXT) {
+ clipboard_contents_ = base::EscapeForHTML(data);
+ // Clear clipboard_contents_html_ to avoid using stale value. Html will
+ // be set in next call to SetData (if at all).
+ clipboard_contents_html_.clear();
+ // Using ELM_SEL_FORMAT_TEXT in elm_cnp_selection_set in this case causes
+ // strange effect, that html data is overriden in clipboard app. Workaround
+ // is to use ELM_SEL_FORMAT_HTML even for text (which should be a valid
+ // html anyway).
+ // TODO: investigate this problem and create a bug
+ elm_cnp_selection_set(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_TEXT, clipboard_contents_.c_str(),
+ clipboard_contents_.length());
+ } else if (data_format == ELM_SEL_FORMAT_HTML) {
+ // TODO: ELM_SEL_FORMAT_HTML doesn't work properly on the latest platform,
+ // plus when we call elm_cnp_selection_set twice, it doesn't work.
+ // In order to support plain text properly, temporarily block the below.
+#if !defined(EWK_BRINGUP)
+ clipboard_contents_html_ = data;
+ elm_cnp_selection_set(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_HTML, clipboard_contents_html_.c_str(),
+ clipboard_contents_html_.length());
+#endif
+ } else if (data_format == ELM_SEL_FORMAT_IMAGE) {
+ // Image is downloaded by engine and we get local file path here.
+ // TODO(g.ludwikowsk): investigate if it is better to just get image html
+ // and let clipboard app handle the downloading.
+ std::string base64_img_tag;
+ if (Base64ImageTagFromImagePath(data, &base64_img_tag))
+ clipboard_contents_html_ = base64_img_tag;
+ else
+ LOG(ERROR) << "[CLIPBOARD] ConvertImgTagToBase64 failed";
+ // Clipboard service doesn't work unless we pass image paths as a file URL.
+ // This behavior is not documented anywhere.
+ // See: https://review.tizen.org/gerrit/#/c/86582/
+ std::string file_uri = kFileScheme + data;
+ elm_cnp_selection_set(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_IMAGE, file_uri.c_str(),
+ file_uri.length());
+ } else {
+ LOG(ERROR)
+ << "[CLIPBOARD] ClipboardHelperEfl::SetData unsupported data type "
+ << data_format;
+ }
+}
+
+void ClipboardHelperEfl::Clear() {
+ if (!source_widget_) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::Clear "
+ "elm_cnp_selection_set with NULL widget";
+ return;
+ }
+ elm_cnp_selection_set(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_TEXT, nullptr, 0);
+}
+
+bool ClipboardHelperEfl::Base64ImageTagFromImagePath(const std::string& path,
+ std::string* image_html) {
+ std::string file_contents;
+ if (!base::ReadFileToString(base::FilePath(path), &file_contents)) {
+ LOG(ERROR) << "[CLIPBOARD] couldn't read file: " << path;
+ return false;
+ }
+
+ base::Base64Encode(file_contents, &file_contents);
+
+ *image_html = kDataURIImagePrefix;
+ *image_html += file_contents;
+ *image_html += kDataURIImageSuffix;
+ return true;
+}
+
+// We get images from clipboard app as <img> tags with local path ("file://"
+// scheme), but we can't paste them in http and https pages (browsers block
+// this for security reasons). To work around this limitation we convert local
+// images to base64 encoded data URI.
+bool ClipboardHelperEfl::ConvertImgTagToBase64(const std::string& tag,
+ std::string* out_tag) {
+ std::string::size_type front_pos = tag.find(kHTMLImageFromClipboardAppFront);
+ if (front_pos == std::string::npos) {
+ LOG(ERROR) << "[CLIPBOARD] couldn't find "
+ << kHTMLImageFromClipboardAppFront
+ << " in html from clipboard app: " << tag;
+ return false;
+ }
+
+ std::string front_stripped =
+ tag.substr(front_pos + kHTMLImageFromClipboardAppFrontLength);
+ std::string::size_type back_pos =
+ front_stripped.find(kHTMLImageFromClipboardAppEnd);
+ if (back_pos == std::string::npos) {
+ LOG(ERROR) << "[CLIPBOARD] couldn't find " << kHTMLImageFromClipboardAppEnd
+ << " in html from clipboard app: " << front_stripped;
+ return false;
+ }
+
+ std::string image_path = front_stripped.substr(0, back_pos);
+ return Base64ImageTagFromImagePath(image_path, out_tag);
+}
+
+void ClipboardHelperEfl::GetClipboardTextPost(ClipboardHelperEfl* self) {
+ if (!elm_cnp_selection_get(self->source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_TEXT, SelectionGetCbText, self))
+ LOG(ERROR)
+ << "[CLIPBOARD] GetClipboardTextPost elm_cnp_selection_get failed";
+}
+
+bool ClipboardHelperEfl::RetrieveClipboardItem(
+ std::string* data,
+ ClipboardDataTypeEfl format) const {
+ // elm_cnp_selection_get is async, so no point in calling it here. We have
+ // to do polling or call it on some specific moments, like being focused.
+ Elm_Sel_Format elm_format = ClipboardFormatToElm(format);
+ if (elm_format == ELM_SEL_FORMAT_TEXT) {
+ *data = clipboard_text();
+ return true;
+ } else if (elm_format == ELM_SEL_FORMAT_HTML) {
+ *data = clipboard_html();
+ return true;
+ }
+
+ LOG(ERROR) << "[CLIPBOARD] Unexpected selection data format: "
+ << static_cast<int>(elm_format);
+ return false;
+}
+
+bool ClipboardHelperEfl::CanPasteFromClipboardApp() const {
+#if BUILDFLAG(IS_TIZEN_TV)
+ return false;
+#else
+ return CbhmNumberOfItems() > 0;
+#endif
+}
+
+void ClipboardHelperEfl::RefreshClipboard() {
+ if (!source_widget_) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::RefreshClipboard "
+ "elm_cnp_selection_get with NULL widget";
+ return;
+ }
+
+ paste_from_clipboard_app_ = false;
+
+ // We need to get both html and plain text from clipboard.
+ // elm_cnp_selection_get doesn't allow requesting both types on the same time
+ // and doesn't support multiple calls at once - we get only one callback
+ // anyway. If elm_cnp_selection_get succeeds for ELM_SEL_FORMAT_HTML, we
+ // call elm_cnp_selection_get for ELM_SEL_FORMAT_TEXT when callback returns.
+ //
+ // elm_cnp_selection_get failing for ELM_SEL_FORMAT_HTML is normal operation
+ // if html is not available. In such case we request ELM_SEL_FORMAT_TEXT
+ // immediately.
+ if (elm_cnp_selection_get(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_HTML, SelectionGetCbHTML, this))
+ return;
+
+ // Avoid using stale clipboard_contents_html_ value. elm_cnp_selection_get
+ // failed for ELM_SEL_FORMAT_HTML, so there is no html data in clipboard.
+ clipboard_contents_html_.clear();
+ if (!elm_cnp_selection_get(source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_TEXT, SelectionGetCbText, this))
+ LOG(INFO) << "[CLIPBOARD] elm_cnp_selection_get in RefreshClipboard failed"
+ << " for both HTML and TEXT";
+}
+
+Eina_Bool ClipboardHelperEfl::SelectionGetCbHTML(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev) {
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+
+ if (!ev->data) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::SelectionGetCbHTML no data";
+ return EINA_TRUE;
+ }
+
+ // We request text from clipboard app, but ev->format is
+ // ELM_SEL_FORMAT_MARKUP. Data looks like text so whatever.
+ if (!(ev->format == ELM_SEL_FORMAT_TEXT ||
+ ev->format == ELM_SEL_FORMAT_MARKUP)) {
+ // TODO(g.ludwikowsk): Support other data types
+ LOG(ERROR) << "[CLIPBOARD] Unexpected selection data format: "
+ << ev->format;
+ return ECORE_CALLBACK_PASS_ON;
+ }
+
+ // Convert ev->data to std::string, because it might not be
+ // a null terminated c-string.
+ std::string selection_data(static_cast<char*>(ev->data), ev->len);
+
+ // Process HTML, because we get images from clipboard app as lone <img> tag
+ // with local file path, which can't be used in normal web pages.
+ // See comment in ::ConvertImgTagToBase64
+ std::string img_tag;
+ if (ConvertImgTagToBase64(selection_data, &img_tag)) {
+ self->clipboard_contents_html_ = img_tag;
+ } else {
+ self->clipboard_contents_html_ = selection_data;
+ // We received html from clipboard app, but we also want plain text version
+ // of the selection. See comment in ::RefreshClipboard why we do it here.
+ // Also we have to post it on UI thread, because ::SelectionGetCbHTML is
+ // running as elm_cnp_selection_get callback, so we can't call
+ // elm_cnp_selection_get from inside.
+ // TODO(g.ludwikowsk): should we also get text for images?
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindRepeating(GetClipboardTextPost, self));
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool ClipboardHelperEfl::SelectionGetCbText(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev) {
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+
+ if (!ev->data) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::SelectionGetCbText no data";
+ return EINA_TRUE;
+ }
+
+ // Convert ev->data to std::string, because it might not be
+ // a null terminated c-string.
+ std::string selection_data(static_cast<char*>(ev->data), ev->len);
+
+ self->clipboard_contents_ = selection_data;
+ return EINA_TRUE;
+}
+
+void ClipboardHelperEfl::OnWebviewFocusIn(
+ EWebView* webview,
+ Evas_Object* source,
+ bool is_content_editable,
+ ExecCommandCallback exec_command_callback) {
+ source_widget_ = source;
+ last_webview_ = webview;
+ // Normally we are notified about change in contentEditable status of focused
+ // node by RenderWidgetHostViewEfl through ::SetContentEditable when focused
+ // node changes. But there is another way in which contentEditable status can
+ // change for us - if user switches to another tab in browser we won't get
+ // information from RWHVEfl since from its point of view the focused node
+ // didn't change. That is why also EWebView informs us when it gains focus.
+ is_content_editable_ = is_content_editable;
+ exec_command_callback_ = exec_command_callback;
+ accept_clipboard_app_events_ = true;
+ RefreshClipboard();
+}
+
+void ClipboardHelperEfl::MaybeInvalidateActiveWebview(EWebView* webview) {
+ if (last_webview_ == webview) {
+ CloseClipboardWindow();
+ accept_clipboard_app_events_ = false;
+ last_webview_ = nullptr;
+ exec_command_callback_.Reset();
+ }
+}
+
+void ClipboardHelperEfl::OnClipboardItemClicked(void* data,
+ const Eldbus_Message* /*msg*/) {
+ // ::OnClipboardItemClicked calls elm_cnp_selection_get (async), which
+ // calls us back when clipboard data is ready. We save this data and ask the
+ // engine to perform "paste" execCommand (also async), which calls us back
+ // for the data saved before. When waiting for these asynchronous calls we
+ // might get a second "ItemClicked" and ::OnClipboardItemClicked, which can
+ // have surprising results.
+ //
+ // elm_cnp_selection_get API has a habit of ignoring consecutive requests,
+ // so second "ItemClicked" might be ignored. Otherwise the result might be
+ // pasting the same content twice, despite that the user clicked different
+ // items in clipboard app, because it only keeps track of the latest clicked
+ // item.
+ //
+ // It is also a possibility that this might be a non-issue, because the
+ // phenomenon is limited by user interaction speed.
+ //
+ // TODO(g.ludwikowsk): investigate if we should add a queue of clipboard app
+ // paste requests, or a way to ignore other requests before the first one is
+ // completed, or if it is ok to do nothing.
+
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+
+ if (!self->source_widget_) {
+ LOG(ERROR) << "[CLIPBOARD] ClipboardHelperEfl::OnClipboardItemClicked "
+ "elm_cnp_selection_get with NULL widget";
+ return;
+ }
+ // We get clipboard's "ItemClicked" signal also when we are suspended
+ // and clipboard is being used in other applications, or when we are
+ // unfocused and browser UI is the target of clipboard app.
+ //
+ // Ignore events if webview is not focused.
+ if (!self->accept_clipboard_app_events_) {
+ LOG(INFO) << "[CLIPBOARD] OnClipboardItemClicked not focused - not "
+ "accepting clipboard app_events";
+ return;
+ }
+
+ if (self->is_content_editable_) {
+ if (elm_cnp_selection_get(self->source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_HTML, SelectionGetCbAppHTML, self))
+ return;
+ // elm_cnp_selection_get failing for ELM_SEL_FORMAT_HTML is normal
+ // operation if html is not available. In such case we request
+ // ELM_SEL_FORMAT_TEXT.
+ }
+
+ // Avoid using stale clipboard_contents_html_from_clipboard_app_ value.
+ // elm_cnp_selection_get failed for ELM_SEL_FORMAT_HTML, so there is no html
+ // data in clipboard.
+ self->clipboard_contents_html_from_clipboard_app_.clear();
+
+ if (!elm_cnp_selection_get(self->source_widget_, ELM_SEL_TYPE_CLIPBOARD,
+ ELM_SEL_FORMAT_TEXT, SelectionGetCbAppText, self))
+ LOG(INFO) << "[CLIPBOARD] elm_cnp_selection_get in OnClipboardItemClicked "
+ << "failed for both HTML and TEXT";
+}
+
+void ClipboardHelperEfl::ProcessClipboardAppEvent(Elm_Selection_Data* ev,
+ Elm_Sel_Format format) {
+ if (!ev->data) {
+ LOG(ERROR)
+ << "[CLIPBOARD] ClipboardHelperEfl::ProcessClipboardAppEvent no data";
+ return;
+ }
+
+ if (exec_command_callback_.is_null()) {
+ LOG(ERROR) << "[CLIPBOARD] exec_command_callback not set, but received "
+ "event from clipboard app";
+ return;
+ }
+
+ // Convert ev->data to std::string, because it might not be
+ // a null terminated c-string.
+ std::string selection_data(static_cast<char*>(ev->data), ev->len);
+
+ if (format == ELM_SEL_FORMAT_TEXT) {
+ clipboard_contents_from_clipboard_app_ = selection_data;
+ } else {
+ std::string img_tag;
+ if (ConvertImgTagToBase64(selection_data, &img_tag)) {
+ clipboard_contents_html_from_clipboard_app_ = img_tag;
+ } else {
+ clipboard_contents_html_from_clipboard_app_ = selection_data;
+ }
+ }
+ paste_from_clipboard_app_ = true;
+ exec_command_callback_.Run("paste", nullptr);
+ // Do not reset callback here, there might be multiple consecutive
+ // items clicked in Clipboard app. Also do not override
+ // clipboard_contents_ here (behavior from Tizen 2.4).
+}
+
+Eina_Bool ClipboardHelperEfl::SelectionGetCbAppHTML(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev) {
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+ self->ProcessClipboardAppEvent(ev, ELM_SEL_FORMAT_HTML);
+ return EINA_TRUE;
+}
+
+Eina_Bool ClipboardHelperEfl::SelectionGetCbAppText(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev) {
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+ self->ProcessClipboardAppEvent(ev, ELM_SEL_FORMAT_TEXT);
+ return EINA_TRUE;
+}
+
+void ClipboardHelperEfl::OpenClipboardWindow(EWebView* /*webview*/,
+ bool /*richly_editable*/) {
+ // cbhm-service is only available on mobile profile include DA product.
+ if (!IsMobileProfile())
+ return;
+
+ // Here we want to show clipboard app window, but only appropraite class
+ // of items should be enabled in it. We have to either pass "0" or "1" as
+ // string argument in the message - these values are documented in clipboard
+ // porting guide, which is not available to general public:
+ // "0" - text
+ // "1" - text and images
+ //
+ // See related code in cbhmd_eldbus.c _cbhmd_eldbus_show at:
+ // https://review.tizen.org/gerrit/gitweb?p=profile/mobile/platform/core/uifw/cbhm.git;a=blob;f=daemon/cbhmd_eldbus.c;h=ddb3760efac3d89fbe8e365157b613a536add768;hb=5b6f56e8be1ca50c4d3a03a2bf0edbc6c63294db#l135
+ // TODO: replace string literals with constants
+ if (is_content_editable_) {
+ eldbus_proxy_call(eldbus_proxy_, "CbhmShow", nullptr, nullptr, -1, "s",
+ "1");
+ } else {
+ eldbus_proxy_call(eldbus_proxy_, "CbhmShow", nullptr, nullptr, -1, "s",
+ "0");
+ }
+
+ // TODO(g.ludwikowsk): investigate "clipboard,opened" callback for both
+ // X11 and wayland
+ // view->SmartCallback<EWebViewCallbacks::ClipboardOpened>().call(0);
+}
+
+void ClipboardHelperEfl::CloseClipboardWindow() {
+ // cbhm-service is only available on mobile profile include DA product.
+ if (!IsMobileProfile())
+ return;
+
+ eldbus_proxy_call(eldbus_proxy_, "CbhmHide", nullptr, nullptr, -1, "");
+}
+
+void ClipboardHelperEfl::CbhmOnNameOwnerChanged(void* data,
+ const char* /*bus*/,
+ const char* /*old_id*/,
+ const char* /*new_id*/) {
+ // Clipboard porting guide advises to register on owner name changed callback
+ // for cbhm_conn_ to somehow use this to track clipboard's opened/closed
+ // state. Currently this is called only once when connecting to clipboard
+ // app, so it won't work.
+ auto self = static_cast<ClipboardHelperEfl*>(data);
+ self->clipboard_window_opened_ = !self->clipboard_window_opened_;
+}
+
+void ClipboardHelperEfl::CbhmEldbusInit() {
+ // cbhm-service is only available on mobile profile include DA product.
+ if (!IsMobileProfile())
+ return;
+
+ cbhm_conn_ = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+ Eldbus_Object* eldbus_obj =
+ eldbus_object_get(cbhm_conn_, kCbhmDbusInterface, kCbhmDBusObjpath);
+ eldbus_proxy_ = eldbus_proxy_get(eldbus_obj, kCbhmDbusInterface);
+ eldbus_name_owner_changed_callback_add(
+ cbhm_conn_, kCbhmDbusInterface,
+ ClipboardHelperEfl::CbhmOnNameOwnerChanged, this, EINA_TRUE);
+ eldbus_proxy_signal_handler_add(eldbus_proxy_, "ItemClicked",
+ ClipboardHelperEfl::OnClipboardItemClicked,
+ this);
+}
+
+void ClipboardHelperEfl::CbhmEldbusDeinit() {
+ // cbhm-service is only available on mobile profile include DA product.
+ if (!IsMobileProfile())
+ return;
+
+ if (cbhm_conn_)
+ eldbus_connection_unref(cbhm_conn_);
+}
+
+int ClipboardHelperEfl::CbhmNumberOfItems() const {
+ // cbhm-service is only available on mobile profile include DA product.
+ if (!IsMobileProfile())
+ return -1;
+
+ Eldbus_Message* req;
+ if (!(req = eldbus_proxy_method_call_new(eldbus_proxy_, "CbhmGetCount"))) {
+ LOG(ERROR) << "[CLIPBOARD] eldbus_proxy_method_call_new failed calling "
+ "\"CbhmGetCount\"";
+ return -1;
+ }
+
+ // Here we ask clipboard app about number of elements it contains, but we
+ // have to specify which type of elements we want to count. We have to use
+ // either 1 or 2 as integer argument in the message, but these values are not
+ // documented anywhere - they can change at any time:
+ // 1 - text
+ // 2 - text and images
+ //
+ // See cbhmd_eldbus.c: https://review.tizen.org/gerrit/#/c/90102/
+ int atom_index = is_content_editable_ ? 2 : 1;
+
+ if (!eldbus_message_arguments_append(req, "i", atom_index)) {
+ LOG(ERROR) << "[CLIPBOARD] eldbus_message_arguments_append failed calling "
+ "\"CbhmGetCount\"";
+ eldbus_message_unref(req);
+ return -1;
+ }
+
+ Eldbus_Message* reply;
+ if (!(reply = eldbus_proxy_send_and_block(eldbus_proxy_, req, -1))) {
+ LOG(ERROR) << "[CLIPBOARD] eldbus_proxy_send_and_block failed calling "
+ "\"CbhmGetCount\"";
+ return -1;
+ }
+ const char* errname = nullptr;
+ const char* errmsg = nullptr;
+ if (eldbus_message_error_get(reply, &errname, &errmsg)) {
+ LOG(ERROR) << "[CLIPBOARD] eldbus_proxy_send_and_block failed calling "
+ "\"CbhmGetCount\" with error "
+ << errname << ": " << errmsg;
+ eldbus_message_unref(reply);
+ return -1;
+ }
+
+ int count;
+ if (!eldbus_message_arguments_get(reply, "i", &count)) {
+ LOG(ERROR) << "[CLIPBOARD] eldbus_message_arguments_get failed when trying "
+ "to get clipboard item count";
+ eldbus_message_unref(reply);
+ return -1;
+ }
+
+ eldbus_message_unref(reply);
+ return count;
+}
--- /dev/null
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CLIPBOARD_HELPER_EFL_WAYLAND_H_
+#define CLIPBOARD_HELPER_EFL_WAYLAND_H_
+
+#include <Eldbus.h>
+#include <Elementary.h>
+#include <string>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/memory/singleton.h"
+#include "ui/base/clipboard/clipboard.h"
+
+enum class ClipboardDataTypeEfl;
+class EWebView;
+
+class COMPONENT_EXPORT(UI_BASE) ClipboardHelperEfl {
+ public:
+ using ExecCommandCallback =
+ base::RepeatingCallback<void(const char*, const char*)>;
+ static ClipboardHelperEfl* GetInstance();
+ void SetData(const std::string& data, ClipboardDataTypeEfl type);
+ void Clear();
+ bool CanPasteFromClipboardApp() const;
+ bool CanPasteFromSystemClipboard() const {
+ // FIXME(g.ludwikowsk): for now it is the same as CanPasteFromClipboardApp,
+ // but we should also take into account that if there are only images in
+ // clipboard and we are in a text input then we can't paste, but can show
+ // clipboard window (like in tizen 2.4)
+ return CanPasteFromClipboardApp();
+ }
+ bool IsFormatAvailable(const ui::ClipboardFormatType& format) const;
+ void RefreshClipboard();
+ bool RetrieveClipboardItem(std::string* data,
+ ClipboardDataTypeEfl format) const;
+
+ // OnWebviewFocusIn needs a callback to EWebView's ExecuteEditCommand
+ // function, because we can't include eweb_view.h header in chromium_impl
+ // directory to call ExecuteEditCommand directly.
+ // We also keep a pointer to EWebView instance associated with the callback,
+ // to know if we should reset exec_commnad_callback_ when that EWebView is
+ // destroyed.
+ void OnWebviewFocusIn(EWebView* webview,
+ Evas_Object* source,
+ bool is_content_editable,
+ ExecCommandCallback exec_command_callback);
+ void MaybeInvalidateActiveWebview(EWebView* webview);
+ void OpenClipboardWindow(EWebView* webview, bool richly_editable);
+ void CloseClipboardWindow();
+ bool IsClipboardWindowOpened() const {
+ // FIXME(g.ludwikowsk): This doesn't work currently, see comment in
+ // ::CbhmOnNameOwnerChanged
+ return clipboard_window_opened_;
+ }
+ void SetContentEditable(bool is_content_editable) {
+ is_content_editable_ = is_content_editable;
+ }
+
+ private:
+ friend struct base::DefaultSingletonTraits<ClipboardHelperEfl>;
+
+ static Eina_Bool SelectionGetCbHTML(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev);
+ static Eina_Bool SelectionGetCbText(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev);
+ static Eina_Bool SelectionGetCbAppHTML(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev);
+ static Eina_Bool SelectionGetCbAppText(void* data,
+ Evas_Object* obj,
+ Elm_Selection_Data* ev);
+
+ static bool Base64ImageTagFromImagePath(const std::string& path,
+ std::string* image_html);
+ static bool ConvertImgTagToBase64(const std::string& tag,
+ std::string* out_tag);
+
+ static void CbhmOnNameOwnerChanged(void* data,
+ const char* bus,
+ const char* old_id,
+ const char* new_id);
+ static void OnClipboardItemClicked(void* data, const Eldbus_Message* msg);
+ static void GetClipboardTextPost(ClipboardHelperEfl* self);
+
+ ClipboardHelperEfl();
+ ~ClipboardHelperEfl();
+
+ ClipboardHelperEfl(const ClipboardHelperEfl&) = delete;
+ ClipboardHelperEfl& operator=(const ClipboardHelperEfl&) = delete;
+
+ void RefreshClipboardForApp();
+ void ProcessClipboardAppEvent(Elm_Selection_Data* ev, Elm_Sel_Format format);
+
+ const std::string& clipboard_html() const {
+ return paste_from_clipboard_app_
+ ? clipboard_contents_html_from_clipboard_app_
+ : clipboard_contents_html_;
+ }
+ const std::string& clipboard_text() const {
+ return paste_from_clipboard_app_ ? clipboard_contents_from_clipboard_app_
+ : clipboard_contents_;
+ }
+
+ void CbhmEldbusInit();
+ void CbhmEldbusDeinit();
+ int CbhmNumberOfItems() const;
+
+ // elm_cnp_selection_* API requires an elm object
+ // TODO(g.ludwikowsk): what happens when we use different source widgets
+ // (multiple webviews)?
+ Evas_Object* source_widget_ = nullptr;
+
+ std::string clipboard_contents_html_;
+ std::string clipboard_contents_html_from_clipboard_app_;
+ std::string clipboard_contents_;
+ std::string clipboard_contents_from_clipboard_app_;
+
+ // Clipboard app integration:
+ Eldbus_Proxy* eldbus_proxy_;
+ Eldbus_Connection* cbhm_conn_;
+ ExecCommandCallback exec_command_callback_;
+
+ bool clipboard_window_opened_ = false;
+ bool paste_from_clipboard_app_ = false;
+ bool accept_clipboard_app_events_ = false;
+ bool is_content_editable_= false;
+ EWebView* last_webview_ = nullptr;
+};
+
+#endif /* CLIPBOARD_HELPER_EFL_WAYLAND_H_ */
# For //ui/base target
external_ui_base_includes = [ "//third_party/mojo/src/" ]
external_ui_base_sources = [
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc",
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.h",
"//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl.cc",
"//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl.h",
"//ui/base/nine_image_painter_factory.h",
]
-# FIXME: ewk_bringup definition should be removed.
-if (!ewk_bringup) {
- sources += [
- "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc",
- "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.h",
+if (use_wayland) {
+ external_ui_base_sources += [
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl_wayland.cc",
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl_wayland.h",
+ ]
+} else {
+ external_ui_base_sources += [
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl_X11.cc",
+ "//tizen_src/chromium_impl/ui/base/clipboard/clipboard_helper_efl_X11.h",
]
}
if (!CreateContextMenu())
return false;
+#if defined(USE_WAYLAND)
+ ClipboardHelperEfl::GetInstance()->RefreshClipboard();
+#endif
+
return ShowContextMenu();
}
std::string(),
params_.link_url.spec());
}
- if (params_.is_editable && ClipboardHelperEfl::NumberOfItems() > 0) {
+ if (params_.is_editable &&
+ ClipboardHelperEfl::GetInstance()->CanPasteFromSystemClipboard()) {
AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION, EWK_CONTEXT_MENU_ITEM_TAG_PASTE,
std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_PASTE")));
}
std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_DRAG_AND_DROP")));
}
#endif
-#if !defined(WAYLAND_BRINGUP)
- if (params_.is_editable && ClipboardHelperEfl::NumberOfItems() > 0) {
+
+ if (params_.is_editable &&
+ ClipboardHelperEfl::GetInstance()->CanPasteFromClipboardApp()) {
AddItemToProposedList(EWK_CONTEXT_MENU_ITEM_TYPE_ACTION, EWK_CONTEXT_MENU_ITEM_TAG_CLIPBOARD,
std::string(dgettext("WebKit", "IDS_WEBVIEW_OPT_CLIPBOARD")));
}
-#else
- NOTIMPLEMENTED();
-#endif
}
bool ContextMenuControllerEfl::CreateContextMenu() {
#if !defined(WAYLAND_BRINGUP)
const std::string& download_path = download->GetForcedFilePath().value();
ClipboardHelperEfl::GetInstance()->SetData(download_path,
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_IMAGE);
+ ClipboardDataTypeEfl::IMAGE);
#else
NOTIMPLEMENTED();
#endif
break;
}
case EWK_CONTEXT_MENU_ITEM_TAG_COPY_IMAGE_TO_CLIPBOARD: {
+ LOG(INFO) << "[CLIPBOARD] copying image to clipboard!";
std::string plain_text = params_.src_url.spec();
- ClipboardHelperEfl::GetInstance()->SetData(plain_text,
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_PLAIN_TEXT);
+ ClipboardHelperEfl::GetInstance()->SetData(
+ plain_text, ClipboardDataTypeEfl::PLAIN_TEXT);
- ClipboardHelperEfl::GetInstance()->SetData(base::UTF16ToASCII(params_.selection_text),
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_MARKUP);
+ // FIXME(g.ludwikowsk): Setting markup data doesn't work like this,
+ // selection_text doesn't contain html. Do we actually need to do this?
+ ClipboardHelperEfl::GetInstance()->SetData(
+ base::UTF16ToASCII(params_.selection_text),
+ ClipboardDataTypeEfl::MARKUP);
DownloadFile(
GURL(params_.src_url.spec()), base::FilePath("/tmp/"),
- base::BindOnce(&ContextMenuControllerEfl::OnClipboardDownload,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindRepeating(&ContextMenuControllerEfl::OnClipboardDownload,
+ weak_ptr_factory_.GetWeakPtr()));
break;
}
case EWK_CONTEXT_MENU_ITEM_TAG_COPY_LINK_DATA: {
ClipboardHelperEfl::GetInstance()->SetData(
- base::UTF16ToUTF8(params_.link_text),
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_URL);
+ base::UTF16ToUTF8(params_.link_text), ClipboardDataTypeEfl::URL);
break;
}
case EWK_CONTEXT_MENU_ITEM_TAG_COPY_LINK_TO_CLIPBOARD: {
ClipboardHelperEfl::GetInstance()->SetData(params_.link_url.spec(),
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_URL);
+ ClipboardDataTypeEfl::URL);
break;
}
case EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_LINK_TO_DISK: {
}
case EWK_CONTEXT_MENU_ITEM_TAG_CLIPBOARD: {
// TODO: set true for richly editable.
- // Paste operations are blocked by Editor if content is not richly editible.
- // Need to find if webview_ has rich editor.
-#if !defined(WAYLAND_BRINGUP)
+ // Paste operations are blocked by Editor if content is not richly
+ // editible. Need to find if webview_ has rich editor.
ClipboardHelperEfl::GetInstance()->OpenClipboardWindow(webview_, true);
-#else
- NOTIMPLEMENTED();
-#endif
break;
}
case EWK_CONTEXT_MENU_ITEM_TAG_DRAG: {
#include "ui/aura/test/test_focus_client.h"
#include "ui/aura/test/test_window_parenting_client.h"
#include "ui/aura/window.h"
+#include "ui/base/clipboard/clipboard_helper_efl.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/display/screen.h"
#include "ui/events/event_switches.h"
cbce->RemoveAcceptLangsChangedCallback(
std::move(accept_langs_changed_callback_));
#endif
+
+#if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
+ ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
+#endif
+
std::map<int64_t, WebViewAsyncRequestHitTestDataCallback*>::iterator
hit_test_callback_iterator;
for (hit_test_callback_iterator = hit_test_callback_.begin();
void EWebView::ExecuteEditCommand(const char* command, const char* value) {
EINA_SAFETY_ON_NULL_RETURN(command);
- value = (value == NULL) ? "" : value;
-
- RenderWidgetHostImpl* rwhi = static_cast<RenderWidgetHostImpl*>(
- web_contents_->GetRenderViewHost()->GetWidget());
+ value = (value == nullptr) ? "" : value;
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- // This is moved to mojo in upstream. Change it.
- // https://chromium-review.googlesource.com/c/chromium/src/+/541036
- rwhi->ExecuteEditCommand(command, value);
-#endif
+ absl::optional<std::u16string> optional_value =
+ absl::make_optional(base::ASCIIToUTF16(value));
- // This is workaround for rich text toolbar buttons in email application
- if (!strcmp(command, "InsertOrderedList") ||
- !strcmp(command, "InsertUnorderedList") ||
- !strcmp(command, "AlignCenter") || !strcmp(command, "AlignJustified") ||
- !strcmp(command, "AlignLeft") || !strcmp(command, "AlignRight")) {
- QuerySelectionStyle();
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(web_contents_.get());
+ if (wc) {
+ wc->GetFocusedFrameWidgetInputHandler()->ExecuteEditCommand(
+ std::string(command), optional_value);
}
}
void EWebView::OnFocusIn() {
SmartCallback<EWebViewCallbacks::FocusIn>().call();
+#if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
+ if (!rwhva() || !rwhva()->offscreen_helper())
+ return;
+ ClipboardHelperEfl::GetInstance()->OnWebviewFocusIn(
+ this, rwhva()->offscreen_helper()->content_image_elm_host(),
+ rwhva()->offscreen_helper()->IsFocusedNodeContentEditable(),
+ base::BindRepeating(&EWebView::ExecuteEditCommand,
+ base::Unretained(this)));
+#endif
}
void EWebView::OnFocusOut() {
SmartCallback<EWebViewCallbacks::FocusOut>().call();
+#if defined(USE_WAYLAND) && !BUILDFLAG(IS_TIZEN_TV)
+ ClipboardHelperEfl::GetInstance()->MaybeInvalidateActiveWebview(this);
+#endif
}
void EWebView::RenderViewReady() {
}
}
-void EWebView::SetOverrideEncoding(const std::string& encoding) {
-// EWK_BRINGUP definition should be removed.
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- web_contents_->SetOverrideEncoding(encoding);
-#endif // !defined(EWK_BRINGUP)
-}
-
void EWebView::SetQuotaPermissionRequestCallback(
Ewk_Quota_Permission_Request_Callback callback,
void* user_data) {
if (currentEntry >= static_cast<int>(scopedEntries.size()))
currentEntry = scopedEntries.size() - 1;
-#if !defined(EWK_BRINGUP) // FIXME: m67 bringup
- // FIXME: EWK_BRINGUP definition should be removed.
- navigationController.Restore(
- currentEntry, NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
- &scopedEntries);
-#endif // !defined(EWK_BRINGUP)
+ navigationController.Restore(currentEntry, RestoreType::kRestored,
+ &scopedEntries);
return true;
}
bool GetLinkMagnifierEnabled() const;
void SetLinkMagnifierEnabled(bool enabled);
- void SetOverrideEncoding(const std::string& encoding);
void SetQuotaPermissionRequestCallback(
Ewk_Quota_Permission_Request_Callback callback,
void* user_data);
if (controller->options_[index] == COPY) {
ClipboardHelperEfl::GetInstance()->SetData(
- controller->content(),
- ClipboardHelperEfl::CLIPBOARD_DATA_TYPE_PLAIN_TEXT);
+ controller->content(), ClipboardDataTypeEfl::PLAIN_TEXT);
} else if (controller->popupContentType() == PHONE) {
if (controller->options_[index] == CALL) {
app_control_set_operation(svcHandle, APP_CONTROL_OPERATION_DIAL);
"utc_blink_ewk_settings_autofill_password_form_enabled_set_func.cpp",
"utc_blink_ewk_settings_clear_text_selection_automatically_set_func.cpp",
"utc_blink_ewk_settings_current_legacy_font_size_mode_set_func.cpp",
- "utc_blink_ewk_settings_default_encoding_set_func.cpp",
"utc_blink_ewk_settings_default_keypad_enabled_set_func.cpp",
"utc_blink_ewk_settings_detect_contents_automatically_set_func.cpp",
"utc_blink_ewk_settings_dom_paste_allowed_get_func.cpp",
+++ /dev/null
-// Copyright 2014 Samsung Electronics. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "utc_blink_ewk_base.h"
-
-class utc_blink_ewk_view_encoding_custom_set : public utc_blink_ewk_base
-{
-public:
- static const char* encoding_;
-};
-
-const char* utc_blink_ewk_view_encoding_custom_set::encoding_ = "utf-8";
-
-/**
-* @brief Check whether function works well with correct webview as parameter
-*/
-TEST_F(utc_blink_ewk_view_encoding_custom_set, POS_TEST)
-{
- ewk_view_encoding_custom_set(GetEwkWebView(), encoding_);
- SUCCEED();
-}
-
-/**
-* @brief Checking whether function works properly in case of NULL of a webview.
-*/
-TEST_F(utc_blink_ewk_view_encoding_custom_set, NEG_TEST)
-{
- ewk_view_encoding_custom_set(NULL, encoding_);
- SUCCEED();
-}
// maximizes the amount of data that can be extracted by various programs.
// Documentation on motivation for format ordering is also available here:
// https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats#multiple-clipboard-formats
+#if BUILDFLAG(IS_TIZEN)
+ // On Tizen, it is required that HTML content should be written to clipboard
+ // after type TEXT. So that when Copy-Paste operation is performed on markup
+ // content, it should be rendered as-is.
+ enum class PortableFormat{
+ kText,
+ kHtml,
+ kRtf,
+ kBookmark,
+ kWebkit,
+ kBitmap, // Bitmap from shared memory.
+ kData, // Arbitrary block of bytes.
+ kSvg,
+ kFilenames,
+ kWebCustomFormatMap,
+ };
+#else
enum class PortableFormat {
kBitmap, // Bitmap from shared memory.
kHtml,
kEncodedDataTransferEndpoint,
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
};
+#endif
// TODO (https://crbug.com/994928): Rename ObjectMap-related types.
// ObjectMap is a map from PortableFormat to associated data.
#include "ui/base/ui_base_switches.h"
#include "ui/ozone/public/ozone_platform.h"
+#if BUILDFLAG(IS_EFL)
+#include "ui/base/clipboard/clipboard_efl.h"
+#endif
+
namespace ui {
Clipboard* Clipboard::Create() {
switches::kUseSystemClipboard);
#endif
+#if BUILDFLAG(IS_EFL)
+ return new ClipboardEfl;
+#else
if (use_ozone_impl && OzonePlatform::GetInstance()->GetPlatformClipboard())
return new ClipboardOzone;
+#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
NOTREACHED() << "System clipboard integration should be in place.";
std::string GetName() const;
#if BUILDFLAG(IS_WIN)
const FORMATETC& ToFormatEtc() const { return *ChromeToWindowsType(&data_); }
+#elif BUILDFLAG(IS_EFL)
+ const std::string& ToString() const { return data_; }
#elif BUILDFLAG(IS_APPLE)
NSString* ToNSString() const { return data_; }
// Custom copy and assignment constructor to handle NSString.