| 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 <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/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 | 152 |
| 153 // Called to request the next target from the source window. This is only | 153 // Called to request the next target from the source window. This is only |
| 154 // done on the first XdndPosition; after that, we cache the data offered by | 154 // done on the first XdndPosition; after that, we cache the data offered by |
| 155 // the source window. | 155 // the source window. |
| 156 void RequestNextTarget(); | 156 void RequestNextTarget(); |
| 157 | 157 |
| 158 // Called when XSelection data has been copied to our process. | 158 // Called when XSelection data has been copied to our process. |
| 159 void OnSelectionNotify(const XSelectionEvent& xselection); | 159 void OnSelectionNotify(const XSelectionEvent& xselection); |
| 160 | 160 |
| 161 // Clones the fetched targets. | 161 // Clones the fetched targets. |
| 162 scoped_ptr<ui::SelectionFormatMap> CloneFetchedTargets() { | 162 const ui::SelectionFormatMap& fetched_targets() { return fetched_targets_; } |
| 163 DCHECK(fetched_targets_); | |
| 164 return fetched_targets_->Clone(); | |
| 165 } | |
| 166 | 163 |
| 167 // Reads the "XdndActionList" property from |source_window| and copies it | 164 // Reads the "XdndActionList" property from |source_window| and copies it |
| 168 // into |actions|. | 165 // into |actions|. |
| 169 void ReadActions(); | 166 void ReadActions(); |
| 170 | 167 |
| 171 // Creates a ui::DragDropTypes::DragOperation representation of the current | 168 // Creates a ui::DragDropTypes::DragOperation representation of the current |
| 172 // action list. | 169 // action list. |
| 173 int GetDragOperation() const; | 170 int GetDragOperation() const; |
| 174 | 171 |
| 175 private: | 172 private: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 189 DesktopDragDropClientAuraX11* drag_drop_client_; | 186 DesktopDragDropClientAuraX11* drag_drop_client_; |
| 190 | 187 |
| 191 // Whether we're blocking the handling of an XdndPosition message by waiting | 188 // Whether we're blocking the handling of an XdndPosition message by waiting |
| 192 // for |unfetched_targets_| to be fetched. | 189 // for |unfetched_targets_| to be fetched. |
| 193 bool waiting_to_handle_position_; | 190 bool waiting_to_handle_position_; |
| 194 | 191 |
| 195 // Where the cursor is on screen. | 192 // Where the cursor is on screen. |
| 196 gfx::Point screen_point_; | 193 gfx::Point screen_point_; |
| 197 | 194 |
| 198 // A SelectionFormatMap of data that we have in our process. | 195 // A SelectionFormatMap of data that we have in our process. |
| 199 scoped_ptr<ui::SelectionFormatMap> fetched_targets_; | 196 ui::SelectionFormatMap fetched_targets_; |
| 200 | 197 |
| 201 // The names of various data types offered by the other window that we | 198 // The names of various data types offered by the other window that we |
| 202 // haven't fetched and put in |fetched_targets_| yet. | 199 // haven't fetched and put in |fetched_targets_| yet. |
| 203 std::vector<Atom> unfetched_targets_; | 200 std::vector<Atom> unfetched_targets_; |
| 204 | 201 |
| 205 // Possible actions. | 202 // Possible actions. |
| 206 std::vector<Atom> actions_; | 203 std::vector<Atom> actions_; |
| 207 | 204 |
| 208 DISALLOW_COPY_AND_ASSIGN(X11DragContext); | 205 DISALLOW_COPY_AND_ASSIGN(X11DragContext); |
| 209 }; | 206 }; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 XSelectInput(base::MessagePumpAuraX11::GetDefaultXDisplay(), | 241 XSelectInput(base::MessagePumpAuraX11::GetDefaultXDisplay(), |
| 245 source_window_, PropertyChangeMask); | 242 source_window_, PropertyChangeMask); |
| 246 | 243 |
| 247 // We must perform a full sync here because we could be racing | 244 // We must perform a full sync here because we could be racing |
| 248 // |source_window_|. | 245 // |source_window_|. |
| 249 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), False); | 246 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), False); |
| 250 } else { | 247 } else { |
| 251 // This drag originates from an aura window within our process. This means | 248 // This drag originates from an aura window within our process. This means |
| 252 // that we can shortcut the X11 server and ask the owning SelectionOwner | 249 // that we can shortcut the X11 server and ask the owning SelectionOwner |
| 253 // for the data it's offering. | 250 // for the data it's offering. |
| 254 fetched_targets_ = client->CloneFormatMap(); | 251 fetched_targets_ = client->GetFormatMap(); |
| 255 unfetched_targets_.clear(); | 252 unfetched_targets_.clear(); |
| 256 } | 253 } |
| 257 | 254 |
| 258 ReadActions(); | 255 ReadActions(); |
| 259 } | 256 } |
| 260 | 257 |
| 261 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { | 258 DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() { |
| 262 DesktopDragDropClientAuraX11* client = | 259 DesktopDragDropClientAuraX11* client = |
| 263 DesktopDragDropClientAuraX11::GetForWindow(source_window_); | 260 DesktopDragDropClientAuraX11::GetForWindow(source_window_); |
| 264 if (!client) { | 261 if (!client) { |
| 265 // Unsubscribe from message events. | 262 // Unsubscribe from message events. |
| 266 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow( | 263 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow( |
| 267 source_window_); | 264 source_window_); |
| 268 } | 265 } |
| 269 } | 266 } |
| 270 | 267 |
| 271 void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage( | 268 void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage( |
| 272 DesktopDragDropClientAuraX11* client, | 269 DesktopDragDropClientAuraX11* client, |
| 273 ::Window source_window, | 270 ::Window source_window, |
| 274 const gfx::Point& screen_point) { | 271 const gfx::Point& screen_point) { |
| 275 DCHECK_EQ(source_window_, source_window); | 272 DCHECK_EQ(source_window_, source_window); |
| 276 | 273 |
| 277 if (!unfetched_targets_.empty()) { | 274 if (!unfetched_targets_.empty()) { |
| 278 // We have unfetched targets. That means we need to pause the handling of | 275 // We have unfetched targets. That means we need to pause the handling of |
| 279 // the position message and ask the other window for its data. | 276 // the position message and ask the other window for its data. |
| 280 screen_point_ = screen_point; | 277 screen_point_ = screen_point; |
| 281 drag_drop_client_ = client; | 278 drag_drop_client_ = client; |
| 282 waiting_to_handle_position_ = true; | 279 waiting_to_handle_position_ = true; |
| 283 | 280 |
| 284 fetched_targets_.reset(new ui::SelectionFormatMap); | 281 fetched_targets_ = ui::SelectionFormatMap(); |
| 285 RequestNextTarget(); | 282 RequestNextTarget(); |
| 286 } else { | 283 } else { |
| 287 client->CompleteXdndPosition(source_window, screen_point); | 284 client->CompleteXdndPosition(source_window, screen_point); |
| 288 } | 285 } |
| 289 } | 286 } |
| 290 | 287 |
| 291 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { | 288 void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() { |
| 292 ::Atom target = unfetched_targets_.back(); | 289 ::Atom target = unfetched_targets_.back(); |
| 293 unfetched_targets_.pop_back(); | 290 unfetched_targets_.pop_back(); |
| 294 | 291 |
| 295 XConvertSelection(base::MessagePumpAuraX11::GetDefaultXDisplay(), | 292 XConvertSelection(base::MessagePumpAuraX11::GetDefaultXDisplay(), |
| 296 atom_cache_->GetAtom(kXdndSelection), | 293 atom_cache_->GetAtom(kXdndSelection), |
| 297 target, | 294 target, |
| 298 atom_cache_->GetAtom(kChromiumDragReciever), | 295 atom_cache_->GetAtom(kChromiumDragReciever), |
| 299 local_window_, | 296 local_window_, |
| 300 CurrentTime); | 297 CurrentTime); |
| 301 } | 298 } |
| 302 | 299 |
| 303 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify( | 300 void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify( |
| 304 const XSelectionEvent& event) { | 301 const XSelectionEvent& event) { |
| 305 DCHECK(waiting_to_handle_position_); | 302 DCHECK(waiting_to_handle_position_); |
| 306 DCHECK(drag_drop_client_); | 303 DCHECK(drag_drop_client_); |
| 307 DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever)); | 304 DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever)); |
| 308 | 305 |
| 309 unsigned char* data = NULL; | 306 scoped_refptr<base::RefCountedMemory> data; |
| 310 size_t data_bytes = 0; | |
| 311 ::Atom type = None; | 307 ::Atom type = None; |
| 312 if (ui::GetRawBytesOfProperty(local_window_, event.property, | 308 if (ui::GetRawBytesOfProperty(local_window_, event.property, |
| 313 &data, &data_bytes, NULL, &type)) { | 309 &data, NULL, NULL, &type)) { |
| 314 char* copied_data = new char[data_bytes]; | 310 fetched_targets_.Insert(event.target, data); |
| 315 memcpy(copied_data, data, data_bytes); | |
| 316 fetched_targets_->Insert(event.target, copied_data, data_bytes); | |
| 317 XFree(data); | |
| 318 } | 311 } |
| 319 | 312 |
| 320 if (!unfetched_targets_.empty()) { | 313 if (!unfetched_targets_.empty()) { |
| 321 RequestNextTarget(); | 314 RequestNextTarget(); |
| 322 } else { | 315 } else { |
| 323 waiting_to_handle_position_ = false; | 316 waiting_to_handle_position_ = false; |
| 324 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_); | 317 drag_drop_client_->CompleteXdndPosition(source_window_, screen_point_); |
| 325 drag_drop_client_ = NULL; | 318 drag_drop_client_ = NULL; |
| 326 } | 319 } |
| 327 } | 320 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 DVLOG(1) << "XdndDrop"; | 503 DVLOG(1) << "XdndDrop"; |
| 511 | 504 |
| 512 unsigned long source_window = event.data.l[0]; | 505 unsigned long source_window = event.data.l[0]; |
| 513 | 506 |
| 514 int drag_operation = ui::DragDropTypes::DRAG_NONE; | 507 int drag_operation = ui::DragDropTypes::DRAG_NONE; |
| 515 if (target_window_) { | 508 if (target_window_) { |
| 516 aura::client::DragDropDelegate* delegate = | 509 aura::client::DragDropDelegate* delegate = |
| 517 aura::client::GetDragDropDelegate(target_window_); | 510 aura::client::GetDragDropDelegate(target_window_); |
| 518 if (delegate) { | 511 if (delegate) { |
| 519 ui::OSExchangeData data(new ui::OSExchangeDataProviderAuraX11( | 512 ui::OSExchangeData data(new ui::OSExchangeDataProviderAuraX11( |
| 520 xwindow_, target_current_context_->CloneFetchedTargets())); | 513 xwindow_, target_current_context_->fetched_targets())); |
| 521 | 514 |
| 522 ui::DropTargetEvent event(data, | 515 ui::DropTargetEvent event(data, |
| 523 target_window_location_, | 516 target_window_location_, |
| 524 target_window_root_location_, | 517 target_window_root_location_, |
| 525 target_current_context_->GetDragOperation()); | 518 target_current_context_->GetDragOperation()); |
| 526 drag_operation = delegate->OnPerformDrop(event); | 519 drag_operation = delegate->OnPerformDrop(event); |
| 527 } | 520 } |
| 528 | 521 |
| 529 target_window_->RemoveObserver(this); | 522 target_window_->RemoveObserver(this); |
| 530 target_window_ = NULL; | 523 target_window_ = NULL; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 target_window_changed = true; | 679 target_window_changed = true; |
| 687 } | 680 } |
| 688 *delegate = NULL; | 681 *delegate = NULL; |
| 689 if (!target_window_) | 682 if (!target_window_) |
| 690 return; | 683 return; |
| 691 *delegate = aura::client::GetDragDropDelegate(target_window_); | 684 *delegate = aura::client::GetDragDropDelegate(target_window_); |
| 692 if (!*delegate) | 685 if (!*delegate) |
| 693 return; | 686 return; |
| 694 | 687 |
| 695 data->reset(new OSExchangeData(new ui::OSExchangeDataProviderAuraX11( | 688 data->reset(new OSExchangeData(new ui::OSExchangeDataProviderAuraX11( |
| 696 xwindow_, target_current_context_->CloneFetchedTargets()))); | 689 xwindow_, target_current_context_->fetched_targets()))); |
| 697 gfx::Point location = root_location; | 690 gfx::Point location = root_location; |
| 698 aura::Window::ConvertPointToTarget(root_window_, target_window_, &location); | 691 aura::Window::ConvertPointToTarget(root_window_, target_window_, &location); |
| 699 | 692 |
| 700 target_window_location_ = location; | 693 target_window_location_ = location; |
| 701 target_window_root_location_ = root_location; | 694 target_window_root_location_ = root_location; |
| 702 | 695 |
| 703 event->reset(new ui::DropTargetEvent( | 696 event->reset(new ui::DropTargetEvent( |
| 704 *(data->get()), | 697 *(data->get()), |
| 705 location, | 698 location, |
| 706 root_location, | 699 root_location, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 std::vector< ::Atom> operations; | 740 std::vector< ::Atom> operations; |
| 748 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY) | 741 if (drag_operation_ & ui::DragDropTypes::DRAG_COPY) |
| 749 operations.push_back(atom_cache_.GetAtom(kXdndActionCopy)); | 742 operations.push_back(atom_cache_.GetAtom(kXdndActionCopy)); |
| 750 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE) | 743 if (drag_operation_ & ui::DragDropTypes::DRAG_MOVE) |
| 751 operations.push_back(atom_cache_.GetAtom(kXdndActionMove)); | 744 operations.push_back(atom_cache_.GetAtom(kXdndActionMove)); |
| 752 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) | 745 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) |
| 753 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); | 746 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); |
| 754 return operations; | 747 return operations; |
| 755 } | 748 } |
| 756 | 749 |
| 757 scoped_ptr<ui::SelectionFormatMap> | 750 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { |
| 758 DesktopDragDropClientAuraX11::CloneFormatMap() const { | 751 return source_provider_ ? source_provider_->GetFormatMap() : |
| 759 return source_provider_ ? source_provider_->CloneFormatMap() : | 752 ui::SelectionFormatMap(); |
| 760 scoped_ptr<ui::SelectionFormatMap>(); | |
| 761 } | 753 } |
| 762 | 754 |
| 763 void DesktopDragDropClientAuraX11::CompleteXdndPosition( | 755 void DesktopDragDropClientAuraX11::CompleteXdndPosition( |
| 764 ::Window source_window, | 756 ::Window source_window, |
| 765 const gfx::Point& screen_point) { | 757 const gfx::Point& screen_point) { |
| 766 int drag_operation = ui::DragDropTypes::DRAG_NONE; | 758 int drag_operation = ui::DragDropTypes::DRAG_NONE; |
| 767 scoped_ptr<ui::OSExchangeData> data; | 759 scoped_ptr<ui::OSExchangeData> data; |
| 768 scoped_ptr<ui::DropTargetEvent> drop_target_event; | 760 scoped_ptr<ui::DropTargetEvent> drop_target_event; |
| 769 DragDropDelegate* delegate = NULL; | 761 DragDropDelegate* delegate = NULL; |
| 770 DragTranslate(screen_point, &data, &drop_target_event, &delegate); | 762 DragTranslate(screen_point, &data, &drop_target_event, &delegate); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 // GdkEvent about the failed drag. (And sending this message doesn't appear | 899 // GdkEvent about the failed drag. (And sending this message doesn't appear |
| 908 // to go through normal xlib machinery, but instead passes through the low | 900 // to go through normal xlib machinery, but instead passes through the low |
| 909 // level xProto (the x11 wire format) that I don't understand. | 901 // level xProto (the x11 wire format) that I don't understand. |
| 910 // | 902 // |
| 911 // I'm unsure if I have to jump through those hoops, or if XSendEvent is | 903 // I'm unsure if I have to jump through those hoops, or if XSendEvent is |
| 912 // sufficient. | 904 // sufficient. |
| 913 XSendEvent(xdisplay_, xid, False, 0, xev); | 905 XSendEvent(xdisplay_, xid, False, 0, xev); |
| 914 } | 906 } |
| 915 | 907 |
| 916 } // namespace views | 908 } // namespace views |
| OLD | NEW |