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 "base/win/win_util.h"
      8 #include "ui/aura/window.h"
      9 #include "ui/aura/window_tree_host.h"
     10 #include "ui/base/dragdrop/drag_drop_types.h"
     11 #include "ui/base/dragdrop/drop_target_event.h"
     12 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
     13 #include "ui/events/event_constants.h"
     14 #include "ui/wm/public/drag_drop_client.h"
     15 #include "ui/wm/public/drag_drop_delegate.h"
     16 
     17 using aura::client::DragDropDelegate;
     18 using ui::OSExchangeData;
     19 using ui::OSExchangeDataProviderWin;
     20 
     21 namespace views {
     22 
     23 DesktopDropTargetWin::DesktopDropTargetWin(aura::Window* root_window,
     24                                            HWND window)
     25     : ui::DropTargetWin(window),
     26       root_window_(root_window),
     27       target_window_(NULL) {
     28 }
     29 
     30 DesktopDropTargetWin::~DesktopDropTargetWin() {
     31   if (target_window_)
     32     target_window_->RemoveObserver(this);
     33 }
     34 
     35 DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object,
     36                                         DWORD key_state,
     37                                         POINT position,
     38                                         DWORD effect) {
     39   scoped_ptr<OSExchangeData> data;
     40   scoped_ptr<ui::DropTargetEvent> event;
     41   DragDropDelegate* delegate;
     42   // Translate will call OnDragEntered.
     43   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     44   return ui::DragDropTypes::DragOperationToDropEffect(
     45       ui::DragDropTypes::DRAG_NONE);
     46 }
     47 
     48 DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object,
     49                                        DWORD key_state,
     50                                        POINT position,
     51                                        DWORD effect) {
     52   int drag_operation = ui::DragDropTypes::DRAG_NONE;
     53   scoped_ptr<OSExchangeData> data;
     54   scoped_ptr<ui::DropTargetEvent> event;
     55   DragDropDelegate* delegate;
     56   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     57   if (delegate)
     58     drag_operation = delegate->OnDragUpdated(*event);
     59   return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
     60 }
     61 
     62 void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) {
     63   NotifyDragLeave();
     64 }
     65 
     66 DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object,
     67                                    DWORD key_state,
     68                                    POINT position,
     69                                    DWORD effect) {
     70   int drag_operation = ui::DragDropTypes::DRAG_NONE;
     71   scoped_ptr<OSExchangeData> data;
     72   scoped_ptr<ui::DropTargetEvent> event;
     73   DragDropDelegate* delegate;
     74   Translate(data_object, key_state, position, effect, &data, &event, &delegate);
     75   if (delegate)
     76     drag_operation = delegate->OnPerformDrop(*event);
     77   if (target_window_) {
     78     target_window_->RemoveObserver(this);
     79     target_window_ = NULL;
     80   }
     81   return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
     82 }
     83 
     84 void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) {
     85   DCHECK(window == target_window_);
     86   target_window_ = NULL;
     87 }
     88 
     89 void DesktopDropTargetWin::Translate(
     90     IDataObject* data_object,
     91     DWORD key_state,
     92     POINT position,
     93     DWORD effect,
     94     scoped_ptr<OSExchangeData>* data,
     95     scoped_ptr<ui::DropTargetEvent>* event,
     96     DragDropDelegate** delegate) {
     97   gfx::Point location(position.x, position.y);
     98   gfx::Point root_location = location;
     99   root_window_->GetHost()->ConvertPointFromNativeScreen(
    100       &root_location);
    101   aura::Window* target_window =
    102       root_window_->GetEventHandlerForPoint(root_location);
    103   bool target_window_changed = false;
    104   if (target_window != target_window_) {
    105     if (target_window_)
    106       NotifyDragLeave();
    107     target_window_ = target_window;
    108     if (target_window_)
    109       target_window_->AddObserver(this);
    110     target_window_changed = true;
    111   }
    112   *delegate = NULL;
    113   if (!target_window_)
    114     return;
    115   *delegate = aura::client::GetDragDropDelegate(target_window_);
    116   if (!*delegate)
    117     return;
    118 
    119   data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object)));
    120   location = root_location;
    121   aura::Window::ConvertPointToTarget(root_window_, target_window_, &location);
    122   event->reset(new ui::DropTargetEvent(
    123       *(data->get()),
    124       location,
    125       root_location,
    126       ui::DragDropTypes::DropEffectToDragOperation(effect)));
    127   int flags = 0;
    128   flags |= base::win::IsAltPressed() ? ui::EF_ALT_DOWN : ui::EF_NONE;
    129   flags |= base::win::IsShiftPressed() ? ui::EF_SHIFT_DOWN : ui::EF_NONE;
    130   flags |= base::win::IsCtrlPressed() ? ui::EF_CONTROL_DOWN : ui::EF_NONE;
    131   (*event)->set_flags(flags);
    132   if (target_window_changed)
    133     (*delegate)->OnDragEntered(*event->get());
    134 }
    135 
    136 void DesktopDropTargetWin::NotifyDragLeave() {
    137   if (!target_window_)
    138     return;
    139   DragDropDelegate* delegate =
    140       aura::client::GetDragDropDelegate(target_window_);
    141   if (delegate)
    142     delegate->OnDragExited();
    143   target_window_->RemoveObserver(this);
    144   target_window_ = NULL;
    145 }
    146 
    147 }  // namespace views
    148