| 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/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" | 5 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
| 10 | 10 |
| 11 #include "base/event_types.h" | 11 #include "base/event_types.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 17 #include "third_party/skia/include/core/SkBitmap.h" | 17 #include "third_party/skia/include/core/SkBitmap.h" |
| 18 #include "ui/aura/client/capture_client.h" | 18 #include "ui/aura/client/capture_client.h" |
| 19 #include "ui/aura/client/drag_drop_client.h" | 19 #include "ui/aura/client/drag_drop_client.h" |
| 20 #include "ui/aura/client/drag_drop_delegate.h" | 20 #include "ui/aura/client/drag_drop_delegate.h" |
| 21 #include "ui/aura/window.h" | 21 #include "ui/aura/window.h" |
| 22 #include "ui/aura/window_tree_host.h" | 22 #include "ui/aura/window_tree_host.h" |
| 23 #include "ui/base/clipboard/clipboard.h" | 23 #include "ui/base/clipboard/clipboard.h" |
| 24 #include "ui/base/dragdrop/drop_target_event.h" | 24 #include "ui/base/dragdrop/drop_target_event.h" |
| 25 #include "ui/base/dragdrop/os_exchange_data.h" | 25 #include "ui/base/dragdrop/os_exchange_data.h" |
| 26 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" | 26 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" |
| 27 #include "ui/base/layout.h" | 27 #include "ui/base/layout.h" |
| 28 #include "ui/base/x/selection_utils.h" | 28 #include "ui/base/x/selection_utils.h" |
| 29 #include "ui/base/x/x11_util.h" | |
| 30 #include "ui/base/x/x11_window_event_manager.h" | 29 #include "ui/base/x/x11_window_event_manager.h" |
| 31 #include "ui/display/screen.h" | 30 #include "ui/display/screen.h" |
| 32 #include "ui/events/event.h" | 31 #include "ui/events/event.h" |
| 33 #include "ui/events/event_utils.h" | 32 #include "ui/events/event_utils.h" |
| 34 #include "ui/events/platform/platform_event_source.h" | 33 #include "ui/events/platform/platform_event_source.h" |
| 35 #include "ui/gfx/image/image_skia.h" | 34 #include "ui/gfx/image/image_skia.h" |
| 35 #include "ui/gfx/x/x11_atom_cache.h" |
| 36 #include "ui/views/controls/image_view.h" | 36 #include "ui/views/controls/image_view.h" |
| 37 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" | 37 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" |
| 38 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" | 38 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" |
| 39 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" | 39 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" |
| 40 #include "ui/views/widget/widget.h" | 40 #include "ui/views/widget/widget.h" |
| 41 | 41 |
| 42 // Reading recommended for understanding the implementation in this file: | 42 // Reading recommended for understanding the implementation in this file: |
| 43 // | 43 // |
| 44 // * The X Window System Concepts section in The X New Developer’s Guide | 44 // * The X Window System Concepts section in The X New Developer’s Guide |
| 45 // * The X Selection Mechanism paper by Keith Packard | 45 // * The X Selection Mechanism paper by Keith Packard |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 source_window_(event.data.l[0]), | 305 source_window_(event.data.l[0]), |
| 306 source_client_( | 306 source_client_( |
| 307 DesktopDragDropClientAuraX11::GetForWindow(source_window_)), | 307 DesktopDragDropClientAuraX11::GetForWindow(source_window_)), |
| 308 drag_drop_client_(NULL), | 308 drag_drop_client_(NULL), |
| 309 waiting_to_handle_position_(false), | 309 waiting_to_handle_position_(false), |
| 310 suggested_action_(None) { | 310 suggested_action_(None) { |
| 311 if (!source_client_) { | 311 if (!source_client_) { |
| 312 bool get_types_from_property = ((event.data.l[1] & 1) != 0); | 312 bool get_types_from_property = ((event.data.l[1] & 1) != 0); |
| 313 | 313 |
| 314 if (get_types_from_property) { | 314 if (get_types_from_property) { |
| 315 if (!ui::GetAtomArrayProperty(source_window_, | 315 if (!ui::GetAtomArrayProperty(source_window_, kXdndTypeList, |
| 316 kXdndTypeList, | |
| 317 &unfetched_targets_)) { | 316 &unfetched_targets_)) { |
| 318 return; | 317 return; |
| 319 } | 318 } |
| 320 } else { | 319 } else { |
| 321 // data.l[2,3,4] contain the first three types. Unused slots can be None. | 320 // data.l[2,3,4] contain the first three types. Unused slots can be None. |
| 322 for (int i = 0; i < 3; ++i) { | 321 for (int i = 0; i < 3; ++i) { |
| 323 if (event.data.l[2 + i] != None) { | 322 if (event.data.l[2 + i] != None) { |
| 324 unfetched_targets_.push_back(event.data.l[2 + i]); | 323 unfetched_targets_.push_back(event.data.l[2 + i]); |
| 325 } | 324 } |
| 326 } | 325 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 } | 383 } |
| 385 | 384 |
| 386 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { | 385 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { |
| 387 DCHECK(!unfetched_targets_.empty()); | 386 DCHECK(!unfetched_targets_.empty()); |
| 388 DCHECK(drag_drop_client_); | 387 DCHECK(drag_drop_client_); |
| 389 DCHECK(waiting_to_handle_position_); | 388 DCHECK(waiting_to_handle_position_); |
| 390 | 389 |
| 391 ::Atom target = unfetched_targets_.back(); | 390 ::Atom target = unfetched_targets_.back(); |
| 392 unfetched_targets_.pop_back(); | 391 unfetched_targets_.pop_back(); |
| 393 | 392 |
| 394 XConvertSelection(gfx::GetXDisplay(), ui::GetAtom(kXdndSelection), target, | 393 XConvertSelection(gfx::GetXDisplay(), gfx::GetAtom(kXdndSelection), target, |
| 395 ui::GetAtom(kChromiumDragReciever), local_window_, | 394 gfx::GetAtom(kChromiumDragReciever), local_window_, |
| 396 position_time_stamp_); | 395 position_time_stamp_); |
| 397 } | 396 } |
| 398 | 397 |
| 399 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify( | 398 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify( |
| 400 const XSelectionEvent& event) { | 399 const XSelectionEvent& event) { |
| 401 if (!waiting_to_handle_position_) { | 400 if (!waiting_to_handle_position_) { |
| 402 // A misbehaved window may send SelectionNotify without us requesting data | 401 // A misbehaved window may send SelectionNotify without us requesting data |
| 403 // via XConvertSelection(). | 402 // via XConvertSelection(). |
| 404 return; | 403 return; |
| 405 } | 404 } |
| 406 DCHECK(drag_drop_client_); | 405 DCHECK(drag_drop_client_); |
| 407 | 406 |
| 408 DVLOG(1) << "SelectionNotify, format " << event.target; | 407 DVLOG(1) << "SelectionNotify, format " << event.target; |
| 409 | 408 |
| 410 if (event.property != None) { | 409 if (event.property != None) { |
| 411 DCHECK_EQ(event.property, ui::GetAtom(kChromiumDragReciever)); | 410 DCHECK_EQ(event.property, gfx::GetAtom(kChromiumDragReciever)); |
| 412 | 411 |
| 413 scoped_refptr<base::RefCountedMemory> data; | 412 scoped_refptr<base::RefCountedMemory> data; |
| 414 ::Atom type = None; | 413 ::Atom type = None; |
| 415 if (ui::GetRawBytesOfProperty(local_window_, event.property, | 414 if (ui::GetRawBytesOfProperty(local_window_, event.property, |
| 416 &data, NULL, &type)) { | 415 &data, NULL, &type)) { |
| 417 fetched_targets_.Insert(event.target, data); | 416 fetched_targets_.Insert(event.target, data); |
| 418 } | 417 } |
| 419 } else { | 418 } else { |
| 420 // The source failed to convert the drop data to the format (target in X11 | 419 // The source failed to convert the drop data to the format (target in X11 |
| 421 // parlance) that we asked for. This happens, even though we only ask for | 420 // parlance) that we asked for. This happens, even though we only ask for |
| 422 // the formats advertised by the source. http://crbug.com/628099 | 421 // the formats advertised by the source. http://crbug.com/628099 |
| 423 LOG(ERROR) << "XConvertSelection failed for source-advertised target " | 422 LOG(ERROR) << "XConvertSelection failed for source-advertised target " |
| 424 << event.target; | 423 << event.target; |
| 425 } | 424 } |
| 426 | 425 |
| 427 if (!unfetched_targets_.empty()) { | 426 if (!unfetched_targets_.empty()) { |
| 428 RequestNextTarget(); | 427 RequestNextTarget(); |
| 429 } else { | 428 } else { |
| 430 waiting_to_handle_position_ = false; | 429 waiting_to_handle_position_ = false; |
| 431 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_); | 430 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_); |
| 432 drag_drop_client_ = NULL; | 431 drag_drop_client_ = NULL; |
| 433 } | 432 } |
| 434 } | 433 } |
| 435 | 434 |
| 436 void DesktopDragDropClientAuraX11::X11DragContext::ReadActions() { | 435 void DesktopDragDropClientAuraX11::X11DragContext::ReadActions() { |
| 437 if (!source_client_) { | 436 if (!source_client_) { |
| 438 std::vector<::Atom> atom_array; | 437 std::vector<::Atom> atom_array; |
| 439 if (!ui::GetAtomArrayProperty(source_window_, | 438 if (!ui::GetAtomArrayProperty(source_window_, kXdndActionList, |
| 440 kXdndActionList, | |
| 441 &atom_array)) { | 439 &atom_array)) { |
| 442 actions_.clear(); | 440 actions_.clear(); |
| 443 } else { | 441 } else { |
| 444 actions_.swap(atom_array); | 442 actions_.swap(atom_array); |
| 445 } | 443 } |
| 446 } else { | 444 } else { |
| 447 // We have a property notify set up for other windows in case they change | 445 // We have a property notify set up for other windows in case they change |
| 448 // their action list. Thankfully, the views interface is static and you | 446 // their action list. Thankfully, the views interface is static and you |
| 449 // can't change the action list after you enter StartDragAndDrop(). | 447 // can't change the action list after you enter StartDragAndDrop(). |
| 450 actions_ = source_client_->GetOfferedDragOperations(); | 448 actions_ = source_client_->GetOfferedDragOperations(); |
| 451 } | 449 } |
| 452 } | 450 } |
| 453 | 451 |
| 454 int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const { | 452 int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const { |
| 455 int drag_operation = ui::DragDropTypes::DRAG_NONE; | 453 int drag_operation = ui::DragDropTypes::DRAG_NONE; |
| 456 for (std::vector<::Atom>::const_iterator it = actions_.begin(); | 454 for (std::vector<::Atom>::const_iterator it = actions_.begin(); |
| 457 it != actions_.end(); ++it) { | 455 it != actions_.end(); ++it) { |
| 458 MaskOperation(*it, &drag_operation); | 456 MaskOperation(*it, &drag_operation); |
| 459 } | 457 } |
| 460 | 458 |
| 461 MaskOperation(suggested_action_, &drag_operation); | 459 MaskOperation(suggested_action_, &drag_operation); |
| 462 | 460 |
| 463 return drag_operation; | 461 return drag_operation; |
| 464 } | 462 } |
| 465 | 463 |
| 466 void DesktopDragDropClientAuraX11::X11DragContext::MaskOperation( | 464 void DesktopDragDropClientAuraX11::X11DragContext::MaskOperation( |
| 467 ::Atom xdnd_operation, | 465 ::Atom xdnd_operation, |
| 468 int* drag_operation) const { | 466 int* drag_operation) const { |
| 469 if (xdnd_operation == ui::GetAtom(kXdndActionCopy)) | 467 if (xdnd_operation == gfx::GetAtom(kXdndActionCopy)) |
| 470 *drag_operation |= ui::DragDropTypes::DRAG_COPY; | 468 *drag_operation |= ui::DragDropTypes::DRAG_COPY; |
| 471 else if (xdnd_operation == ui::GetAtom(kXdndActionMove)) | 469 else if (xdnd_operation == gfx::GetAtom(kXdndActionMove)) |
| 472 *drag_operation |= ui::DragDropTypes::DRAG_MOVE; | 470 *drag_operation |= ui::DragDropTypes::DRAG_MOVE; |
| 473 else if (xdnd_operation == ui::GetAtom(kXdndActionLink)) | 471 else if (xdnd_operation == gfx::GetAtom(kXdndActionLink)) |
| 474 *drag_operation |= ui::DragDropTypes::DRAG_LINK; | 472 *drag_operation |= ui::DragDropTypes::DRAG_LINK; |
| 475 } | 473 } |
| 476 | 474 |
| 477 bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent( | 475 bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent( |
| 478 const ui::PlatformEvent& event) { | 476 const ui::PlatformEvent& event) { |
| 479 return event->xany.window == source_window_; | 477 return event->xany.window == source_window_; |
| 480 } | 478 } |
| 481 | 479 |
| 482 uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent( | 480 uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent( |
| 483 const ui::PlatformEvent& event) { | 481 const ui::PlatformEvent& event) { |
| 484 if (event->type == PropertyNotify && | 482 if (event->type == PropertyNotify && |
| 485 event->xproperty.atom == ui::GetAtom(kXdndActionList)) { | 483 event->xproperty.atom == gfx::GetAtom(kXdndActionList)) { |
| 486 ReadActions(); | 484 ReadActions(); |
| 487 return ui::POST_DISPATCH_STOP_PROPAGATION; | 485 return ui::POST_DISPATCH_STOP_PROPAGATION; |
| 488 } | 486 } |
| 489 return ui::POST_DISPATCH_NONE; | 487 return ui::POST_DISPATCH_NONE; |
| 490 } | 488 } |
| 491 | 489 |
| 492 /////////////////////////////////////////////////////////////////////////////// | 490 /////////////////////////////////////////////////////////////////////////////// |
| 493 | 491 |
| 494 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( | 492 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( |
| 495 aura::Window* root_window, | 493 aura::Window* root_window, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 509 source_state_(SOURCE_STATE_OTHER), | 507 source_state_(SOURCE_STATE_OTHER), |
| 510 drag_operation_(0), | 508 drag_operation_(0), |
| 511 negotiated_operation_(ui::DragDropTypes::DRAG_NONE), | 509 negotiated_operation_(ui::DragDropTypes::DRAG_NONE), |
| 512 weak_ptr_factory_(this) { | 510 weak_ptr_factory_(this) { |
| 513 // Some tests change the DesktopDragDropClientAuraX11 associated with an | 511 // Some tests change the DesktopDragDropClientAuraX11 associated with an |
| 514 // |xwindow|. | 512 // |xwindow|. |
| 515 g_live_client_map.Get()[xwindow] = this; | 513 g_live_client_map.Get()[xwindow] = this; |
| 516 | 514 |
| 517 // Mark that we are aware of drag and drop concepts. | 515 // Mark that we are aware of drag and drop concepts. |
| 518 unsigned long xdnd_version = kMaxXdndVersion; | 516 unsigned long xdnd_version = kMaxXdndVersion; |
| 519 XChangeProperty(xdisplay_, xwindow_, ui::GetAtom(kXdndAware), XA_ATOM, 32, | 517 XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndAware), XA_ATOM, 32, |
| 520 PropModeReplace, | 518 PropModeReplace, |
| 521 reinterpret_cast<unsigned char*>(&xdnd_version), 1); | 519 reinterpret_cast<unsigned char*>(&xdnd_version), 1); |
| 522 } | 520 } |
| 523 | 521 |
| 524 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { | 522 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() { |
| 525 // This is necessary when the parent native widget gets destroyed while a drag | 523 // This is necessary when the parent native widget gets destroyed while a drag |
| 526 // operation is in progress. | 524 // operation is in progress. |
| 527 move_loop_->EndMoveLoop(); | 525 move_loop_->EndMoveLoop(); |
| 528 NotifyDragLeave(); | 526 NotifyDragLeave(); |
| 529 | 527 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 | 717 |
| 720 drag_operation = delegate->OnPerformDrop(event); | 718 drag_operation = delegate->OnPerformDrop(event); |
| 721 } | 719 } |
| 722 | 720 |
| 723 target_window_->RemoveObserver(this); | 721 target_window_->RemoveObserver(this); |
| 724 target_window_ = NULL; | 722 target_window_ = NULL; |
| 725 } | 723 } |
| 726 | 724 |
| 727 XEvent xev; | 725 XEvent xev; |
| 728 xev.xclient.type = ClientMessage; | 726 xev.xclient.type = ClientMessage; |
| 729 xev.xclient.message_type = ui::GetAtom(kXdndFinished); | 727 xev.xclient.message_type = gfx::GetAtom(kXdndFinished); |
| 730 xev.xclient.format = 32; | 728 xev.xclient.format = 32; |
| 731 xev.xclient.window = source_window; | 729 xev.xclient.window = source_window; |
| 732 xev.xclient.data.l[0] = xwindow_; | 730 xev.xclient.data.l[0] = xwindow_; |
| 733 xev.xclient.data.l[1] = (drag_operation != 0) ? 1 : 0; | 731 xev.xclient.data.l[1] = (drag_operation != 0) ? 1 : 0; |
| 734 xev.xclient.data.l[2] = DragOperationToAtom(drag_operation); | 732 xev.xclient.data.l[2] = DragOperationToAtom(drag_operation); |
| 735 | 733 |
| 736 SendXClientEvent(source_window, &xev); | 734 SendXClientEvent(source_window, &xev); |
| 737 } | 735 } |
| 738 | 736 |
| 739 void DesktopDragDropClientAuraX11::OnSelectionNotify( | 737 void DesktopDragDropClientAuraX11::OnSelectionNotify( |
| (...skipping 28 matching lines...) Expand all Loading... |
| 768 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; | 766 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; |
| 769 | 767 |
| 770 const ui::OSExchangeData::Provider* provider = &data.provider(); | 768 const ui::OSExchangeData::Provider* provider = &data.provider(); |
| 771 source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>( | 769 source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>( |
| 772 provider); | 770 provider); |
| 773 | 771 |
| 774 source_provider_->TakeOwnershipOfSelection(); | 772 source_provider_->TakeOwnershipOfSelection(); |
| 775 | 773 |
| 776 std::vector<::Atom> actions = GetOfferedDragOperations(); | 774 std::vector<::Atom> actions = GetOfferedDragOperations(); |
| 777 if (!source_provider_->file_contents_name().empty()) { | 775 if (!source_provider_->file_contents_name().empty()) { |
| 778 actions.push_back(ui::GetAtom(kXdndActionDirectSave)); | 776 actions.push_back(gfx::GetAtom(kXdndActionDirectSave)); |
| 779 ui::SetStringProperty( | 777 ui::SetStringProperty( |
| 780 xwindow_, ui::GetAtom(kXdndDirectSave0), | 778 xwindow_, gfx::GetAtom(kXdndDirectSave0), |
| 781 ui::GetAtom(ui::Clipboard::kMimeTypeText), | 779 gfx::GetAtom(ui::Clipboard::kMimeTypeText), |
| 782 source_provider_->file_contents_name().AsUTF8Unsafe()); | 780 source_provider_->file_contents_name().AsUTF8Unsafe()); |
| 783 } | 781 } |
| 784 ui::SetAtomArrayProperty(xwindow_, kXdndActionList, "ATOM", actions); | 782 ui::SetAtomArrayProperty(xwindow_, kXdndActionList, "ATOM", actions); |
| 785 | 783 |
| 786 gfx::ImageSkia drag_image = source_provider_->GetDragImage(); | 784 gfx::ImageSkia drag_image = source_provider_->GetDragImage(); |
| 787 if (IsValidDragImage(drag_image)) { | 785 if (IsValidDragImage(drag_image)) { |
| 788 CreateDragWidget(drag_image); | 786 CreateDragWidget(drag_image); |
| 789 drag_widget_offset_ = source_provider_->GetDragImageOffset(); | 787 drag_widget_offset_ = source_provider_->GetDragImageOffset(); |
| 790 } | 788 } |
| 791 | 789 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 813 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); | 811 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); |
| 814 } else { | 812 } else { |
| 815 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, | 813 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, |
| 816 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); | 814 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); |
| 817 } | 815 } |
| 818 drag_widget_.reset(); | 816 drag_widget_.reset(); |
| 819 | 817 |
| 820 source_provider_ = NULL; | 818 source_provider_ = NULL; |
| 821 g_current_drag_drop_client = NULL; | 819 g_current_drag_drop_client = NULL; |
| 822 drag_operation_ = 0; | 820 drag_operation_ = 0; |
| 823 XDeleteProperty(xdisplay_, xwindow_, ui::GetAtom(kXdndActionList)); | 821 XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndActionList)); |
| 824 XDeleteProperty(xdisplay_, xwindow_, ui::GetAtom(kXdndDirectSave0)); | 822 XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndDirectSave0)); |
| 825 | 823 |
| 826 return negotiated_operation_; | 824 return negotiated_operation_; |
| 827 } | 825 } |
| 828 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, | 826 UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, |
| 829 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); | 827 ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); |
| 830 return ui::DragDropTypes::DRAG_NONE; | 828 return ui::DragDropTypes::DRAG_NONE; |
| 831 } | 829 } |
| 832 | 830 |
| 833 void DesktopDragDropClientAuraX11::DragCancel() { | 831 void DesktopDragDropClientAuraX11::DragCancel() { |
| 834 move_loop_->EndMoveLoop(); | 832 move_loop_->EndMoveLoop(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 } | 953 } |
| 956 | 954 |
| 957 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid, | 955 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid, |
| 958 XEvent* xev) { | 956 XEvent* xev) { |
| 959 DCHECK_EQ(ClientMessage, xev->type); | 957 DCHECK_EQ(ClientMessage, xev->type); |
| 960 | 958 |
| 961 // Don't send messages to the X11 message queue if we can help it. | 959 // Don't send messages to the X11 message queue if we can help it. |
| 962 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid); | 960 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid); |
| 963 if (short_circuit) { | 961 if (short_circuit) { |
| 964 Atom message_type = xev->xclient.message_type; | 962 Atom message_type = xev->xclient.message_type; |
| 965 if (message_type == ui::GetAtom(kXdndEnter)) { | 963 if (message_type == gfx::GetAtom(kXdndEnter)) { |
| 966 short_circuit->OnXdndEnter(xev->xclient); | 964 short_circuit->OnXdndEnter(xev->xclient); |
| 967 return; | 965 return; |
| 968 } else if (message_type == ui::GetAtom(kXdndLeave)) { | 966 } else if (message_type == gfx::GetAtom(kXdndLeave)) { |
| 969 short_circuit->OnXdndLeave(xev->xclient); | 967 short_circuit->OnXdndLeave(xev->xclient); |
| 970 return; | 968 return; |
| 971 } else if (message_type == ui::GetAtom(kXdndPosition)) { | 969 } else if (message_type == gfx::GetAtom(kXdndPosition)) { |
| 972 short_circuit->OnXdndPosition(xev->xclient); | 970 short_circuit->OnXdndPosition(xev->xclient); |
| 973 return; | 971 return; |
| 974 } else if (message_type == ui::GetAtom(kXdndStatus)) { | 972 } else if (message_type == gfx::GetAtom(kXdndStatus)) { |
| 975 short_circuit->OnXdndStatus(xev->xclient); | 973 short_circuit->OnXdndStatus(xev->xclient); |
| 976 return; | 974 return; |
| 977 } else if (message_type == ui::GetAtom(kXdndFinished)) { | 975 } else if (message_type == gfx::GetAtom(kXdndFinished)) { |
| 978 short_circuit->OnXdndFinished(xev->xclient); | 976 short_circuit->OnXdndFinished(xev->xclient); |
| 979 return; | 977 return; |
| 980 } else if (message_type == ui::GetAtom(kXdndDrop)) { | 978 } else if (message_type == gfx::GetAtom(kXdndDrop)) { |
| 981 short_circuit->OnXdndDrop(xev->xclient); | 979 short_circuit->OnXdndDrop(xev->xclient); |
| 982 return; | 980 return; |
| 983 } | 981 } |
| 984 } | 982 } |
| 985 | 983 |
| 986 // I don't understand why the GTK+ code is doing what it's doing here. It | 984 // I don't understand why the GTK+ code is doing what it's doing here. It |
| 987 // goes out of its way to send the XEvent so that it receives a callback on | 985 // goes out of its way to send the XEvent so that it receives a callback on |
| 988 // success or failure, and when it fails, it then sends an internal | 986 // success or failure, and when it fails, it then sends an internal |
| 989 // GdkEvent about the failed drag. (And sending this message doesn't appear | 987 // GdkEvent about the failed drag. (And sending this message doesn't appear |
| 990 // to go through normal xlib machinery, but instead passes through the low | 988 // to go through normal xlib machinery, but instead passes through the low |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 aura::client::GetDragDropDelegate(target_window_); | 1106 aura::client::GetDragDropDelegate(target_window_); |
| 1109 if (delegate) | 1107 if (delegate) |
| 1110 delegate->OnDragExited(); | 1108 delegate->OnDragExited(); |
| 1111 target_window_->RemoveObserver(this); | 1109 target_window_->RemoveObserver(this); |
| 1112 target_window_ = NULL; | 1110 target_window_ = NULL; |
| 1113 } | 1111 } |
| 1114 | 1112 |
| 1115 ::Atom DesktopDragDropClientAuraX11::DragOperationToAtom( | 1113 ::Atom DesktopDragDropClientAuraX11::DragOperationToAtom( |
| 1116 int drag_operation) { | 1114 int drag_operation) { |
| 1117 if (drag_operation & ui::DragDropTypes::DRAG_COPY) | 1115 if (drag_operation & ui::DragDropTypes::DRAG_COPY) |
| 1118 return ui::GetAtom(kXdndActionCopy); | 1116 return gfx::GetAtom(kXdndActionCopy); |
| 1119 if (drag_operation & ui::DragDropTypes::DRAG_MOVE) | 1117 if (drag_operation & ui::DragDropTypes::DRAG_MOVE) |
| 1120 return ui::GetAtom(kXdndActionMove); | 1118 return gfx::GetAtom(kXdndActionMove); |
| 1121 if (drag_operation & ui::DragDropTypes::DRAG_LINK) | 1119 if (drag_operation & ui::DragDropTypes::DRAG_LINK) |
| 1122 return ui::GetAtom(kXdndActionLink); | 1120 return gfx::GetAtom(kXdndActionLink); |
| 1123 | 1121 |
| 1124 return None; | 1122 return None; |
| 1125 } | 1123 } |
| 1126 | 1124 |
| 1127 ui::DragDropTypes::DragOperation | 1125 ui::DragDropTypes::DragOperation |
| 1128 DesktopDragDropClientAuraX11::AtomToDragOperation(::Atom atom) { | 1126 DesktopDragDropClientAuraX11::AtomToDragOperation(::Atom atom) { |
| 1129 if (atom == ui::GetAtom(kXdndActionCopy)) | 1127 if (atom == gfx::GetAtom(kXdndActionCopy)) |
| 1130 return ui::DragDropTypes::DRAG_COPY; | 1128 return ui::DragDropTypes::DRAG_COPY; |
| 1131 if (atom == ui::GetAtom(kXdndActionMove)) | 1129 if (atom == gfx::GetAtom(kXdndActionMove)) |
| 1132 return ui::DragDropTypes::DRAG_MOVE; | 1130 return ui::DragDropTypes::DRAG_MOVE; |
| 1133 if (atom == ui::GetAtom(kXdndActionLink)) | 1131 if (atom == gfx::GetAtom(kXdndActionLink)) |
| 1134 return ui::DragDropTypes::DRAG_LINK; | 1132 return ui::DragDropTypes::DRAG_LINK; |
| 1135 | 1133 |
| 1136 return ui::DragDropTypes::DRAG_NONE; | 1134 return ui::DragDropTypes::DRAG_NONE; |
| 1137 } | 1135 } |
| 1138 | 1136 |
| 1139 std::vector<::Atom> DesktopDragDropClientAuraX11::GetOfferedDragOperations() { | 1137 std::vector<::Atom> DesktopDragDropClientAuraX11::GetOfferedDragOperations() { |
| 1140 std::vector<::Atom> operations; | 1138 std::vector<::Atom> operations; |
| 1141 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY) | 1139 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY) |
| 1142 operations.push_back(ui::GetAtom(kXdndActionCopy)); | 1140 operations.push_back(gfx::GetAtom(kXdndActionCopy)); |
| 1143 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE) | 1141 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE) |
| 1144 operations.push_back(ui::GetAtom(kXdndActionMove)); | 1142 operations.push_back(gfx::GetAtom(kXdndActionMove)); |
| 1145 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) | 1143 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) |
| 1146 operations.push_back(ui::GetAtom(kXdndActionLink)); | 1144 operations.push_back(gfx::GetAtom(kXdndActionLink)); |
| 1147 return operations; | 1145 return operations; |
| 1148 } | 1146 } |
| 1149 | 1147 |
| 1150 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { | 1148 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { |
| 1151 return source_provider_ ? source_provider_->GetFormatMap() : | 1149 return source_provider_ ? source_provider_->GetFormatMap() : |
| 1152 ui::SelectionFormatMap(); | 1150 ui::SelectionFormatMap(); |
| 1153 } | 1151 } |
| 1154 | 1152 |
| 1155 void DesktopDragDropClientAuraX11::CompleteXdndPosition( | 1153 void DesktopDragDropClientAuraX11::CompleteXdndPosition( |
| 1156 ::Window source_window, | 1154 ::Window source_window, |
| 1157 const gfx::Point& screen_point) { | 1155 const gfx::Point& screen_point) { |
| 1158 int drag_operation = ui::DragDropTypes::DRAG_NONE; | 1156 int drag_operation = ui::DragDropTypes::DRAG_NONE; |
| 1159 std::unique_ptr<ui::OSExchangeData> data; | 1157 std::unique_ptr<ui::OSExchangeData> data; |
| 1160 std::unique_ptr<ui::DropTargetEvent> drop_target_event; | 1158 std::unique_ptr<ui::DropTargetEvent> drop_target_event; |
| 1161 DragDropDelegate* delegate = NULL; | 1159 DragDropDelegate* delegate = NULL; |
| 1162 DragTranslate(screen_point, &data, &drop_target_event, &delegate); | 1160 DragTranslate(screen_point, &data, &drop_target_event, &delegate); |
| 1163 if (delegate) | 1161 if (delegate) |
| 1164 drag_operation = delegate->OnDragUpdated(*drop_target_event); | 1162 drag_operation = delegate->OnDragUpdated(*drop_target_event); |
| 1165 | 1163 |
| 1166 // Sends an XdndStatus message back to the source_window. l[2,3] | 1164 // Sends an XdndStatus message back to the source_window. l[2,3] |
| 1167 // theoretically represent an area in the window where the current action is | 1165 // theoretically represent an area in the window where the current action is |
| 1168 // the same as what we're returning, but I can't find any implementation that | 1166 // the same as what we're returning, but I can't find any implementation that |
| 1169 // actually making use of this. A client can return (0, 0) and/or set the | 1167 // actually making use of this. A client can return (0, 0) and/or set the |
| 1170 // first bit of l[1] to disable the feature, and it appears that gtk neither | 1168 // first bit of l[1] to disable the feature, and it appears that gtk neither |
| 1171 // sets this nor respects it if set. | 1169 // sets this nor respects it if set. |
| 1172 XEvent xev; | 1170 XEvent xev; |
| 1173 xev.xclient.type = ClientMessage; | 1171 xev.xclient.type = ClientMessage; |
| 1174 xev.xclient.message_type = ui::GetAtom(kXdndStatus); | 1172 xev.xclient.message_type = gfx::GetAtom(kXdndStatus); |
| 1175 xev.xclient.format = 32; | 1173 xev.xclient.format = 32; |
| 1176 xev.xclient.window = source_window; | 1174 xev.xclient.window = source_window; |
| 1177 xev.xclient.data.l[0] = xwindow_; | 1175 xev.xclient.data.l[0] = xwindow_; |
| 1178 xev.xclient.data.l[1] = (drag_operation != 0) ? | 1176 xev.xclient.data.l[1] = (drag_operation != 0) ? |
| 1179 (kWantFurtherPosEvents | kWillAcceptDrop) : 0; | 1177 (kWantFurtherPosEvents | kWillAcceptDrop) : 0; |
| 1180 xev.xclient.data.l[2] = 0; | 1178 xev.xclient.data.l[2] = 0; |
| 1181 xev.xclient.data.l[3] = 0; | 1179 xev.xclient.data.l[3] = 0; |
| 1182 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation); | 1180 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation); |
| 1183 | 1181 |
| 1184 SendXClientEvent(source_window, &xev); | 1182 SendXClientEvent(source_window, &xev); |
| 1185 } | 1183 } |
| 1186 | 1184 |
| 1187 void DesktopDragDropClientAuraX11::SendXdndEnter(::Window dest_window) { | 1185 void DesktopDragDropClientAuraX11::SendXdndEnter(::Window dest_window) { |
| 1188 XEvent xev; | 1186 XEvent xev; |
| 1189 xev.xclient.type = ClientMessage; | 1187 xev.xclient.type = ClientMessage; |
| 1190 xev.xclient.message_type = ui::GetAtom(kXdndEnter); | 1188 xev.xclient.message_type = gfx::GetAtom(kXdndEnter); |
| 1191 xev.xclient.format = 32; | 1189 xev.xclient.format = 32; |
| 1192 xev.xclient.window = dest_window; | 1190 xev.xclient.window = dest_window; |
| 1193 xev.xclient.data.l[0] = xwindow_; | 1191 xev.xclient.data.l[0] = xwindow_; |
| 1194 xev.xclient.data.l[1] = (kMaxXdndVersion << 24); // The version number. | 1192 xev.xclient.data.l[1] = (kMaxXdndVersion << 24); // The version number. |
| 1195 xev.xclient.data.l[2] = 0; | 1193 xev.xclient.data.l[2] = 0; |
| 1196 xev.xclient.data.l[3] = 0; | 1194 xev.xclient.data.l[3] = 0; |
| 1197 xev.xclient.data.l[4] = 0; | 1195 xev.xclient.data.l[4] = 0; |
| 1198 | 1196 |
| 1199 std::vector<Atom> targets; | 1197 std::vector<Atom> targets; |
| 1200 source_provider_->RetrieveTargets(&targets); | 1198 source_provider_->RetrieveTargets(&targets); |
| 1201 | 1199 |
| 1202 if (targets.size() > 3) { | 1200 if (targets.size() > 3) { |
| 1203 xev.xclient.data.l[1] |= 1; | 1201 xev.xclient.data.l[1] |= 1; |
| 1204 ui::SetAtomArrayProperty(xwindow_, kXdndTypeList, "ATOM", targets); | 1202 ui::SetAtomArrayProperty(xwindow_, kXdndTypeList, "ATOM", targets); |
| 1205 } else { | 1203 } else { |
| 1206 // Pack the targets into the enter message. | 1204 // Pack the targets into the enter message. |
| 1207 for (size_t i = 0; i < targets.size(); ++i) | 1205 for (size_t i = 0; i < targets.size(); ++i) |
| 1208 xev.xclient.data.l[2 + i] = targets[i]; | 1206 xev.xclient.data.l[2 + i] = targets[i]; |
| 1209 } | 1207 } |
| 1210 | 1208 |
| 1211 SendXClientEvent(dest_window, &xev); | 1209 SendXClientEvent(dest_window, &xev); |
| 1212 } | 1210 } |
| 1213 | 1211 |
| 1214 void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) { | 1212 void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) { |
| 1215 XEvent xev; | 1213 XEvent xev; |
| 1216 xev.xclient.type = ClientMessage; | 1214 xev.xclient.type = ClientMessage; |
| 1217 xev.xclient.message_type = ui::GetAtom(kXdndLeave); | 1215 xev.xclient.message_type = gfx::GetAtom(kXdndLeave); |
| 1218 xev.xclient.format = 32; | 1216 xev.xclient.format = 32; |
| 1219 xev.xclient.window = dest_window; | 1217 xev.xclient.window = dest_window; |
| 1220 xev.xclient.data.l[0] = xwindow_; | 1218 xev.xclient.data.l[0] = xwindow_; |
| 1221 xev.xclient.data.l[1] = 0; | 1219 xev.xclient.data.l[1] = 0; |
| 1222 xev.xclient.data.l[2] = 0; | 1220 xev.xclient.data.l[2] = 0; |
| 1223 xev.xclient.data.l[3] = 0; | 1221 xev.xclient.data.l[3] = 0; |
| 1224 xev.xclient.data.l[4] = 0; | 1222 xev.xclient.data.l[4] = 0; |
| 1225 SendXClientEvent(dest_window, &xev); | 1223 SendXClientEvent(dest_window, &xev); |
| 1226 } | 1224 } |
| 1227 | 1225 |
| 1228 void DesktopDragDropClientAuraX11::SendXdndPosition( | 1226 void DesktopDragDropClientAuraX11::SendXdndPosition( |
| 1229 ::Window dest_window, | 1227 ::Window dest_window, |
| 1230 const gfx::Point& screen_point, | 1228 const gfx::Point& screen_point, |
| 1231 unsigned long event_time) { | 1229 unsigned long event_time) { |
| 1232 waiting_on_status_ = true; | 1230 waiting_on_status_ = true; |
| 1233 | 1231 |
| 1234 XEvent xev; | 1232 XEvent xev; |
| 1235 xev.xclient.type = ClientMessage; | 1233 xev.xclient.type = ClientMessage; |
| 1236 xev.xclient.message_type = ui::GetAtom(kXdndPosition); | 1234 xev.xclient.message_type = gfx::GetAtom(kXdndPosition); |
| 1237 xev.xclient.format = 32; | 1235 xev.xclient.format = 32; |
| 1238 xev.xclient.window = dest_window; | 1236 xev.xclient.window = dest_window; |
| 1239 xev.xclient.data.l[0] = xwindow_; | 1237 xev.xclient.data.l[0] = xwindow_; |
| 1240 xev.xclient.data.l[1] = 0; | 1238 xev.xclient.data.l[1] = 0; |
| 1241 xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y(); | 1239 xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y(); |
| 1242 xev.xclient.data.l[3] = event_time; | 1240 xev.xclient.data.l[3] = event_time; |
| 1243 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation_); | 1241 xev.xclient.data.l[4] = DragOperationToAtom(drag_operation_); |
| 1244 SendXClientEvent(dest_window, &xev); | 1242 SendXClientEvent(dest_window, &xev); |
| 1245 | 1243 |
| 1246 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and | 1244 // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and |
| 1247 // the Xdnd protocol both recommend that drag events should be sent | 1245 // the Xdnd protocol both recommend that drag events should be sent |
| 1248 // periodically. | 1246 // periodically. |
| 1249 repeat_mouse_move_timer_.Start( | 1247 repeat_mouse_move_timer_.Start( |
| 1250 FROM_HERE, | 1248 FROM_HERE, |
| 1251 base::TimeDelta::FromMilliseconds(kRepeatMouseMoveTimeoutMs), | 1249 base::TimeDelta::FromMilliseconds(kRepeatMouseMoveTimeoutMs), |
| 1252 base::Bind(&DesktopDragDropClientAuraX11::ProcessMouseMove, | 1250 base::Bind(&DesktopDragDropClientAuraX11::ProcessMouseMove, |
| 1253 base::Unretained(this), | 1251 base::Unretained(this), |
| 1254 screen_point, | 1252 screen_point, |
| 1255 event_time)); | 1253 event_time)); |
| 1256 } | 1254 } |
| 1257 | 1255 |
| 1258 void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) { | 1256 void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) { |
| 1259 XEvent xev; | 1257 XEvent xev; |
| 1260 xev.xclient.type = ClientMessage; | 1258 xev.xclient.type = ClientMessage; |
| 1261 xev.xclient.message_type = ui::GetAtom(kXdndDrop); | 1259 xev.xclient.message_type = gfx::GetAtom(kXdndDrop); |
| 1262 xev.xclient.format = 32; | 1260 xev.xclient.format = 32; |
| 1263 xev.xclient.window = dest_window; | 1261 xev.xclient.window = dest_window; |
| 1264 xev.xclient.data.l[0] = xwindow_; | 1262 xev.xclient.data.l[0] = xwindow_; |
| 1265 xev.xclient.data.l[1] = 0; | 1263 xev.xclient.data.l[1] = 0; |
| 1266 xev.xclient.data.l[2] = CurrentTime; | 1264 xev.xclient.data.l[2] = CurrentTime; |
| 1267 xev.xclient.data.l[3] = None; | 1265 xev.xclient.data.l[3] = None; |
| 1268 xev.xclient.data.l[4] = None; | 1266 xev.xclient.data.l[4] = None; |
| 1269 SendXClientEvent(dest_window, &xev); | 1267 SendXClientEvent(dest_window, &xev); |
| 1270 } | 1268 } |
| 1271 | 1269 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 for (int x = 0; x < in_bitmap->width(); ++x) { | 1314 for (int x = 0; x < in_bitmap->width(); ++x) { |
| 1317 if (SkColorGetA(in_row[x]) > kMinAlpha) | 1315 if (SkColorGetA(in_row[x]) > kMinAlpha) |
| 1318 return true; | 1316 return true; |
| 1319 } | 1317 } |
| 1320 } | 1318 } |
| 1321 | 1319 |
| 1322 return false; | 1320 return false; |
| 1323 } | 1321 } |
| 1324 | 1322 |
| 1325 } // namespace views | 1323 } // namespace views |
| OLD | NEW |