| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/clipboard.h" | 5 #include "base/clipboard.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 // Called on GdkPixbuf destruction; see WriteBitmap(). | 86 // Called on GdkPixbuf destruction; see WriteBitmap(). |
| 87 void GdkPixbufFree(guchar* pixels, gpointer data) { | 87 void GdkPixbufFree(guchar* pixels, gpointer data) { |
| 88 free(pixels); | 88 free(pixels); |
| 89 } | 89 } |
| 90 | 90 |
| 91 } // namespace | 91 } // namespace |
| 92 | 92 |
| 93 Clipboard::Clipboard() { | 93 Clipboard::Clipboard() { |
| 94 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | 94 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
| 95 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
| 95 } | 96 } |
| 96 | 97 |
| 97 Clipboard::~Clipboard() { | 98 Clipboard::~Clipboard() { |
| 98 // TODO(estade): do we want to save clipboard data after we exit? | 99 // TODO(estade): do we want to save clipboard data after we exit? |
| 99 // gtk_clipboard_set_can_store and gtk_clipboard_store work | 100 // gtk_clipboard_set_can_store and gtk_clipboard_store work |
| 100 // but have strangely awful performance. | 101 // but have strangely awful performance. |
| 101 } | 102 } |
| 102 | 103 |
| 103 void Clipboard::WriteObjects(const ObjectMap& objects) { | 104 void Clipboard::WriteObjects(const ObjectMap& objects) { |
| 104 clipboard_data_ = new TargetMap(); | 105 clipboard_data_ = new TargetMap(); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 const char* data_data, size_t data_len) { | 201 const char* data_data, size_t data_len) { |
| 201 char* data = new char[data_len]; | 202 char* data = new char[data_len]; |
| 202 memcpy(data, data_data, data_len); | 203 memcpy(data, data_data, data_len); |
| 203 std::string format(format_name, format_len); | 204 std::string format(format_name, format_len); |
| 204 InsertMapping(format.c_str(), data, data_len); | 205 InsertMapping(format.c_str(), data, data_len); |
| 205 } | 206 } |
| 206 | 207 |
| 207 // We do not use gtk_clipboard_wait_is_target_available because of | 208 // We do not use gtk_clipboard_wait_is_target_available because of |
| 208 // a bug with the gtk clipboard. It caches the available targets | 209 // a bug with the gtk clipboard. It caches the available targets |
| 209 // and does not always refresh the cache when it is appropriate. | 210 // and does not always refresh the cache when it is appropriate. |
| 210 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format) const { | 211 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, |
| 212 Clipboard::Buffer buffer) const { |
| 213 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
| 214 if (clipboard == NULL) |
| 215 return false; |
| 216 |
| 211 bool format_is_plain_text = GetPlainTextFormatType() == format; | 217 bool format_is_plain_text = GetPlainTextFormatType() == format; |
| 212 if (format_is_plain_text) { | 218 if (format_is_plain_text) { |
| 213 // This tries a number of common text targets. | 219 // This tries a number of common text targets. |
| 214 if (gtk_clipboard_wait_is_text_available(clipboard_)) | 220 if (gtk_clipboard_wait_is_text_available(clipboard)) |
| 215 return true; | 221 return true; |
| 216 } | 222 } |
| 217 | 223 |
| 218 bool retval = false; | 224 bool retval = false; |
| 219 GdkAtom* targets = NULL; | 225 GdkAtom* targets = NULL; |
| 220 GtkSelectionData* data = | 226 GtkSelectionData* data = |
| 221 gtk_clipboard_wait_for_contents(clipboard_, | 227 gtk_clipboard_wait_for_contents(clipboard, |
| 222 gdk_atom_intern("TARGETS", false)); | 228 gdk_atom_intern("TARGETS", false)); |
| 223 | 229 |
| 224 if (!data) | 230 if (!data) |
| 225 return false; | 231 return false; |
| 226 | 232 |
| 227 int num = 0; | 233 int num = 0; |
| 228 gtk_selection_data_get_targets(data, &targets, &num); | 234 gtk_selection_data_get_targets(data, &targets, &num); |
| 229 | 235 |
| 230 // Some programs post data to the clipboard without any targets. If this is | 236 // Some programs post data to the clipboard without any targets. If this is |
| 231 // the case we attempt to make sense of the contents as text. This is pretty | 237 // the case we attempt to make sense of the contents as text. This is pretty |
| 232 // unfortunate since it means we have to actually copy the data to see if it | 238 // unfortunate since it means we have to actually copy the data to see if it |
| 233 // is available, but at least this path shouldn't be hit for conforming | 239 // is available, but at least this path shouldn't be hit for conforming |
| 234 // programs. | 240 // programs. |
| 235 if (num <= 0) { | 241 if (num <= 0) { |
| 236 if (format_is_plain_text) { | 242 if (format_is_plain_text) { |
| 237 gchar* text = gtk_clipboard_wait_for_text(clipboard_); | 243 gchar* text = gtk_clipboard_wait_for_text(clipboard); |
| 238 if (text) { | 244 if (text) { |
| 239 g_free(text); | 245 g_free(text); |
| 240 retval = true; | 246 retval = true; |
| 241 } | 247 } |
| 242 } | 248 } |
| 243 } | 249 } |
| 244 | 250 |
| 245 GdkAtom format_atom = StringToGdkAtom(format); | 251 GdkAtom format_atom = StringToGdkAtom(format); |
| 246 | 252 |
| 247 for (int i = 0; i < num; i++) { | 253 for (int i = 0; i < num; i++) { |
| 248 if (targets[i] == format_atom) { | 254 if (targets[i] == format_atom) { |
| 249 retval = true; | 255 retval = true; |
| 250 break; | 256 break; |
| 251 } | 257 } |
| 252 } | 258 } |
| 253 | 259 |
| 254 g_free(targets); | 260 g_free(targets); |
| 255 gtk_selection_data_free(data); | 261 gtk_selection_data_free(data); |
| 256 | 262 |
| 257 return retval; | 263 return retval; |
| 258 } | 264 } |
| 259 | 265 |
| 260 bool Clipboard::IsFormatAvailableByString(const std::string& format) const { | 266 bool Clipboard::IsFormatAvailableByString(const std::string& format, |
| 261 return IsFormatAvailable(format); | 267 Clipboard::Buffer buffer) const { |
| 268 return IsFormatAvailable(format, buffer); |
| 262 } | 269 } |
| 263 | 270 |
| 264 void Clipboard::ReadText(string16* result) const { | 271 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const { |
| 272 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
| 273 if (clipboard == NULL) |
| 274 return; |
| 275 |
| 265 result->clear(); | 276 result->clear(); |
| 266 gchar* text = gtk_clipboard_wait_for_text(clipboard_); | 277 gchar* text = gtk_clipboard_wait_for_text(clipboard); |
| 267 | 278 |
| 268 if (text == NULL) | 279 if (text == NULL) |
| 269 return; | 280 return; |
| 270 | 281 |
| 271 // TODO(estade): do we want to handle the possible error here? | 282 // TODO(estade): do we want to handle the possible error here? |
| 272 UTF8ToUTF16(text, strlen(text), result); | 283 UTF8ToUTF16(text, strlen(text), result); |
| 273 g_free(text); | 284 g_free(text); |
| 274 } | 285 } |
| 275 | 286 |
| 276 void Clipboard::ReadAsciiText(std::string* result) const { | 287 void Clipboard::ReadAsciiText(Clipboard::Buffer buffer, |
| 288 std::string* result) const { |
| 289 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
| 290 if (clipboard == NULL) |
| 291 return; |
| 292 |
| 277 result->clear(); | 293 result->clear(); |
| 278 gchar* text = gtk_clipboard_wait_for_text(clipboard_); | 294 gchar* text = gtk_clipboard_wait_for_text(clipboard); |
| 279 | 295 |
| 280 if (text == NULL) | 296 if (text == NULL) |
| 281 return; | 297 return; |
| 282 | 298 |
| 283 result->assign(text); | 299 result->assign(text); |
| 284 g_free(text); | 300 g_free(text); |
| 285 } | 301 } |
| 286 | 302 |
| 287 void Clipboard::ReadFile(FilePath* file) const { | 303 void Clipboard::ReadFile(FilePath* file) const { |
| 288 *file = FilePath(); | 304 *file = FilePath(); |
| 289 } | 305 } |
| 290 | 306 |
| 291 // TODO(estade): handle different charsets. | 307 // TODO(estade): handle different charsets. |
| 292 // TODO(port): set *src_url. | 308 // TODO(port): set *src_url. |
| 293 void Clipboard::ReadHTML(string16* markup, std::string* src_url) const { | 309 void Clipboard::ReadHTML(Clipboard::Buffer buffer, string16* markup, |
| 310 std::string* src_url) const { |
| 311 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
| 312 if (clipboard == NULL) |
| 313 return; |
| 294 markup->clear(); | 314 markup->clear(); |
| 295 | 315 |
| 296 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard_, | 316 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, |
| 297 StringToGdkAtom(GetHtmlFormatType())); | 317 StringToGdkAtom(GetHtmlFormatType())); |
| 298 | 318 |
| 299 if (!data) | 319 if (!data) |
| 300 return; | 320 return; |
| 301 | 321 |
| 302 UTF8ToUTF16(reinterpret_cast<char*>(data->data), data->length, markup); | 322 UTF8ToUTF16(reinterpret_cast<char*>(data->data), data->length, markup); |
| 303 gtk_selection_data_free(data); | 323 gtk_selection_data_free(data); |
| 304 } | 324 } |
| 305 | 325 |
| 306 void Clipboard::ReadBookmark(string16* title, std::string* url) const { | 326 void Clipboard::ReadBookmark(string16* title, std::string* url) const { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 368 |
| 349 if (iter != clipboard_data_->end()) { | 369 if (iter != clipboard_data_->end()) { |
| 350 if (strcmp(kMimeBmp, key) == 0) | 370 if (strcmp(kMimeBmp, key) == 0) |
| 351 g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first)); | 371 g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first)); |
| 352 else | 372 else |
| 353 delete[] iter->second.first; | 373 delete[] iter->second.first; |
| 354 } | 374 } |
| 355 | 375 |
| 356 (*clipboard_data_)[key] = std::make_pair(data, data_len); | 376 (*clipboard_data_)[key] = std::make_pair(data, data_len); |
| 357 } | 377 } |
| 378 |
| 379 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { |
| 380 GtkClipboard* result; |
| 381 |
| 382 switch (clipboard) { |
| 383 case BUFFER_STANDARD: |
| 384 result = clipboard_; |
| 385 break; |
| 386 case BUFFER_SELECTION: |
| 387 result = primary_selection_; |
| 388 break; |
| 389 default: |
| 390 NOTREACHED(); |
| 391 result = NULL; |
| 392 break; |
| 393 } |
| 394 return result; |
| 395 } |
| 396 |
| OLD | NEW |