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

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

Issue 12041078: Clear the clipboard closing Incognito window (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Selection clipboard support Created 7 years, 10 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
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 <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 #include <X11/extensions/Xfixes.h> 8 #include <X11/extensions/Xfixes.h>
9 #include <X11/Xatom.h> 9 #include <X11/Xatom.h>
10 #include <map> 10 #include <map>
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 clipboard_sequence_number_++; 99 clipboard_sequence_number_++;
100 } else if (ev->selection == XA_PRIMARY) { 100 } else if (ev->selection == XA_PRIMARY) {
101 primary_sequence_number_++; 101 primary_sequence_number_++;
102 } else { 102 } else {
103 DLOG(ERROR) << "Unexpected selection atom: " << ev->selection; 103 DLOG(ERROR) << "Unexpected selection atom: " << ev->selection;
104 } 104 }
105 } 105 }
106 return GDK_FILTER_CONTINUE; 106 return GDK_FILTER_CONTINUE;
107 } 107 }
108 108
109 const char kSourceTagType[] = "org.chromium.source-tag";
109 const char kMimeTypeBitmap[] = "image/bmp"; 110 const char kMimeTypeBitmap[] = "image/bmp";
110 const char kMimeTypeMozillaURL[] = "text/x-moz-url"; 111 const char kMimeTypeMozillaURL[] = "text/x-moz-url";
111 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data"; 112 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
112 const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste"; 113 const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
113 114
114 std::string GdkAtomToString(const GdkAtom& atom) { 115 std::string GdkAtomToString(const GdkAtom& atom) {
115 gchar* name = gdk_atom_name(atom); 116 gchar* name = gdk_atom_name(atom);
116 std::string rv(name); 117 std::string rv(name);
117 g_free(name); 118 g_free(name);
118 return rv; 119 return rv;
(...skipping 26 matching lines...) Expand all
145 gtk_selection_data_set(selection_data, 146 gtk_selection_data_set(selection_data,
146 gtk_selection_data_get_target(selection_data), 8, 147 gtk_selection_data_get_target(selection_data), 8,
147 reinterpret_cast<guchar*>(iter->second.first), 148 reinterpret_cast<guchar*>(iter->second.first),
148 iter->second.second); 149 iter->second.second);
149 } 150 }
150 } 151 }
151 152
152 // GtkClipboardClearFunc callback. 153 // GtkClipboardClearFunc callback.
153 // We are guaranteed this will be called exactly once for each call to 154 // We are guaranteed this will be called exactly once for each call to
154 // gtk_clipboard_set_with_data. 155 // gtk_clipboard_set_with_data.
155 void ClearData(GtkClipboard* clipboard, 156 void ClearData(GtkClipboard* /*clipboard*/,
156 gpointer user_data) { 157 gpointer user_data) {
157 Clipboard::TargetMap* map = 158 Clipboard::TargetMap* map =
158 reinterpret_cast<Clipboard::TargetMap*>(user_data); 159 reinterpret_cast<Clipboard::TargetMap*>(user_data);
159 // The same data may be inserted under multiple keys, so use a set to 160 // The same data may be inserted under multiple keys, so use a set to
160 // uniq them. 161 // uniq them.
161 std::set<char*> ptrs; 162 std::set<char*> ptrs;
162 163
163 for (Clipboard::TargetMap::iterator iter = map->begin(); 164 for (Clipboard::TargetMap::iterator iter = map->begin();
164 iter != map->end(); ++iter) { 165 iter != map->end(); ++iter) {
165 if (iter->first == kMimeTypeBitmap) 166 if (iter->first == kMimeTypeBitmap)
166 g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first)); 167 g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first));
167 else 168 else
168 ptrs.insert(iter->second.first); 169 ptrs.insert(iter->second.first);
169 } 170 }
170 171
171 for (std::set<char*>::iterator iter = ptrs.begin(); 172 for (std::set<char*>::iterator iter = ptrs.begin();
172 iter != ptrs.end(); ++iter) { 173 iter != ptrs.end(); ++iter) {
173 delete[] *iter; 174 delete[] *iter;
174 } 175 }
175 176
176 delete map; 177 delete map;
177 } 178 }
178 179
180 // Sets the content of |clipboard|. |clipboard_data| is to be allocated by new.
181 // The ownership is transferred to the function. |clipboard_data| is destroyed
182 // inside upon failure.
battre 2013/02/12 12:50:59 I think the entire comment can be simplified to //
vasilii 2013/02/12 15:58:32 The whole function is reverted...
183 bool GtkClipboardSetWithData(GtkClipboard* clipboard,
184 Clipboard::TargetMap* clipboard_data) {
185 scoped_array<GtkTargetEntry> targets(
186 new GtkTargetEntry[clipboard_data->size()]);
187
188 int i = 0;
189 for (Clipboard::TargetMap::iterator iter = clipboard_data->begin();
190 iter != clipboard_data->end(); ++iter, ++i) {
battre 2013/02/12 12:50:59 nit: +1 space
vasilii 2013/02/12 15:58:32 Done.
191 targets[i].target = const_cast<char*>(iter->first.c_str());
192 targets[i].flags = 0;
193 targets[i].info = 0;
194 }
195
196 if (gtk_clipboard_set_with_data(clipboard, targets.get(),
197 clipboard_data->size(),
198 GetData, ClearData,
199 clipboard_data)) {
200 gtk_clipboard_set_can_store(clipboard,
201 targets.get(),
202 clipboard_data->size());
203 return true;
204 }
205 // We should clear data manually on failure.
206 ClearData(clipboard, clipboard_data);
207 return false;
208 }
209
179 } // namespace 210 } // namespace
180 211
181 Clipboard::FormatType::FormatType() : data_(GDK_NONE) { 212 Clipboard::FormatType::FormatType() : data_(GDK_NONE) {
182 } 213 }
183 214
184 Clipboard::FormatType::FormatType(const std::string& format_string) 215 Clipboard::FormatType::FormatType(const std::string& format_string)
185 : data_(StringToGdkAtom(format_string)) { 216 : data_(StringToGdkAtom(format_string)) {
186 } 217 }
187 218
188 Clipboard::FormatType::FormatType(const GdkAtom& native_format) 219 Clipboard::FormatType::FormatType(const GdkAtom& native_format)
(...skipping 21 matching lines...) Expand all
210 DCHECK(CalledOnValidThread()); 241 DCHECK(CalledOnValidThread());
211 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); 242 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
212 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); 243 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
213 } 244 }
214 245
215 Clipboard::~Clipboard() { 246 Clipboard::~Clipboard() {
216 DCHECK(CalledOnValidThread()); 247 DCHECK(CalledOnValidThread());
217 gtk_clipboard_store(clipboard_); 248 gtk_clipboard_store(clipboard_);
218 } 249 }
219 250
220 void Clipboard::WriteObjects(Buffer buffer, const ObjectMap& objects) { 251 void Clipboard::WriteObjectsImpl(Buffer buffer,
252 const ObjectMap& objects,
253 SourceTag tag) {
221 DCHECK(CalledOnValidThread()); 254 DCHECK(CalledOnValidThread());
222 clipboard_data_ = new TargetMap(); 255 clipboard_data_ = new TargetMap();
223 256
224 for (ObjectMap::const_iterator iter = objects.begin(); 257 for (ObjectMap::const_iterator iter = objects.begin();
225 iter != objects.end(); ++iter) { 258 iter != objects.end(); ++iter) {
226 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); 259 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
227 } 260 }
261 WriteSourceTag(tag);
228 262
229 SetGtkClipboard(buffer); 263 SetGtkClipboard(buffer, tag);
dcheng 2013/02/11 22:58:21 I'd prefer not to pass tag explicitly here. It's a
vasilii 2013/02/12 15:58:32 Done.
230 } 264 }
231 265
232 // Take ownership of the GTK clipboard and inform it of the targets we support. 266 // Take ownership of the GTK clipboard and inform it of the targets we support.
233 void Clipboard::SetGtkClipboard(Buffer buffer) { 267 void Clipboard::SetGtkClipboard(Buffer buffer, SourceTag tag) {
234 scoped_ptr<GtkTargetEntry[]> targets(
235 new GtkTargetEntry[clipboard_data_->size()]);
236
237 int i = 0;
238 for (Clipboard::TargetMap::iterator iter = clipboard_data_->begin();
239 iter != clipboard_data_->end(); ++iter, ++i) {
240 targets[i].target = const_cast<char*>(iter->first.c_str());
241 targets[i].flags = 0;
242 targets[i].info = 0;
243 }
244
245 GtkClipboard *clipboard = LookupBackingClipboard(buffer); 268 GtkClipboard *clipboard = LookupBackingClipboard(buffer);
246 269 if (GtkClipboardSetWithData(clipboard, clipboard_data_))
battre 2013/02/12 12:50:59 please add {}
vasilii 2013/02/12 15:58:32 Done.
247 if (gtk_clipboard_set_with_data(clipboard, targets.get(), 270 if (buffer == BUFFER_STANDARD) {
248 clipboard_data_->size(), 271 Clipboard::TargetMap::iterator text_iter = clipboard_data_->find("TEXT");
249 GetData, ClearData, 272 if (text_iter != clipboard_data_->end()) {
250 clipboard_data_)) { 273 // Copy text and SourceTag to the selection clipboard.
251 gtk_clipboard_set_can_store(clipboard, 274 clipboard_data_ = new TargetMap;
dcheng 2013/02/11 22:58:21 I think this might be cleaner if you pull this log
vasilii 2013/02/12 15:58:32 Done.
252 targets.get(), 275 WriteText(text_iter->second.first, text_iter->second.second);
253 clipboard_data_->size()); 276 WriteSourceTag(tag);
254 } 277 GtkClipboardSetWithData(primary_selection_, clipboard_data_);
255 278 }
256 if (buffer == BUFFER_STANDARD) {
257 Clipboard::TargetMap::iterator text_iter = clipboard_data_->find("TEXT");
258 if (text_iter != clipboard_data_->end()) {
259 gtk_clipboard_set_text(primary_selection_, text_iter->second.first,
260 text_iter->second.second);
261 } 279 }
262 }
263 280
264 // clipboard_data_ now owned by the GtkClipboard. 281 // clipboard_data_ now owned by the GtkClipboard.
265 clipboard_data_ = NULL; 282 clipboard_data_ = NULL;
266 } 283 }
267 284
268 void Clipboard::WriteText(const char* text_data, size_t text_len) { 285 void Clipboard::WriteText(const char* text_data, size_t text_len) {
269 char* data = new char[text_len]; 286 char* data = new char[text_len];
270 memcpy(data, text_data, text_len); 287 memcpy(data, text_data, text_len);
271 288
272 InsertMapping(kMimeTypeText, data, text_len); 289 InsertMapping(kMimeTypeText, data, text_len);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 // We assume that certain mapping types are only written by trusted code. 360 // We assume that certain mapping types are only written by trusted code.
344 // Therefore we must upkeep their integrity. 361 // Therefore we must upkeep their integrity.
345 if (format.Equals(GetBitmapFormatType())) 362 if (format.Equals(GetBitmapFormatType()))
346 return; 363 return;
347 char* data = new char[data_len]; 364 char* data = new char[data_len];
348 memcpy(data, data_data, data_len); 365 memcpy(data, data_data, data_len);
349 // TODO(dcheng): Maybe this map should use GdkAtoms... 366 // TODO(dcheng): Maybe this map should use GdkAtoms...
350 InsertMapping(GdkAtomToString(format.ToGdkAtom()).c_str(), data, data_len); 367 InsertMapping(GdkAtomToString(format.ToGdkAtom()).c_str(), data, data_len);
351 } 368 }
352 369
370 void Clipboard::WriteSourceTag(SourceTag tag) {
371 if (tag != SourceTag()) {
372 ObjectMapParam binary = SourceTag2Binary(tag);
373 WriteData(GetSourceTagFormatType(), &binary[0], binary.size());
374 }
375 }
376
353 // We do not use gtk_clipboard_wait_is_target_available because of 377 // We do not use gtk_clipboard_wait_is_target_available because of
354 // a bug with the gtk clipboard. It caches the available targets 378 // a bug with the gtk clipboard. It caches the available targets
355 // and does not always refresh the cache when it is appropriate. 379 // and does not always refresh the cache when it is appropriate.
356 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, 380 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
357 Clipboard::Buffer buffer) const { 381 Clipboard::Buffer buffer) const {
358 DCHECK(CalledOnValidThread()); 382 DCHECK(CalledOnValidThread());
359 GtkClipboard* clipboard = LookupBackingClipboard(buffer); 383 GtkClipboard* clipboard = LookupBackingClipboard(buffer);
360 if (clipboard == NULL) 384 if (clipboard == NULL)
361 return false; 385 return false;
362 386
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 type, result); 593 type, result);
570 gtk_selection_data_free(data); 594 gtk_selection_data_free(data);
571 } 595 }
572 596
573 void Clipboard::ReadBookmark(string16* title, std::string* url) const { 597 void Clipboard::ReadBookmark(string16* title, std::string* url) const {
574 // TODO(estade): implement this. 598 // TODO(estade): implement this.
575 NOTIMPLEMENTED(); 599 NOTIMPLEMENTED();
576 } 600 }
577 601
578 void Clipboard::ReadData(const FormatType& format, std::string* result) const { 602 void Clipboard::ReadData(const FormatType& format, std::string* result) const {
603 ReadDataImpl(BUFFER_STANDARD, format, result);
604 }
605
606 void Clipboard::ReadDataImpl(Buffer buffer,
607 const FormatType& format,
608 std::string* result) const {
579 DCHECK(CalledOnValidThread()); 609 DCHECK(CalledOnValidThread());
610 result->clear();
611 GtkClipboard* clipboard = LookupBackingClipboard(buffer);
580 GtkSelectionData* data = 612 GtkSelectionData* data =
581 gtk_clipboard_wait_for_contents(clipboard_, format.ToGdkAtom()); 613 gtk_clipboard_wait_for_contents(clipboard, format.ToGdkAtom());
582 if (!data) 614 if (!data)
583 return; 615 return;
584 result->assign(reinterpret_cast<const char*>( 616 result->assign(reinterpret_cast<const char*>(
585 gtk_selection_data_get_data(data)), 617 gtk_selection_data_get_data(data)),
586 gtk_selection_data_get_length(data)); 618 gtk_selection_data_get_length(data));
587 gtk_selection_data_free(data); 619 gtk_selection_data_free(data);
588 } 620 }
589 621
622 Clipboard::SourceTag Clipboard::ReadSourceTag(Buffer buffer) const {
623 std::string result;
624 ReadDataImpl(buffer, GetSourceTagFormatType(), &result);
625 return Binary2SourceTag(result);
626 }
627
590 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { 628 uint64 Clipboard::GetSequenceNumber(Buffer buffer) {
591 DCHECK(CalledOnValidThread()); 629 DCHECK(CalledOnValidThread());
592 if (buffer == BUFFER_STANDARD) 630 if (buffer == BUFFER_STANDARD)
593 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); 631 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number();
594 else 632 else
595 return SelectionChangeObserver::GetInstance()->primary_sequence_number(); 633 return SelectionChangeObserver::GetInstance()->primary_sequence_number();
596 } 634 }
597 635
598 //static 636 //static
599 Clipboard::FormatType Clipboard::GetFormatType( 637 Clipboard::FormatType Clipboard::GetFormatType(
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData)); 690 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
653 return type; 691 return type;
654 } 692 }
655 693
656 // static 694 // static
657 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { 695 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
658 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); 696 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
659 return type; 697 return type;
660 } 698 }
661 699
700 // static
701 const Clipboard::FormatType& Clipboard::GetSourceTagFormatType() {
702 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kSourceTagType));
703 return type;
704 }
705
662 void Clipboard::InsertMapping(const char* key, 706 void Clipboard::InsertMapping(const char* key,
663 char* data, 707 char* data,
664 size_t data_len) { 708 size_t data_len) {
665 DCHECK(clipboard_data_->find(key) == clipboard_data_->end()); 709 DCHECK(clipboard_data_->find(key) == clipboard_data_->end());
666 (*clipboard_data_)[key] = std::make_pair(data, data_len); 710 (*clipboard_data_)[key] = std::make_pair(data, data_len);
667 } 711 }
668 712
669 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { 713 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const {
670 switch (clipboard) { 714 switch (clipboard) {
671 case BUFFER_STANDARD: 715 case BUFFER_STANDARD:
672 return clipboard_; 716 return clipboard_;
673 case BUFFER_SELECTION: 717 case BUFFER_SELECTION:
674 return primary_selection_; 718 return primary_selection_;
675 default: 719 default:
676 NOTREACHED(); 720 NOTREACHED();
677 return NULL; 721 return NULL;
678 } 722 }
679 } 723 }
680 724
681 } // namespace ui 725 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698