| 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 |