| 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_aurax11.h" | 5 #include "ui/base/clipboard/clipboard_aurax11.h" |
| 6 | 6 |
| 7 #include <X11/Xatom.h> | 7 #include <X11/Xatom.h> |
| 8 #include <X11/extensions/Xfixes.h> | 8 #include <X11/extensions/Xfixes.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 #include "ui/base/x/selection_owner.h" | 27 #include "ui/base/x/selection_owner.h" |
| 28 #include "ui/base/x/selection_requestor.h" | 28 #include "ui/base/x/selection_requestor.h" |
| 29 #include "ui/base/x/selection_utils.h" | 29 #include "ui/base/x/selection_utils.h" |
| 30 #include "ui/base/x/x11_util.h" | 30 #include "ui/base/x/x11_util.h" |
| 31 #include "ui/base/x/x11_window_event_manager.h" | 31 #include "ui/base/x/x11_window_event_manager.h" |
| 32 #include "ui/events/platform/platform_event_dispatcher.h" | 32 #include "ui/events/platform/platform_event_dispatcher.h" |
| 33 #include "ui/events/platform/platform_event_observer.h" | 33 #include "ui/events/platform/platform_event_observer.h" |
| 34 #include "ui/events/platform/platform_event_source.h" | 34 #include "ui/events/platform/platform_event_source.h" |
| 35 #include "ui/gfx/codec/png_codec.h" | 35 #include "ui/gfx/codec/png_codec.h" |
| 36 #include "ui/gfx/geometry/size.h" | 36 #include "ui/gfx/geometry/size.h" |
| 37 #include "ui/gfx/x/x11_atom_cache.h" |
| 37 | 38 |
| 38 namespace ui { | 39 namespace ui { |
| 39 | 40 |
| 40 namespace { | 41 namespace { |
| 41 | 42 |
| 42 const char kClipboard[] = "CLIPBOARD"; | 43 const char kClipboard[] = "CLIPBOARD"; |
| 43 const char kClipboardManager[] = "CLIPBOARD_MANAGER"; | 44 const char kClipboardManager[] = "CLIPBOARD_MANAGER"; |
| 44 const char kMimeTypeFilename[] = "chromium/filename"; | 45 const char kMimeTypeFilename[] = "chromium/filename"; |
| 45 const char kSaveTargets[] = "SAVE_TARGETS"; | 46 const char kSaveTargets[] = "SAVE_TARGETS"; |
| 46 const char kTargets[] = "TARGETS"; | 47 const char kTargets[] = "TARGETS"; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 75 DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver); | 76 DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver); |
| 76 }; | 77 }; |
| 77 | 78 |
| 78 SelectionChangeObserver::SelectionChangeObserver() | 79 SelectionChangeObserver::SelectionChangeObserver() |
| 79 : event_base_(-1), | 80 : event_base_(-1), |
| 80 clipboard_atom_(None), | 81 clipboard_atom_(None), |
| 81 clipboard_sequence_number_(0), | 82 clipboard_sequence_number_(0), |
| 82 primary_sequence_number_(0) { | 83 primary_sequence_number_(0) { |
| 83 int ignored; | 84 int ignored; |
| 84 if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) { | 85 if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) { |
| 85 clipboard_atom_ = GetAtom(kClipboard); | 86 clipboard_atom_ = gfx::GetAtom(kClipboard); |
| 86 XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), | 87 XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), |
| 87 clipboard_atom_, | 88 clipboard_atom_, |
| 88 XFixesSetSelectionOwnerNotifyMask | | 89 XFixesSetSelectionOwnerNotifyMask | |
| 89 XFixesSelectionWindowDestroyNotifyMask | | 90 XFixesSelectionWindowDestroyNotifyMask | |
| 90 XFixesSelectionClientCloseNotifyMask); | 91 XFixesSelectionClientCloseNotifyMask); |
| 91 // This seems to be semi-optional. For some reason, registering for any | 92 // This seems to be semi-optional. For some reason, registering for any |
| 92 // selection notify events seems to subscribe us to events for both the | 93 // selection notify events seems to subscribe us to events for both the |
| 93 // primary and the clipboard buffers. Register anyway just to be safe. | 94 // primary and the clipboard buffers. Register anyway just to be safe. |
| 94 XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), | 95 XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), |
| 95 XA_PRIMARY, | 96 XA_PRIMARY, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 it != atoms.end(); ++it) { | 153 it != atoms.end(); ++it) { |
| 153 if (ContainsAtom(*it)) | 154 if (ContainsAtom(*it)) |
| 154 return true; | 155 return true; |
| 155 } | 156 } |
| 156 | 157 |
| 157 return false; | 158 return false; |
| 158 } | 159 } |
| 159 | 160 |
| 160 bool TargetList::ContainsFormat( | 161 bool TargetList::ContainsFormat( |
| 161 const Clipboard::FormatType& format_type) const { | 162 const Clipboard::FormatType& format_type) const { |
| 162 ::Atom atom = GetAtom(format_type.ToString().c_str()); | 163 ::Atom atom = gfx::GetAtom(format_type.ToString().c_str()); |
| 163 return ContainsAtom(atom); | 164 return ContainsAtom(atom); |
| 164 } | 165 } |
| 165 | 166 |
| 166 bool TargetList::ContainsAtom(::Atom atom) const { | 167 bool TargetList::ContainsAtom(::Atom atom) const { |
| 167 return find(target_list_.begin(), target_list_.end(), atom) | 168 return find(target_list_.begin(), target_list_.end(), atom) |
| 168 != target_list_.end(); | 169 != target_list_.end(); |
| 169 } | 170 } |
| 170 | 171 |
| 171 } // namespace | 172 } // namespace |
| 172 | 173 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 -100, | 308 -100, |
| 308 10, | 309 10, |
| 309 10, // x, y, width, height | 310 10, // x, y, width, height |
| 310 0, // border width | 311 0, // border width |
| 311 CopyFromParent, // depth | 312 CopyFromParent, // depth |
| 312 InputOnly, | 313 InputOnly, |
| 313 CopyFromParent, // visual | 314 CopyFromParent, // visual |
| 314 0, | 315 0, |
| 315 NULL)), | 316 NULL)), |
| 316 selection_requestor_(x_display_, x_window_, this), | 317 selection_requestor_(x_display_, x_window_, this), |
| 317 clipboard_owner_(x_display_, x_window_, GetAtom(kClipboard)), | 318 clipboard_owner_(x_display_, x_window_, gfx::GetAtom(kClipboard)), |
| 318 primary_owner_(x_display_, x_window_, XA_PRIMARY) { | 319 primary_owner_(x_display_, x_window_, XA_PRIMARY) { |
| 319 XStoreName(x_display_, x_window_, "Chromium clipboard"); | 320 XStoreName(x_display_, x_window_, "Chromium clipboard"); |
| 320 x_window_events_.reset( | 321 x_window_events_.reset( |
| 321 new XScopedEventSelector(x_window_, PropertyChangeMask)); | 322 new XScopedEventSelector(x_window_, PropertyChangeMask)); |
| 322 | 323 |
| 323 if (PlatformEventSource::GetInstance()) | 324 if (PlatformEventSource::GetInstance()) |
| 324 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); | 325 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
| 325 } | 326 } |
| 326 | 327 |
| 327 ClipboardAuraX11::AuraX11Details::~AuraX11Details() { | 328 ClipboardAuraX11::AuraX11Details::~AuraX11Details() { |
| 328 if (PlatformEventSource::GetInstance()) | 329 if (PlatformEventSource::GetInstance()) |
| 329 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); | 330 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); |
| 330 | 331 |
| 331 XDestroyWindow(x_display_, x_window_); | 332 XDestroyWindow(x_display_, x_window_); |
| 332 } | 333 } |
| 333 | 334 |
| 334 ::Atom ClipboardAuraX11::AuraX11Details::LookupSelectionForClipboardType( | 335 ::Atom ClipboardAuraX11::AuraX11Details::LookupSelectionForClipboardType( |
| 335 ClipboardType type) const { | 336 ClipboardType type) const { |
| 336 if (type == CLIPBOARD_TYPE_COPY_PASTE) | 337 if (type == CLIPBOARD_TYPE_COPY_PASTE) |
| 337 return GetCopyPasteSelection(); | 338 return GetCopyPasteSelection(); |
| 338 | 339 |
| 339 return XA_PRIMARY; | 340 return XA_PRIMARY; |
| 340 } | 341 } |
| 341 | 342 |
| 342 ::Atom ClipboardAuraX11::AuraX11Details::GetCopyPasteSelection() const { | 343 ::Atom ClipboardAuraX11::AuraX11Details::GetCopyPasteSelection() const { |
| 343 return GetAtom(kClipboard); | 344 return gfx::GetAtom(kClipboard); |
| 344 } | 345 } |
| 345 | 346 |
| 346 const SelectionFormatMap& | 347 const SelectionFormatMap& |
| 347 ClipboardAuraX11::AuraX11Details::LookupStorageForAtom(::Atom atom) { | 348 ClipboardAuraX11::AuraX11Details::LookupStorageForAtom(::Atom atom) { |
| 348 if (atom == XA_PRIMARY) | 349 if (atom == XA_PRIMARY) |
| 349 return primary_owner_.selection_format_map(); | 350 return primary_owner_.selection_format_map(); |
| 350 | 351 |
| 351 DCHECK_EQ(GetCopyPasteSelection(), atom); | 352 DCHECK_EQ(GetCopyPasteSelection(), atom); |
| 352 return clipboard_owner_.selection_format_map(); | 353 return clipboard_owner_.selection_format_map(); |
| 353 } | 354 } |
| 354 | 355 |
| 355 void ClipboardAuraX11::AuraX11Details::CreateNewClipboardData() { | 356 void ClipboardAuraX11::AuraX11Details::CreateNewClipboardData() { |
| 356 clipboard_data_ = SelectionFormatMap(); | 357 clipboard_data_ = SelectionFormatMap(); |
| 357 } | 358 } |
| 358 | 359 |
| 359 void ClipboardAuraX11::AuraX11Details::InsertMapping( | 360 void ClipboardAuraX11::AuraX11Details::InsertMapping( |
| 360 const std::string& key, | 361 const std::string& key, |
| 361 const scoped_refptr<base::RefCountedMemory>& memory) { | 362 const scoped_refptr<base::RefCountedMemory>& memory) { |
| 362 ::Atom atom_key = GetAtom(key.c_str()); | 363 ::Atom atom_key = gfx::GetAtom(key.c_str()); |
| 363 clipboard_data_.Insert(atom_key, memory); | 364 clipboard_data_.Insert(atom_key, memory); |
| 364 } | 365 } |
| 365 | 366 |
| 366 void ClipboardAuraX11::AuraX11Details::TakeOwnershipOfSelection( | 367 void ClipboardAuraX11::AuraX11Details::TakeOwnershipOfSelection( |
| 367 ClipboardType type) { | 368 ClipboardType type) { |
| 368 if (type == CLIPBOARD_TYPE_COPY_PASTE) | 369 if (type == CLIPBOARD_TYPE_COPY_PASTE) |
| 369 return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_); | 370 return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_); |
| 370 else | 371 else |
| 371 return primary_owner_.TakeOwnershipOfSelection(clipboard_data_); | 372 return primary_owner_.TakeOwnershipOfSelection(clipboard_data_); |
| 372 } | 373 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 384 it != types.end(); ++it) { | 385 it != types.end(); ++it) { |
| 385 SelectionFormatMap::const_iterator format_map_it = format_map.find(*it); | 386 SelectionFormatMap::const_iterator format_map_it = format_map.find(*it); |
| 386 if (format_map_it != format_map.end()) | 387 if (format_map_it != format_map.end()) |
| 387 return SelectionData(format_map_it->first, format_map_it->second); | 388 return SelectionData(format_map_it->first, format_map_it->second); |
| 388 } | 389 } |
| 389 } else { | 390 } else { |
| 390 TargetList targets = WaitAndGetTargetsList(type); | 391 TargetList targets = WaitAndGetTargetsList(type); |
| 391 | 392 |
| 392 ::Atom selection_name = LookupSelectionForClipboardType(type); | 393 ::Atom selection_name = LookupSelectionForClipboardType(type); |
| 393 std::vector< ::Atom> intersection; | 394 std::vector< ::Atom> intersection; |
| 394 ui::GetAtomIntersection(types, targets.target_list(), &intersection); | 395 GetAtomIntersection(types, targets.target_list(), &intersection); |
| 395 return selection_requestor_.RequestAndWaitForTypes(selection_name, | 396 return selection_requestor_.RequestAndWaitForTypes(selection_name, |
| 396 intersection); | 397 intersection); |
| 397 } | 398 } |
| 398 | 399 |
| 399 return SelectionData(); | 400 return SelectionData(); |
| 400 } | 401 } |
| 401 | 402 |
| 402 TargetList ClipboardAuraX11::AuraX11Details::WaitAndGetTargetsList( | 403 TargetList ClipboardAuraX11::AuraX11Details::WaitAndGetTargetsList( |
| 403 ClipboardType type) { | 404 ClipboardType type) { |
| 404 ::Atom selection_name = LookupSelectionForClipboardType(type); | 405 ::Atom selection_name = LookupSelectionForClipboardType(type); |
| 405 std::vector< ::Atom> out; | 406 std::vector< ::Atom> out; |
| 406 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { | 407 if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { |
| 407 // We can local fastpath and return the list of local targets. | 408 // We can local fastpath and return the list of local targets. |
| 408 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); | 409 const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); |
| 409 | 410 |
| 410 for (SelectionFormatMap::const_iterator it = format_map.begin(); | 411 for (SelectionFormatMap::const_iterator it = format_map.begin(); |
| 411 it != format_map.end(); ++it) { | 412 it != format_map.end(); ++it) { |
| 412 out.push_back(it->first); | 413 out.push_back(it->first); |
| 413 } | 414 } |
| 414 } else { | 415 } else { |
| 415 scoped_refptr<base::RefCountedMemory> data; | 416 scoped_refptr<base::RefCountedMemory> data; |
| 416 size_t out_data_items = 0; | 417 size_t out_data_items = 0; |
| 417 ::Atom out_type = None; | 418 ::Atom out_type = None; |
| 418 | 419 |
| 419 if (selection_requestor_.PerformBlockingConvertSelection( | 420 if (selection_requestor_.PerformBlockingConvertSelection( |
| 420 selection_name, GetAtom(kTargets), &data, &out_data_items, | 421 selection_name, gfx::GetAtom(kTargets), &data, &out_data_items, |
| 421 &out_type)) { | 422 &out_type)) { |
| 422 // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) | 423 // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) |
| 423 if (out_type == XA_ATOM || out_type == GetAtom(kTargets)) { | 424 if (out_type == XA_ATOM || out_type == gfx::GetAtom(kTargets)) { |
| 424 const ::Atom* atom_array = | 425 const ::Atom* atom_array = |
| 425 reinterpret_cast<const ::Atom*>(data->front()); | 426 reinterpret_cast<const ::Atom*>(data->front()); |
| 426 for (size_t i = 0; i < out_data_items; ++i) | 427 for (size_t i = 0; i < out_data_items; ++i) |
| 427 out.push_back(atom_array[i]); | 428 out.push_back(atom_array[i]); |
| 428 } | 429 } |
| 429 } else { | 430 } else { |
| 430 // There was no target list. Most Java apps doesn't offer a TARGETS list, | 431 // There was no target list. Most Java apps doesn't offer a TARGETS list, |
| 431 // even though they AWT to. They will offer individual text types if you | 432 // even though they AWT to. They will offer individual text types if you |
| 432 // ask. If this is the case we attempt to make sense of the contents as | 433 // ask. If this is the case we attempt to make sense of the contents as |
| 433 // text. This is pretty unfortunate since it means we have to actually | 434 // text. This is pretty unfortunate since it means we have to actually |
| (...skipping 18 matching lines...) Expand all Loading... |
| 452 return TargetList(out); | 453 return TargetList(out); |
| 453 } | 454 } |
| 454 | 455 |
| 455 std::vector<::Atom> ClipboardAuraX11::AuraX11Details::GetTextAtoms() const { | 456 std::vector<::Atom> ClipboardAuraX11::AuraX11Details::GetTextAtoms() const { |
| 456 return GetTextAtomsFrom(); | 457 return GetTextAtomsFrom(); |
| 457 } | 458 } |
| 458 | 459 |
| 459 std::vector<::Atom> ClipboardAuraX11::AuraX11Details::GetAtomsForFormat( | 460 std::vector<::Atom> ClipboardAuraX11::AuraX11Details::GetAtomsForFormat( |
| 460 const Clipboard::FormatType& format) { | 461 const Clipboard::FormatType& format) { |
| 461 std::vector< ::Atom> atoms; | 462 std::vector< ::Atom> atoms; |
| 462 atoms.push_back(GetAtom(format.ToString().c_str())); | 463 atoms.push_back(gfx::GetAtom(format.ToString().c_str())); |
| 463 return atoms; | 464 return atoms; |
| 464 } | 465 } |
| 465 | 466 |
| 466 void ClipboardAuraX11::AuraX11Details::Clear(ClipboardType type) { | 467 void ClipboardAuraX11::AuraX11Details::Clear(ClipboardType type) { |
| 467 if (type == CLIPBOARD_TYPE_COPY_PASTE) | 468 if (type == CLIPBOARD_TYPE_COPY_PASTE) |
| 468 clipboard_owner_.ClearSelectionOwner(); | 469 clipboard_owner_.ClearSelectionOwner(); |
| 469 else | 470 else |
| 470 primary_owner_.ClearSelectionOwner(); | 471 primary_owner_.ClearSelectionOwner(); |
| 471 } | 472 } |
| 472 | 473 |
| 473 void ClipboardAuraX11::AuraX11Details::StoreCopyPasteDataAndWait() { | 474 void ClipboardAuraX11::AuraX11Details::StoreCopyPasteDataAndWait() { |
| 474 ::Atom selection = GetCopyPasteSelection(); | 475 ::Atom selection = GetCopyPasteSelection(); |
| 475 if (XGetSelectionOwner(x_display_, selection) != x_window_) | 476 if (XGetSelectionOwner(x_display_, selection) != x_window_) |
| 476 return; | 477 return; |
| 477 | 478 |
| 478 ::Atom clipboard_manager_atom = GetAtom(kClipboardManager); | 479 ::Atom clipboard_manager_atom = gfx::GetAtom(kClipboardManager); |
| 479 if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == None) | 480 if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == None) |
| 480 return; | 481 return; |
| 481 | 482 |
| 482 const SelectionFormatMap& format_map = LookupStorageForAtom(selection); | 483 const SelectionFormatMap& format_map = LookupStorageForAtom(selection); |
| 483 if (format_map.size() == 0) | 484 if (format_map.size() == 0) |
| 484 return; | 485 return; |
| 485 std::vector<Atom> targets = format_map.GetTypes(); | 486 std::vector<Atom> targets = format_map.GetTypes(); |
| 486 | 487 |
| 487 base::TimeTicks start = base::TimeTicks::Now(); | 488 base::TimeTicks start = base::TimeTicks::Now(); |
| 488 selection_requestor_.PerformBlockingConvertSelectionWithParameter( | 489 selection_requestor_.PerformBlockingConvertSelectionWithParameter( |
| 489 GetAtom(kClipboardManager), GetAtom(kSaveTargets), targets); | 490 gfx::GetAtom(kClipboardManager), gfx::GetAtom(kSaveTargets), targets); |
| 490 UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", | 491 UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", |
| 491 base::TimeTicks::Now() - start); | 492 base::TimeTicks::Now() - start); |
| 492 } | 493 } |
| 493 | 494 |
| 494 bool ClipboardAuraX11::AuraX11Details::CanDispatchEvent( | 495 bool ClipboardAuraX11::AuraX11Details::CanDispatchEvent( |
| 495 const PlatformEvent& event) { | 496 const PlatformEvent& event) { |
| 496 if (event->xany.window == x_window_) | 497 if (event->xany.window == x_window_) |
| 497 return true; | 498 return true; |
| 498 | 499 |
| 499 if (event->type == PropertyNotify) { | 500 if (event->type == PropertyNotify) { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 if (format.Equals(GetBitmapFormatType())) | 915 if (format.Equals(GetBitmapFormatType())) |
| 915 return; | 916 return; |
| 916 | 917 |
| 917 std::vector<unsigned char> bytes(data_data, data_data + data_len); | 918 std::vector<unsigned char> bytes(data_data, data_data + data_len); |
| 918 scoped_refptr<base::RefCountedMemory> mem( | 919 scoped_refptr<base::RefCountedMemory> mem( |
| 919 base::RefCountedBytes::TakeVector(&bytes)); | 920 base::RefCountedBytes::TakeVector(&bytes)); |
| 920 aurax11_details_->InsertMapping(format.ToString(), mem); | 921 aurax11_details_->InsertMapping(format.ToString(), mem); |
| 921 } | 922 } |
| 922 | 923 |
| 923 } // namespace ui | 924 } // namespace ui |
| OLD | NEW |