OLD | NEW |
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> |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 X11AtomCache* atom_cache() { return &atom_cache_; } | 234 X11AtomCache* atom_cache() { return &atom_cache_; } |
235 | 235 |
236 // Returns the X11 type that we pass to various XSelection functions for the | 236 // Returns the X11 type that we pass to various XSelection functions for the |
237 // given type. | 237 // given type. |
238 ::Atom LookupSelectionForClipboardType(ClipboardType type) const; | 238 ::Atom LookupSelectionForClipboardType(ClipboardType type) const; |
239 | 239 |
240 // Returns the X11 type that we pass to various XSelection functions for | 240 // Returns the X11 type that we pass to various XSelection functions for |
241 // CLIPBOARD_TYPE_COPY_PASTE. | 241 // CLIPBOARD_TYPE_COPY_PASTE. |
242 ::Atom GetCopyPasteSelection() const; | 242 ::Atom GetCopyPasteSelection() const; |
243 | 243 |
244 // Returns the object which is responsible for communication on |type|. | |
245 SelectionRequestor* GetSelectionRequestorForClipboardType(ClipboardType type); | |
246 | |
247 // Finds the SelectionFormatMap for the incoming selection atom. | 244 // Finds the SelectionFormatMap for the incoming selection atom. |
248 const SelectionFormatMap& LookupStorageForAtom(::Atom atom); | 245 const SelectionFormatMap& LookupStorageForAtom(::Atom atom); |
249 | 246 |
250 // As we need to collect all the data types before we tell X11 that we own a | 247 // As we need to collect all the data types before we tell X11 that we own a |
251 // particular selection, we create a temporary clipboard mapping that | 248 // particular selection, we create a temporary clipboard mapping that |
252 // InsertMapping writes to. Then we commit it in TakeOwnershipOfSelection, | 249 // InsertMapping writes to. Then we commit it in TakeOwnershipOfSelection, |
253 // where we save it in one of the clipboard data slots. | 250 // where we save it in one of the clipboard data slots. |
254 void CreateNewClipboardData(); | 251 void CreateNewClipboardData(); |
255 | 252 |
256 // Inserts a mapping into clipboard_data_. | 253 // Inserts a mapping into clipboard_data_. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 | 295 |
299 // Our X11 state. | 296 // Our X11 state. |
300 Display* x_display_; | 297 Display* x_display_; |
301 ::Window x_root_window_; | 298 ::Window x_root_window_; |
302 | 299 |
303 // Input-only window used as a selection owner. | 300 // Input-only window used as a selection owner. |
304 ::Window x_window_; | 301 ::Window x_window_; |
305 | 302 |
306 X11AtomCache atom_cache_; | 303 X11AtomCache atom_cache_; |
307 | 304 |
308 // Objects which request and receive selection data. | 305 // Object which requests and receives selection data. |
309 SelectionRequestor clipboard_requestor_; | 306 SelectionRequestor selection_requestor_; |
310 SelectionRequestor primary_requestor_; | |
311 SelectionRequestor clipboard_manager_requestor_; | |
312 | 307 |
313 // Temporary target map that we write to during DispatchObects. | 308 // Temporary target map that we write to during DispatchObects. |
314 SelectionFormatMap clipboard_data_; | 309 SelectionFormatMap clipboard_data_; |
315 | 310 |
316 // Objects which offer selection data to other windows. | 311 // Objects which offer selection data to other windows. |
317 SelectionOwner clipboard_owner_; | 312 SelectionOwner clipboard_owner_; |
318 SelectionOwner primary_owner_; | 313 SelectionOwner primary_owner_; |
319 | 314 |
320 DISALLOW_COPY_AND_ASSIGN(AuraX11Details); | 315 DISALLOW_COPY_AND_ASSIGN(AuraX11Details); |
321 }; | 316 }; |
322 | 317 |
323 Clipboard::AuraX11Details::AuraX11Details() | 318 Clipboard::AuraX11Details::AuraX11Details() |
324 : x_display_(gfx::GetXDisplay()), | 319 : x_display_(gfx::GetXDisplay()), |
325 x_root_window_(DefaultRootWindow(x_display_)), | 320 x_root_window_(DefaultRootWindow(x_display_)), |
326 x_window_(XCreateWindow( | 321 x_window_(XCreateWindow( |
327 x_display_, x_root_window_, | 322 x_display_, x_root_window_, |
328 -100, -100, 10, 10, // x, y, width, height | 323 -100, -100, 10, 10, // x, y, width, height |
329 0, // border width | 324 0, // border width |
330 CopyFromParent, // depth | 325 CopyFromParent, // depth |
331 InputOnly, | 326 InputOnly, |
332 CopyFromParent, // visual | 327 CopyFromParent, // visual |
333 0, | 328 0, |
334 NULL)), | 329 NULL)), |
335 atom_cache_(x_display_, kAtomsToCache), | 330 atom_cache_(x_display_, kAtomsToCache), |
336 clipboard_requestor_(x_display_, x_window_, | 331 selection_requestor_(x_display_, x_window_, this), |
337 atom_cache_.GetAtom(kClipboard), this), | |
338 primary_requestor_(x_display_, x_window_, XA_PRIMARY, this), | |
339 clipboard_manager_requestor_(x_display_, x_window_, | |
340 atom_cache_.GetAtom(kClipboardManager), | |
341 this), | |
342 clipboard_owner_(x_display_, x_window_, atom_cache_.GetAtom(kClipboard)), | 332 clipboard_owner_(x_display_, x_window_, atom_cache_.GetAtom(kClipboard)), |
343 primary_owner_(x_display_, x_window_, XA_PRIMARY) { | 333 primary_owner_(x_display_, x_window_, XA_PRIMARY) { |
344 // We don't know all possible MIME types at compile time. | 334 // We don't know all possible MIME types at compile time. |
345 atom_cache_.allow_uncached_atoms(); | 335 atom_cache_.allow_uncached_atoms(); |
346 | 336 |
347 XStoreName(x_display_, x_window_, "Chromium clipboard"); | 337 XStoreName(x_display_, x_window_, "Chromium clipboard"); |
348 XSelectInput(x_display_, x_window_, PropertyChangeMask); | 338 XSelectInput(x_display_, x_window_, PropertyChangeMask); |
349 | 339 |
350 if (PlatformEventSource::GetInstance()) | 340 if (PlatformEventSource::GetInstance()) |
351 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); | 341 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
(...skipping 20 matching lines...) Expand all Loading... |
372 | 362 |
373 const SelectionFormatMap& Clipboard::AuraX11Details::LookupStorageForAtom( | 363 const SelectionFormatMap& Clipboard::AuraX11Details::LookupStorageForAtom( |
374 ::Atom atom) { | 364 ::Atom atom) { |
375 if (atom == XA_PRIMARY) | 365 if (atom == XA_PRIMARY) |
376 return primary_owner_.selection_format_map(); | 366 return primary_owner_.selection_format_map(); |
377 | 367 |
378 DCHECK_EQ(GetCopyPasteSelection(), atom); | 368 DCHECK_EQ(GetCopyPasteSelection(), atom); |
379 return clipboard_owner_.selection_format_map(); | 369 return clipboard_owner_.selection_format_map(); |
380 } | 370 } |
381 | 371 |
382 ui::SelectionRequestor* | |
383 Clipboard::AuraX11Details::GetSelectionRequestorForClipboardType( | |
384 ClipboardType type) { | |
385 if (type == CLIPBOARD_TYPE_COPY_PASTE) | |
386 return &clipboard_requestor_; | |
387 else | |
388 return &primary_requestor_; | |
389 } | |
390 | |
391 void Clipboard::AuraX11Details::CreateNewClipboardData() { | 372 void Clipboard::AuraX11Details::CreateNewClipboardData() { |
392 clipboard_data_ = SelectionFormatMap(); | 373 clipboard_data_ = SelectionFormatMap(); |
393 } | 374 } |
394 | 375 |
395 void Clipboard::AuraX11Details::InsertMapping( | 376 void Clipboard::AuraX11Details::InsertMapping( |
396 const std::string& key, | 377 const std::string& key, |
397 const scoped_refptr<base::RefCountedMemory>& memory) { | 378 const scoped_refptr<base::RefCountedMemory>& memory) { |
398 ::Atom atom_key = atom_cache_.GetAtom(key.c_str()); | 379 ::Atom atom_key = atom_cache_.GetAtom(key.c_str()); |
399 clipboard_data_.Insert(atom_key, memory); | 380 clipboard_data_.Insert(atom_key, memory); |
400 } | 381 } |
(...skipping 15 matching lines...) Expand all Loading... |
416 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); | 397 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); |
417 | 398 |
418 for (std::vector< ::Atom>::const_iterator it = types.begin(); | 399 for (std::vector< ::Atom>::const_iterator it = types.begin(); |
419 it != types.end(); ++it) { | 400 it != types.end(); ++it) { |
420 SelectionFormatMap::const_iterator format_map_it = format_map.find(*it); | 401 SelectionFormatMap::const_iterator format_map_it = format_map.find(*it); |
421 if (format_map_it != format_map.end()) | 402 if (format_map_it != format_map.end()) |
422 return SelectionData(format_map_it->first, format_map_it->second); | 403 return SelectionData(format_map_it->first, format_map_it->second); |
423 } | 404 } |
424 } else { | 405 } else { |
425 TargetList targets = WaitAndGetTargetsList(type); | 406 TargetList targets = WaitAndGetTargetsList(type); |
426 SelectionRequestor* receiver = GetSelectionRequestorForClipboardType(type); | |
427 | 407 |
| 408 ::Atom selection_name = LookupSelectionForClipboardType(type); |
428 std::vector< ::Atom> intersection; | 409 std::vector< ::Atom> intersection; |
429 ui::GetAtomIntersection(types, targets.target_list(), &intersection); | 410 ui::GetAtomIntersection(types, targets.target_list(), &intersection); |
430 return receiver->RequestAndWaitForTypes(intersection); | 411 return selection_requestor_.RequestAndWaitForTypes(selection_name, |
| 412 intersection); |
431 } | 413 } |
432 | 414 |
433 return SelectionData(); | 415 return SelectionData(); |
434 } | 416 } |
435 | 417 |
436 TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList( | 418 TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList( |
437 ClipboardType type) { | 419 ClipboardType type) { |
438 ::Atom selection_name = LookupSelectionForClipboardType(type); | 420 ::Atom selection_name = LookupSelectionForClipboardType(type); |
439 std::vector< ::Atom> out; | 421 std::vector< ::Atom> out; |
440 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { | 422 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { |
441 // We can local fastpath and return the list of local targets. | 423 // We can local fastpath and return the list of local targets. |
442 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); | 424 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); |
443 | 425 |
444 for (SelectionFormatMap::const_iterator it = format_map.begin(); | 426 for (SelectionFormatMap::const_iterator it = format_map.begin(); |
445 it != format_map.end(); ++it) { | 427 it != format_map.end(); ++it) { |
446 out.push_back(it->first); | 428 out.push_back(it->first); |
447 } | 429 } |
448 } else { | 430 } else { |
449 scoped_refptr<base::RefCountedMemory> data; | 431 scoped_refptr<base::RefCountedMemory> data; |
450 size_t out_data_items = 0; | 432 size_t out_data_items = 0; |
451 ::Atom out_type = None; | 433 ::Atom out_type = None; |
452 | 434 |
453 SelectionRequestor* receiver = GetSelectionRequestorForClipboardType(type); | 435 if (selection_requestor_.PerformBlockingConvertSelection( |
454 if (receiver->PerformBlockingConvertSelection(atom_cache_.GetAtom(kTargets), | 436 selection_name, |
455 &data, | 437 atom_cache_.GetAtom(kTargets), |
456 &out_data_items, | 438 &data, |
457 &out_type)) { | 439 &out_data_items, |
| 440 &out_type)) { |
458 // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) | 441 // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) |
459 if (out_type == XA_ATOM || out_type == atom_cache_.GetAtom(kTargets)) { | 442 if (out_type == XA_ATOM || out_type == atom_cache_.GetAtom(kTargets)) { |
460 const ::Atom* atom_array = | 443 const ::Atom* atom_array = |
461 reinterpret_cast<const ::Atom*>(data->front()); | 444 reinterpret_cast<const ::Atom*>(data->front()); |
462 for (size_t i = 0; i < out_data_items; ++i) | 445 for (size_t i = 0; i < out_data_items; ++i) |
463 out.push_back(atom_array[i]); | 446 out.push_back(atom_array[i]); |
464 } | 447 } |
465 } else { | 448 } else { |
466 // There was no target list. Most Java apps doesn't offer a TARGETS list, | 449 // There was no target list. Most Java apps doesn't offer a TARGETS list, |
467 // even though they AWT to. They will offer individual text types if you | 450 // even though they AWT to. They will offer individual text types if you |
468 // ask. If this is the case we attempt to make sense of the contents as | 451 // ask. If this is the case we attempt to make sense of the contents as |
469 // text. This is pretty unfortunate since it means we have to actually | 452 // text. This is pretty unfortunate since it means we have to actually |
470 // copy the data to see if it is available, but at least this path | 453 // copy the data to see if it is available, but at least this path |
471 // shouldn't be hit for conforming programs. | 454 // shouldn't be hit for conforming programs. |
472 std::vector< ::Atom> types = GetTextAtoms(); | 455 std::vector< ::Atom> types = GetTextAtoms(); |
473 for (std::vector< ::Atom>::const_iterator it = types.begin(); | 456 for (std::vector< ::Atom>::const_iterator it = types.begin(); |
474 it != types.end(); ++it) { | 457 it != types.end(); ++it) { |
475 ::Atom type = None; | 458 ::Atom type = None; |
476 if (receiver->PerformBlockingConvertSelection(*it, | 459 if (selection_requestor_.PerformBlockingConvertSelection(selection_name, |
477 NULL, | 460 *it, |
478 NULL, | 461 NULL, |
479 &type) && | 462 NULL, |
| 463 &type) && |
480 type == *it) { | 464 type == *it) { |
481 out.push_back(*it); | 465 out.push_back(*it); |
482 } | 466 } |
483 } | 467 } |
484 } | 468 } |
485 } | 469 } |
486 | 470 |
487 return TargetList(out, &atom_cache_); | 471 return TargetList(out, &atom_cache_); |
488 } | 472 } |
489 | 473 |
(...skipping 23 matching lines...) Expand all Loading... |
513 ::Atom clipboard_manager_atom = atom_cache_.GetAtom(kClipboardManager); | 497 ::Atom clipboard_manager_atom = atom_cache_.GetAtom(kClipboardManager); |
514 if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == None) | 498 if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == None) |
515 return; | 499 return; |
516 | 500 |
517 const SelectionFormatMap& format_map = LookupStorageForAtom(selection); | 501 const SelectionFormatMap& format_map = LookupStorageForAtom(selection); |
518 if (format_map.size() == 0) | 502 if (format_map.size() == 0) |
519 return; | 503 return; |
520 std::vector<Atom> targets = format_map.GetTypes(); | 504 std::vector<Atom> targets = format_map.GetTypes(); |
521 | 505 |
522 base::TimeTicks start = base::TimeTicks::Now(); | 506 base::TimeTicks start = base::TimeTicks::Now(); |
523 clipboard_manager_requestor_.PerformBlockingConvertSelectionWithParameter( | 507 selection_requestor_.PerformBlockingConvertSelectionWithParameter( |
524 atom_cache_.GetAtom(kSaveTargets), targets); | 508 atom_cache_.GetAtom(kClipboardManager), |
| 509 atom_cache_.GetAtom(kSaveTargets), |
| 510 targets); |
525 UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", | 511 UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", |
526 base::TimeTicks::Now() - start); | 512 base::TimeTicks::Now() - start); |
527 } | 513 } |
528 | 514 |
529 bool Clipboard::AuraX11Details::CanDispatchEvent(const PlatformEvent& event) { | 515 bool Clipboard::AuraX11Details::CanDispatchEvent(const PlatformEvent& event) { |
530 return event->xany.window == x_window_; | 516 return event->xany.window == x_window_; |
531 } | 517 } |
532 | 518 |
533 uint32_t Clipboard::AuraX11Details::DispatchEvent(const PlatformEvent& xev) { | 519 uint32_t Clipboard::AuraX11Details::DispatchEvent(const PlatformEvent& xev) { |
534 switch (xev->type) { | 520 switch (xev->type) { |
535 case SelectionRequest: { | 521 case SelectionRequest: { |
536 if (xev->xselectionrequest.selection == XA_PRIMARY) { | 522 if (xev->xselectionrequest.selection == XA_PRIMARY) { |
537 primary_owner_.OnSelectionRequest(*xev); | 523 primary_owner_.OnSelectionRequest(*xev); |
538 } else { | 524 } else { |
539 // We should not get requests for the CLIPBOARD_MANAGER selection | 525 // We should not get requests for the CLIPBOARD_MANAGER selection |
540 // because we never take ownership of it. | 526 // because we never take ownership of it. |
541 DCHECK_EQ(GetCopyPasteSelection(), xev->xselectionrequest.selection); | 527 DCHECK_EQ(GetCopyPasteSelection(), xev->xselectionrequest.selection); |
542 clipboard_owner_.OnSelectionRequest(*xev); | 528 clipboard_owner_.OnSelectionRequest(*xev); |
543 } | 529 } |
544 break; | 530 break; |
545 } | 531 } |
546 case SelectionNotify: { | 532 case SelectionNotify: { |
547 ::Atom selection = xev->xselection.selection; | 533 selection_requestor_.OnSelectionNotify(*xev); |
548 if (selection == XA_PRIMARY) | |
549 primary_requestor_.OnSelectionNotify(*xev); | |
550 else if (selection == GetCopyPasteSelection()) | |
551 clipboard_requestor_.OnSelectionNotify(*xev); | |
552 else if (selection == atom_cache_.GetAtom(kClipboardManager)) | |
553 clipboard_manager_requestor_.OnSelectionNotify(*xev); | |
554 break; | 534 break; |
555 } | 535 } |
556 case SelectionClear: { | 536 case SelectionClear: { |
557 if (xev->xselectionclear.selection == XA_PRIMARY) { | 537 if (xev->xselectionclear.selection == XA_PRIMARY) { |
558 primary_owner_.OnSelectionClear(*xev); | 538 primary_owner_.OnSelectionClear(*xev); |
559 } else { | 539 } else { |
560 // We should not get requests for the CLIPBOARD_MANAGER selection | 540 // We should not get requests for the CLIPBOARD_MANAGER selection |
561 // because we never take ownership of it. | 541 // because we never take ownership of it. |
562 DCHECK_EQ(GetCopyPasteSelection(), xev->xselection.selection); | 542 DCHECK_EQ(GetCopyPasteSelection(), xev->xselection.selection); |
563 clipboard_owner_.OnSelectionClear(*xev); | 543 clipboard_owner_.OnSelectionClear(*xev); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 return type; | 894 return type; |
915 } | 895 } |
916 | 896 |
917 // static | 897 // static |
918 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { | 898 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { |
919 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); | 899 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); |
920 return type; | 900 return type; |
921 } | 901 } |
922 | 902 |
923 } // namespace ui | 903 } // namespace ui |
OLD | NEW |