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

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 mouse_window = finder.FindWindowAt(screen_point);
718
719 if (mouse_window == 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 ::Window target = mouse_window;
726 ui::GetXIDProperty(mouse_window, "XdndProxy", &target);
727
728 int version;
729 if (ui::GetIntProperty(target, "XdndAware", &version) &&
730 version >= kMinXdndVersion) {
731 return target;
732 }
733 return None;
734 }
735
736 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
737 XEvent* xev) {
738 DCHECK_EQ(ClientMessage, xev->type);
739
740 // Don't send messages to the X11 message queue if we can help it.
741 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
742 if (short_circuit) {
743 Atom message_type = xev->xclient.message_type;
744 if (message_type == atom_cache_.GetAtom("XdndEnter")) {
745 short_circuit->OnXdndEnter(xev->xclient);
746 return;
747 } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
748 short_circuit->OnXdndLeave(xev->xclient);
749 return;
750 } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
751 short_circuit->OnXdndPosition(xev->xclient);
752 return;
753 } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
754 short_circuit->OnXdndStatus(xev->xclient);
755 return;
756 } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
757 short_circuit->OnXdndFinished(xev->xclient);
758 return;
759 } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
760 short_circuit->OnXdndDrop(xev->xclient);
761 return;
762 }
763 }
764
765 // I don't understand why the GTK+ code is doing what it's doing here. It
766 // goes out of its way to send the XEvent so that it receives a callback on
767 // success or failure, and when it fails, it then sends an internal
768 // GdkEvent about the failed drag. (And sending this message doesn't appear
769 // to go through normal xlib machinery, but instead passes through the low
770 // level xProto (the x11 wire format) that I don't understand.
771 //
772 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
773 // sufficient.
774 XSendEvent(xdisplay_, xid, False, 0, xev);
775 }
776
734 void DesktopDragDropClientAuraX11::ProcessMouseMove( 777 void DesktopDragDropClientAuraX11::ProcessMouseMove(
735 const gfx::Point& screen_point, 778 const gfx::Point& screen_point,
736 unsigned long event_time) { 779 unsigned long event_time) {
737 if (source_state_ != SOURCE_STATE_OTHER) 780 if (source_state_ != SOURCE_STATE_OTHER)
738 return; 781 return;
739 782
740 // Find the current window the cursor is over. 783 // Find the current window the cursor is over.
741 ::Window mouse_window = None; 784 ::Window dest_window = FindWindowFor(screen_point);
742 ::Window dest_window = None;
743 FindWindowFor(screen_point, &mouse_window, &dest_window,
744 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU"));
745 785
746 if (source_current_window_ != dest_window) { 786 if (source_current_window_ != dest_window) {
747 if (source_current_window_ != None) 787 if (source_current_window_ != None)
748 SendXdndLeave(source_current_window_); 788 SendXdndLeave(source_current_window_);
749 789
750 source_current_window_ = dest_window; 790 source_current_window_ = dest_window;
751 waiting_on_status_ = false; 791 waiting_on_status_ = false;
752 next_position_message_.reset(); 792 next_position_message_.reset();
753 status_received_since_enter_ = false; 793 status_received_since_enter_ = false;
754 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 794 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 xev.xclient.format = 32; 1022 xev.xclient.format = 32;
983 xev.xclient.window = dest_window; 1023 xev.xclient.window = dest_window;
984 xev.xclient.data.l[0] = xwindow_; 1024 xev.xclient.data.l[0] = xwindow_;
985 xev.xclient.data.l[1] = 0; 1025 xev.xclient.data.l[1] = 0;
986 xev.xclient.data.l[2] = CurrentTime; 1026 xev.xclient.data.l[2] = CurrentTime;
987 xev.xclient.data.l[3] = None; 1027 xev.xclient.data.l[3] = None;
988 xev.xclient.data.l[4] = None; 1028 xev.xclient.data.l[4] = None;
989 SendXClientEvent(dest_window, &xev); 1029 SendXClientEvent(dest_window, &xev);
990 } 1030 }
991 1031
992 void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
993 XEvent* xev) {
994 DCHECK_EQ(ClientMessage, xev->type);
995
996 // Don't send messages to the X11 message queue if we can help it.
997 DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
998 if (short_circuit) {
999 Atom message_type = xev->xclient.message_type;
1000 if (message_type == atom_cache_.GetAtom("XdndEnter")) {
1001 short_circuit->OnXdndEnter(xev->xclient);
1002 return;
1003 } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
1004 short_circuit->OnXdndLeave(xev->xclient);
1005 return;
1006 } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
1007 short_circuit->OnXdndPosition(xev->xclient);
1008 return;
1009 } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
1010 short_circuit->OnXdndStatus(xev->xclient);
1011 return;
1012 } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
1013 short_circuit->OnXdndFinished(xev->xclient);
1014 return;
1015 } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
1016 short_circuit->OnXdndDrop(xev->xclient);
1017 return;
1018 }
1019 }
1020
1021 // I don't understand why the GTK+ code is doing what it's doing here. It
1022 // goes out of its way to send the XEvent so that it receives a callback on
1023 // success or failure, and when it fails, it then sends an internal
1024 // GdkEvent about the failed drag. (And sending this message doesn't appear
1025 // to go through normal xlib machinery, but instead passes through the low
1026 // level xProto (the x11 wire format) that I don't understand.
1027 //
1028 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
1029 // sufficient.
1030 XSendEvent(xdisplay_, xid, False, 0, xev);
1031 }
1032
1033 } // namespace views 1032 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698