Home | History | Annotate | Download | only in desktop_aura
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
      6 
      7 #include "ui/aura/client/drag_drop_client.h"
      8 #include "ui/aura/client/drag_drop_delegate.h"
      9 #include "ui/aura/window.h"
     10 #include "ui/aura/root_window.h"
     11 #include "ui/base/dragdrop/drag_drop_types.h"
     12 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
     13 #include "ui/base/events/event.h"
     14 
     15 using aura::client::DragDropDelegate;
     16 using ui::OSExchangeData;
     17 using ui::OSExchangeDataProviderWin;
     18 
     19 namespace views {
     20 
     21 DesktopDropTargetWin::DesktopDropTargetWin(aura::RootWindow* root_window,
     22                                            HWND window)
     23     : ui::DropTargetWin(window),
     24       root_window_(root_window),
     25       target_window_(NULL) {
     26 }
     27 
     28 DesktopDropTargetWin::~DesktopDropTargetWin() {
     29   if (target_window_)
     30     target_window_->RemoveObserver(this);
     31 }
     32 
     33 DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object,
     34                                         DWORD key_state,
     35                                         POINT position,
     36                                         DWORD effect) {
     37   scoped_ptr<OSExchangeData> data;
     38   scoped_ptr<ui::DropTargetEvent> event;
     39   DragDropDelegate* delegate;
     40   // Translate will call OnDragEntered.
     41   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     42   return ui::DragDropTypes::DragOperationToDropEffect(
     43       ui::DragDropTypes::DRAG_NONE);
     44 }
     45 
     46 DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object,
     47                                        DWORD key_state,
     48                                        POINT position,
     49                                        DWORD effect) {
     50   int drag_operation = ui::DragDropTypes::DRAG_NONE;
     51   scoped_ptr<OSExchangeData> data;
     52   scoped_ptr<ui::DropTargetEvent> event;
     53   DragDropDelegate* delegate;
     54   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     55   if (delegate)
     56     drag_operation = delegate->OnDragUpdated(*event);
     57   return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
     58 }
     59 
     60 void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) {
     61   NotifyDragLeave();
     62 }
     63 
     64 DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object,
     65                                    DWORD key_state,
     66                                    POINT position,
     67                                    DWORD effect) {
     68   int drag_operation = ui::DragDropTypes::DRAG_NONE;
     69   scoped_ptr<OSExchangeData> data;
     70   scoped_ptr<ui::DropTargetEvent> event;
     71   DragDropDelegate* delegate;
     72   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     73   if (delegate)
     74     drag_operation = delegate->OnPerformDrop(*event);
     75   if (target_window_) {
     76     target_window_->RemoveObserver(this);
     77     target_window_ = NULL;
     78   }
     79   return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
     80 }
     81 
     82 void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) {
     83   DCHECK(window == target_window_);
     84   target_window_ = NULL;
     85 }
     86 
     87 void DesktopDropTargetWin::Translate(
     88     IDataObject* data_object,
     89     DWORD key_state,
     90     POINT position,
     91     DWORD effect,
     92     scoped_ptr<OSExchangeData>* data,
     93     scoped_ptr<ui::DropTargetEvent>* event,
     94     DragDropDelegate** delegate) {
     95   gfx::Point location(position.x, position.y);
     96   gfx::Point root_location = location;
     97   root_window_->ConvertPointFromNativeScreen(&root_location);
     98   aura::Window* target_window =
     99       root_window_->GetEventHandlerForPoint(root_location);
    100   bool target_window_changed = false;
    101   if (target_window != target_window_) {
    102     if (target_window_)
    103       NotifyDragLeave();
    104     target_window_ = target_window;
    105     if (target_window_)
    106       target_window_->AddObserver(this);
    107     target_window_changed = true;
    108   }
    109   *delegate = NULL;
    110   if (!target_window_)
    111     return;
    112   *delegate = aura::client::GetDragDropDelegate(target_window_);
    113   if (!*delegate)
    114     return;
    115 
    116   data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object)));
    117   location = root_location;
    118   aura::Window::ConvertPointToTarget(root_window_, target_window_, &location);
    119   event->reset(new ui::DropTargetEvent(
    120       *(data->get()),
    121       location,
    122       root_location,
    123       ui::DragDropTypes::DropEffectToDragOperation(effect)));
    124   if (target_window_changed)
    125     (*delegate)->OnDragEntered(*event->get());
    126 }
    127 
    128 void DesktopDropTargetWin::NotifyDragLeave() {
    129   if (!target_window_)
    130     return;
    131   DragDropDelegate* delegate =
    132       aura::client::GetDragDropDelegate(target_window_);
    133   if (delegate)
    134     delegate->OnDragExited();
    135   target_window_->RemoveObserver(this);
    136   target_window_ = NULL;
    137 }
    138 
    139 }  // namespace views
    140