Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(499)

Side by Side Diff: ui/base/clipboard/clipboard_aurax11.cc

Issue 14189002: linux_aura: Implement dropping in chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to ToT Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/clipboard/clipboard.h" 5 #include "ui/base/clipboard/clipboard.h"
6 6
7 #include <X11/extensions/Xfixes.h> 7 #include <X11/extensions/Xfixes.h>
8 #include <X11/Xatom.h> 8 #include <X11/Xatom.h>
9 #include <list> 9 #include <list>
10 #include <set> 10 #include <set>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/i18n/icu_string_conversions.h"
15 #include "base/logging.h" 14 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/singleton.h" 16 #include "base/memory/singleton.h"
18 #include "base/message_pump_aurax11.h" 17 #include "base/message_pump_aurax11.h"
19 #include "base/message_pump_observer.h" 18 #include "base/message_pump_observer.h"
20 #include "base/stl_util.h" 19 #include "base/stl_util.h"
21 #include "base/utf_string_conversions.h" 20 #include "base/utf_string_conversions.h"
22 #include "third_party/skia/include/core/SkBitmap.h" 21 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "ui/base/clipboard/custom_data_helper.h" 22 #include "ui/base/clipboard/custom_data_helper.h"
24 #include "ui/base/x/selection_owner.h" 23 #include "ui/base/x/selection_owner.h"
25 #include "ui/base/x/selection_requestor.h" 24 #include "ui/base/x/selection_requestor.h"
26 #include "ui/base/x/selection_utils.h" 25 #include "ui/base/x/selection_utils.h"
27 #include "ui/base/x/x11_atom_cache.h" 26 #include "ui/base/x/x11_atom_cache.h"
28 #include "ui/base/x/x11_util.h" 27 #include "ui/base/x/x11_util.h"
29 28
30 #include "ui/gfx/size.h" 29 #include "ui/gfx/size.h"
31 30
32 namespace ui { 31 namespace ui {
33 32
34 namespace { 33 namespace {
35 34
36 const char kClipboard[] = "CLIPBOARD"; 35 const char kClipboard[] = "CLIPBOARD";
37 const char kMimeTypeBitmap[] = "image/bmp"; 36 const char kMimeTypeBitmap[] = "image/bmp";
38 const char kMimeTypeFilename[] = "chromium/filename"; 37 const char kMimeTypeFilename[] = "chromium/filename";
39 const char kMimeTypeMozillaURL[] = "text/x-moz-url";
40 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data"; 38 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
41 const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste"; 39 const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
42 const char kSourceTagType[] = "org.chromium.source-tag"; 40 const char kSourceTagType[] = "org.chromium.source-tag";
43 const char kString[] = "STRING";
44 const char kTargets[] = "TARGETS"; 41 const char kTargets[] = "TARGETS";
45 const char kText[] = "TEXT";
46 const char kUtf8String[] = "UTF8_STRING";
47 42
48 const char* kAtomsToCache[] = { 43 const char* kAtomsToCache[] = {
49 kClipboard, 44 kClipboard,
50 kMimeTypeBitmap, 45 kMimeTypeBitmap,
51 kMimeTypeFilename, 46 kMimeTypeFilename,
52 kMimeTypeMozillaURL, 47 kMimeTypeMozillaURL,
53 kMimeTypeWebkitSmartPaste, 48 kMimeTypeWebkitSmartPaste,
54 kSourceTagType, 49 kSourceTagType,
55 kString, 50 kString,
56 kTargets, 51 kTargets,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 138
144 /////////////////////////////////////////////////////////////////////////////// 139 ///////////////////////////////////////////////////////////////////////////////
145 140
146 // Represents a list of possible return types. Copy constructable. 141 // Represents a list of possible return types. Copy constructable.
147 class TargetList { 142 class TargetList {
148 public: 143 public:
149 typedef std::vector< ::Atom> AtomVector; 144 typedef std::vector< ::Atom> AtomVector;
150 145
151 TargetList(const AtomVector& target_list, X11AtomCache* atom_cache); 146 TargetList(const AtomVector& target_list, X11AtomCache* atom_cache);
152 147
148 const AtomVector& target_list() { return target_list_; }
149
153 bool ContainsText() const; 150 bool ContainsText() const;
154 bool ContainsFormat(const Clipboard::FormatType& format_type) const; 151 bool ContainsFormat(const Clipboard::FormatType& format_type) const;
155 bool ContainsAtom(::Atom atom) const; 152 bool ContainsAtom(::Atom atom) const;
156 153
157 private: 154 private:
158 AtomVector target_list_; 155 AtomVector target_list_;
159 X11AtomCache* atom_cache_; 156 X11AtomCache* atom_cache_;
160 }; 157 };
161 158
162 TargetList::TargetList(const AtomVector& target_list, 159 TargetList::TargetList(const AtomVector& target_list,
(...skipping 17 matching lines...) Expand all
180 const Clipboard::FormatType& format_type) const { 177 const Clipboard::FormatType& format_type) const {
181 ::Atom atom = atom_cache_->GetAtom(format_type.ToString().c_str()); 178 ::Atom atom = atom_cache_->GetAtom(format_type.ToString().c_str());
182 return ContainsAtom(atom); 179 return ContainsAtom(atom);
183 } 180 }
184 181
185 bool TargetList::ContainsAtom(::Atom atom) const { 182 bool TargetList::ContainsAtom(::Atom atom) const {
186 return find(target_list_.begin(), target_list_.end(), atom) 183 return find(target_list_.begin(), target_list_.end(), atom)
187 != target_list_.end(); 184 != target_list_.end();
188 } 185 }
189 186
190 ///////////////////////////////////////////////////////////////////////////////
191
192 // A holder for data with optional X11 deletion semantics.
193 class SelectionData {
194 public:
195 // |atom_cache| is still owned by caller.
196 explicit SelectionData(X11AtomCache* atom_cache);
197 ~SelectionData();
198
199 ::Atom type() const { return type_; }
200 char* data() const { return data_; }
201 size_t size() const { return size_; }
202
203 void Set(::Atom type, char* data, size_t size, bool owned);
204
205 // If |type_| is a string type, convert the data to UTF8 and return it.
206 std::string GetText() const;
207
208 // Assigns the raw data to the string.
209 void AssignTo(std::string* result) const;
210
211 private:
212 ::Atom type_;
213 char* data_;
214 size_t size_;
215 bool owned_;
216
217 X11AtomCache* atom_cache_;
218 };
219
220 SelectionData::SelectionData(X11AtomCache* atom_cache)
221 : type_(None),
222 data_(NULL),
223 size_(0),
224 owned_(false),
225 atom_cache_(atom_cache) {
226 }
227
228 SelectionData::~SelectionData() {
229 if (owned_)
230 XFree(data_);
231 }
232
233 void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) {
234 if (owned_)
235 XFree(data_);
236
237 type_ = type;
238 data_ = data;
239 size_ = size;
240 owned_ = owned;
241 }
242
243 std::string SelectionData::GetText() const {
244 if (type_ == atom_cache_->GetAtom(kUtf8String) ||
245 type_ == atom_cache_->GetAtom(kText)) {
246 return std::string(data_, size_);
247 } else if (type_ == atom_cache_->GetAtom(kString)) {
248 std::string result;
249 base::ConvertToUtf8AndNormalize(std::string(data_, size_),
250 base::kCodepageLatin1,
251 &result);
252 return result;
253 } else {
254 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
255 // support that. Yuck.
256 NOTREACHED();
257 return std::string();
258 }
259 }
260
261 void SelectionData::AssignTo(std::string* result) const {
262 result->assign(data_, size_);
263 }
264
265 } // namespace 187 } // namespace
266 188
267 /////////////////////////////////////////////////////////////////////////////// 189 ///////////////////////////////////////////////////////////////////////////////
268 190
269 // I would love for the FormatType to really be a wrapper around an X11 ::Atom, 191 // I would love for the FormatType to really be a wrapper around an X11 ::Atom,
270 // but there are a few problems. Chromeos unit tests spawn a new X11 server for 192 // but there are a few problems. Chromeos unit tests spawn a new X11 server for
271 // each test, so Atom numeric values don't persist across tests. We could still 193 // each test, so Atom numeric values don't persist across tests. We could still
272 // maybe deal with that if we didn't have static accessor methods everywhere. 194 // maybe deal with that if we didn't have static accessor methods everywhere.
273 195
274 Clipboard::FormatType::FormatType() { 196 Clipboard::FormatType::FormatType() {
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { 390 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
469 // We can local fastpath instead of playing the nested message loop game 391 // We can local fastpath instead of playing the nested message loop game
470 // with the X server. 392 // with the X server.
471 SelectionFormatMap* format_map = LookupStorageForAtom(selection_name); 393 SelectionFormatMap* format_map = LookupStorageForAtom(selection_name);
472 DCHECK(format_map); 394 DCHECK(format_map);
473 395
474 for (std::vector< ::Atom>::const_iterator it = types.begin(); 396 for (std::vector< ::Atom>::const_iterator it = types.begin();
475 it != types.end(); ++it) { 397 it != types.end(); ++it) {
476 SelectionFormatMap::const_iterator format_map_it = format_map->find(*it); 398 SelectionFormatMap::const_iterator format_map_it = format_map->find(*it);
477 if (format_map_it != format_map->end()) { 399 if (format_map_it != format_map->end()) {
478 scoped_ptr<SelectionData> data_out(new SelectionData(&atom_cache_)); 400 scoped_ptr<SelectionData> data_out(new SelectionData(x_display_));
479 data_out->Set(format_map_it->first, format_map_it->second.first, 401 data_out->Set(format_map_it->first, format_map_it->second.first,
480 format_map_it->second.second, false); 402 format_map_it->second.second, false);
481 return data_out.Pass(); 403 return data_out.Pass();
482 } 404 }
483 } 405 }
484 } else { 406 } else {
485 TargetList targets = WaitAndGetTargetsList(buffer); 407 TargetList targets = WaitAndGetTargetsList(buffer);
486 SelectionRequestor* receiver = GetSelectionRequestorForBuffer(buffer); 408 SelectionRequestor* receiver = GetSelectionRequestorForBuffer(buffer);
487 409
488 for (std::vector< ::Atom>::const_iterator it = types.begin(); 410 std::vector< ::Atom> intersection;
489 it != types.end(); ++it) { 411 ui::GetAtomIntersection(targets.target_list(), types, &intersection);
490 unsigned char* data = NULL; 412 return receiver->RequestAndWaitForTypes(intersection);
491 size_t data_bytes = 0;
492 ::Atom type = None;
493 if (targets.ContainsAtom(*it) &&
494 receiver->PerformBlockingConvertSelection(*it,
495 &data,
496 &data_bytes,
497 NULL,
498 &type) &&
499 type == *it) {
500 scoped_ptr<SelectionData> data_out(new SelectionData(&atom_cache_));
501 data_out->Set(type, (char*)data, data_bytes, true);
502 return data_out.Pass();
503 }
504 }
505 } 413 }
506 414
507 return scoped_ptr<SelectionData>(); 415 return scoped_ptr<SelectionData>();
508 } 416 }
509 417
510 TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList( 418 TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList(
511 Buffer buffer) { 419 Buffer buffer) {
512 ::Atom selection_name = LookupSelectionForBuffer(buffer); 420 ::Atom selection_name = LookupSelectionForBuffer(buffer);
513 std::vector< ::Atom> out; 421 std::vector< ::Atom> out;
514 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { 422 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 if (src_url) 642 if (src_url)
735 src_url->clear(); 643 src_url->clear();
736 *fragment_start = 0; 644 *fragment_start = 0;
737 *fragment_end = 0; 645 *fragment_end = 0;
738 646
739 scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes( 647 scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
740 buffer, aurax11_details_->GetAtomsForFormat(GetHtmlFormatType()))); 648 buffer, aurax11_details_->GetAtomsForFormat(GetHtmlFormatType())));
741 if (!data.get()) 649 if (!data.get())
742 return; 650 return;
743 651
744 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is 652 *markup = data->GetHtml();
745 // UTF-16, otherwise assume UTF-8.
746 if (data->size() >= 2 &&
747 reinterpret_cast<const uint16_t*>(data->data())[0] == 0xFEFF) {
748 markup->assign(reinterpret_cast<const uint16_t*>(data->data()) + 1,
749 (data->size() / 2) - 1);
750 } else {
751 UTF8ToUTF16(reinterpret_cast<const char*>(data->data()), data->size(),
752 markup);
753 }
754
755 // If there is a terminating NULL, drop it.
756 if (!markup->empty() && markup->at(markup->length() - 1) == '\0')
757 markup->resize(markup->length() - 1);
758 653
759 *fragment_start = 0; 654 *fragment_start = 0;
760 DCHECK(markup->length() <= kuint32max); 655 DCHECK(markup->length() <= kuint32max);
761 *fragment_end = static_cast<uint32>(markup->length()); 656 *fragment_end = static_cast<uint32>(markup->length());
762 } 657 }
763 658
764 void Clipboard::ReadRTF(Buffer buffer, std::string* result) const { 659 void Clipboard::ReadRTF(Buffer buffer, std::string* result) const {
765 DCHECK(CalledOnValidThread()); 660 DCHECK(CalledOnValidThread());
766 661
767 scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes( 662 scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 return type; 875 return type;
981 } 876 }
982 877
983 // static 878 // static
984 const Clipboard::FormatType& Clipboard::GetSourceTagFormatType() { 879 const Clipboard::FormatType& Clipboard::GetSourceTagFormatType() {
985 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kSourceTagType)); 880 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kSourceTagType));
986 return type; 881 return type;
987 } 882 }
988 883
989 } // namespace ui 884 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698