Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc

Issue 268083002: Add tests for drag and drop for Linux Aura (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 8
9 #include "base/event_types.h" 9 #include "base/event_types.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 73
74 // The time to wait since sending the last XdndPosition message before 74 // The time to wait since sending the last XdndPosition message before
75 // reprocessing the most recent mouse move event in case that the window 75 // reprocessing the most recent mouse move event in case that the window
76 // stacking order has changed and |source_current_window_| needs to be updated. 76 // stacking order has changed and |source_current_window_| needs to be updated.
77 const int kRepeatMouseMoveTimeoutMs = 350; 77 const int kRepeatMouseMoveTimeoutMs = 350;
78 78
79 static base::LazyInstance< 79 static base::LazyInstance<
80 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky 80 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky
81 g_live_client_map = LAZY_INSTANCE_INITIALIZER; 81 g_live_client_map = LAZY_INSTANCE_INITIALIZER;
82 82
83 // Returns the topmost X11 window at |screen_point| if it is advertising that
84 // is supports the Xdnd protocol. Will return the window under the pointer as
85 // |mouse_window|. If there's a Xdnd aware window, it will be returned in
86 // |dest_window|.
87 void FindWindowFor(const gfx::Point& screen_point,
88 ::Window* mouse_window,
89 ::Window* dest_window) {
90 views::X11TopmostWindowFinder finder;
91 *mouse_window = finder.FindWindowAt(screen_point);
92 *dest_window = None;
93
94 if (*mouse_window == None)
95 return;
96
97 // Figure out which window we should test as XdndAware. If mouse_window has
98 // XdndProxy, it will set that proxy on target, and if not, |target|'s
99 // original value will remain.
100 XID target = *mouse_window;
101 ui::GetXIDProperty(*mouse_window, "XdndProxy", &target);
102
103 int version;
104 if (ui::GetIntProperty(target, "XdndAware", &version) &&
105 version >= kMinXdndVersion) {
106 *dest_window = target;
107 }
108 }
109
110 } // namespace 83 } // namespace
111 84
112 namespace views { 85 namespace views {
113 86
114 DesktopDragDropClientAuraX11* 87 DesktopDragDropClientAuraX11*
115 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL; 88 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL;
116 89
117 class DesktopDragDropClientAuraX11::X11DragContext 90 class DesktopDragDropClientAuraX11::X11DragContext
118 : public ui::PlatformEventDispatcher { 91 : public ui::PlatformEventDispatcher {
119 public: 92 public:
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 unsigned long event_time = next_position_message_->second; 502 unsigned long event_time = next_position_message_->second;
530 next_position_message_.reset(); 503 next_position_message_.reset();
531 504
532 SendXdndPosition(source_window, p, event_time); 505 SendXdndPosition(source_window, p, event_time);
533 } 506 }
534 } 507 }
535 508
536 void DesktopDragDropClientAuraX11::OnXdndFinished( 509 void DesktopDragDropClientAuraX11::OnXdndFinished(
537 const XClientMessageEvent& event) { 510 const XClientMessageEvent& event) {
538 DVLOG(1) << "XdndFinished"; 511 DVLOG(1) << "XdndFinished";
512 unsigned long source_window = event.data.l[0];
513 if (source_current_window_ != source_window)
514 return;
515
516 // Clear |negotiated_operation_| if the drag was rejected.
517 if ((event.data.l[1] & 1) == 0)
518 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
539 519
540 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the 520 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the
541 // move loop. 521 // move loop.
542 source_current_window_ = None; 522 source_current_window_ = None;
543 move_loop_.EndMoveLoop(); 523 move_loop_.EndMoveLoop();
544 } 524 }
545 525
546 void DesktopDragDropClientAuraX11::OnXdndDrop( 526 void DesktopDragDropClientAuraX11::OnXdndDrop(
547 const XClientMessageEvent& event) { 527 const XClientMessageEvent& event) {
548 DVLOG(1) << "XdndDrop"; 528 DVLOG(1) << "XdndDrop";
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 704 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
725 if (source_current_window_ != None) { 705 if (source_current_window_ != None) {
726 SendXdndLeave(source_current_window_); 706 SendXdndLeave(source_current_window_);
727 source_current_window_ = None; 707 source_current_window_ = None;
728 } 708 }
729 target_current_context_.reset(); 709 target_current_context_.reset();
730 repeat_mouse_move_timer_.Stop(); 710 repeat_mouse_move_timer_.Stop();
731 end_move_loop_timer_.Stop(); 711 end_move_loop_timer_.Stop();
732 } 712 }
733 713
714 XID DesktopDragDropClientAuraX11::FindWindowFor(
715 const gfx::Point& screen_point) {
716 views::X11TopmostWindowFinder finder;
717 ::Window target = finder.FindWindowAt(screen_point);
718
719 if (target == None)
720 return None;
721
722 // Figure out which window we should test as XdndAware. If mouse_window has
723 // XdndProxy, it will set that proxy on target, and if not, |target|'s
724 // original value will remain.
725 ui::GetXIDProperty(target, "XdndProxy", &target);
726
727 int version;
728 if (ui::GetIntProperty(target, "XdndAware", &version) &&
729 version >= kMinXdndVersion) {
730 return target;
731 }
732 return None;
733 }
734
735 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
736 XEvent* xev) {
737 DCHECK_EQ(ClientMessage, xev->type);
738
739 // Don't send messages to the X11 message queue if we can help it.
740 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
741 if (short_circuit) {
742 Atom message_type = xev->xclient.message_type;
743 if (message_type == atom_cache_.GetAtom("XdndEnter")) {
744 short_circuit->OnXdndEnter(xev->xclient);
745 return;
746 } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
747 short_circuit->OnXdndLeave(xev->xclient);
748 return;
749 } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
750 short_circuit->OnXdndPosition(xev->xclient);
751 return;
752 } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
753 short_circuit->OnXdndStatus(xev->xclient);
754 return;
755 } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
756 short_circuit->OnXdndFinished(xev->xclient);
757 return;
758 } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
759 short_circuit->OnXdndDrop(xev->xclient);
760 return;
761 }
762 }
763
764 // I don't understand why the GTK+ code is doing what it's doing here. It
765 // goes out of its way to send the XEvent so that it receives a callback on
766 // success or failure, and when it fails, it then sends an internal
767 // GdkEvent about the failed drag. (And sending this message doesn't appear
768 // to go through normal xlib machinery, but instead passes through the low
769 // level xProto (the x11 wire format) that I don't understand.
770 //
771 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
772 // sufficient.
773 XSendEvent(xdisplay_, xid, False, 0, xev);
774 }
775
734 void DesktopDragDropClientAuraX11::ProcessMouseMove( 776 void DesktopDragDropClientAuraX11::ProcessMouseMove(
735 const gfx::Point& screen_point, 777 const gfx::Point& screen_point,
736 unsigned long event_time) { 778 unsigned long event_time) {
737 if (source_state_ != SOURCE_STATE_OTHER) 779 if (source_state_ != SOURCE_STATE_OTHER)
738 return; 780 return;
739 781
740 // Find the current window the cursor is over. 782 // Find the current window the cursor is over.
741 ::Window mouse_window = None; 783 ::Window dest_window = FindWindowFor(screen_point);
742 ::Window dest_window = None;
743 FindWindowFor(screen_point, &mouse_window, &dest_window);
744 784
745 if (source_current_window_ != dest_window) { 785 if (source_current_window_ != dest_window) {
746 if (source_current_window_ != None) 786 if (source_current_window_ != None)
747 SendXdndLeave(source_current_window_); 787 SendXdndLeave(source_current_window_);
748 788
749 source_current_window_ = dest_window; 789 source_current_window_ = dest_window;
750 waiting_on_status_ = false; 790 waiting_on_status_ = false;
751 next_position_message_.reset(); 791 next_position_message_.reset();
752 status_received_since_enter_ = false; 792 status_received_since_enter_ = false;
753 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 793 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 xev.xclient.format = 32; 1021 xev.xclient.format = 32;
982 xev.xclient.window = dest_window; 1022 xev.xclient.window = dest_window;
983 xev.xclient.data.l[0] = xwindow_; 1023 xev.xclient.data.l[0] = xwindow_;
984 xev.xclient.data.l[1] = 0; 1024 xev.xclient.data.l[1] = 0;
985 xev.xclient.data.l[2] = CurrentTime; 1025 xev.xclient.data.l[2] = CurrentTime;
986 xev.xclient.data.l[3] = None; 1026 xev.xclient.data.l[3] = None;
987 xev.xclient.data.l[4] = None; 1027 xev.xclient.data.l[4] = None;
988 SendXClientEvent(dest_window, &xev); 1028 SendXClientEvent(dest_window, &xev);
989 } 1029 }
990 1030
991 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
992 XEvent* xev) {
993 DCHECK_EQ(ClientMessage, xev->type);
994
995 // Don't send messages to the X11 message queue if we can help it.
996 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
997 if (short_circuit) {
998 Atom message_type = xev->xclient.message_type;
999 if (message_type == atom_cache_.GetAtom("XdndEnter")) {
1000 short_circuit->OnXdndEnter(xev->xclient);
1001 return;
1002 } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
1003 short_circuit->OnXdndLeave(xev->xclient);
1004 return;
1005 } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
1006 short_circuit->OnXdndPosition(xev->xclient);
1007 return;
1008 } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
1009 short_circuit->OnXdndStatus(xev->xclient);
1010 return;
1011 } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
1012 short_circuit->OnXdndFinished(xev->xclient);
1013 return;
1014 } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
1015 short_circuit->OnXdndDrop(xev->xclient);
1016 return;
1017 }
1018 }
1019
1020 // I don't understand why the GTK+ code is doing what it's doing here. It
1021 // goes out of its way to send the XEvent so that it receives a callback on
1022 // success or failure, and when it fails, it then sends an internal
1023 // GdkEvent about the failed drag. (And sending this message doesn't appear
1024 // to go through normal xlib machinery, but instead passes through the low
1025 // level xProto (the x11 wire format) that I don't understand.
1026 //
1027 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
1028 // sufficient.
1029 XSendEvent(xdisplay_, xid, False, 0, xev);
1030 }
1031
1032 } // namespace views 1031 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698