Home | History | Annotate | Download | only in drag_drop
      1 // Copyright (c) 2013 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 "ash/drag_drop/drag_drop_controller.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/test/ash_test_base.h"
      9 #include "base/bind.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "ui/aura/root_window.h"
     13 #include "ui/base/dragdrop/drag_drop_types.h"
     14 #include "ui/base/test/ui_controls.h"
     15 #include "ui/views/view.h"
     16 #include "ui/views/widget/widget.h"
     17 
     18 namespace ash {
     19 namespace internal {
     20 namespace {
     21 
     22 class DraggableView : public views::View {
     23  public:
     24   DraggableView() {}
     25   virtual ~DraggableView() {}
     26 
     27   // views::View overrides:
     28   virtual int GetDragOperations(const gfx::Point& press_pt) OVERRIDE {
     29     return ui::DragDropTypes::DRAG_MOVE;
     30   }
     31   virtual void WriteDragData(const gfx::Point& press_pt,
     32                              OSExchangeData* data)OVERRIDE {
     33     data->SetString(UTF8ToUTF16("test"));
     34   }
     35 
     36  private:
     37   DISALLOW_COPY_AND_ASSIGN(DraggableView);
     38 };
     39 
     40 class TargetView : public views::View {
     41  public:
     42   TargetView() : dropped_(false) {}
     43   virtual ~TargetView() {}
     44 
     45   // views::View overrides:
     46   virtual bool GetDropFormats(
     47       int* formats,
     48       std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE {
     49     *formats = ui::OSExchangeData::STRING;
     50     return true;
     51   }
     52   virtual bool AreDropTypesRequired() OVERRIDE {
     53     return false;
     54   }
     55   virtual bool CanDrop(const OSExchangeData& data) OVERRIDE {
     56     return true;
     57   }
     58   virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE {
     59     return ui::DragDropTypes::DRAG_MOVE;
     60   }
     61   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE {
     62     dropped_ = true;
     63     return ui::DragDropTypes::DRAG_MOVE;
     64   }
     65 
     66   bool dropped() const { return dropped_; }
     67 
     68  private:
     69   bool dropped_;
     70 
     71   DISALLOW_COPY_AND_ASSIGN(TargetView);
     72 };
     73 
     74 views::Widget* CreateWidget(views::View* contents_view,
     75                             const gfx::Rect& bounds) {
     76   views::Widget* widget = new views::Widget;
     77   views::Widget::InitParams params;
     78   params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
     79   params.accept_events = true;
     80   params.context = Shell::GetPrimaryRootWindow();
     81   params.bounds = bounds;
     82   widget->Init(params);
     83 
     84   widget->SetContentsView(contents_view);
     85   widget->Show();
     86   return widget;
     87 }
     88 
     89 void QuitLoop() {
     90   base::MessageLoop::current()->Quit();
     91 }
     92 
     93 void DragDropAcrossMultiDisplay_Step4() {
     94   ui_controls::SendMouseEventsNotifyWhenDone(
     95       ui_controls::LEFT, ui_controls::UP,
     96       base::Bind(&QuitLoop));
     97 }
     98 
     99 void DragDropAcrossMultiDisplay_Step3() {
    100   // Move to the edge of the 1st display so that the mouse
    101   // is moved to 2nd display by ash.
    102   ui_controls::SendMouseMoveNotifyWhenDone(
    103       399, 10,
    104       base::Bind(&DragDropAcrossMultiDisplay_Step4));
    105 }
    106 
    107 void DragDropAcrossMultiDisplay_Step2() {
    108   ui_controls::SendMouseMoveNotifyWhenDone(
    109       20, 10,
    110       base::Bind(&DragDropAcrossMultiDisplay_Step3));
    111 }
    112 
    113 void DragDropAcrossMultiDisplay_Step1() {
    114   ui_controls::SendMouseEventsNotifyWhenDone(
    115       ui_controls::LEFT, ui_controls::DOWN,
    116       base::Bind(&DragDropAcrossMultiDisplay_Step2));
    117 }
    118 
    119 }  // namespace
    120 
    121 typedef test::AshTestBase DragDropTest;
    122 
    123 #if defined(OS_WIN)
    124 #define MAYBE_DragDropAcrossMultiDisplay DISABLED_DragDropAcrossMultiDisplay
    125 #else
    126 #define MAYBE_DragDropAcrossMultiDisplay DragDropAcrossMultiDisplay
    127 #endif
    128 
    129 // Test if the mouse gets moved properly to another display
    130 // during drag & drop operation.
    131 TEST_F(DragDropTest, MAYBE_DragDropAcrossMultiDisplay) {
    132   if (!SupportsMultipleDisplays())
    133     return;
    134 
    135   UpdateDisplay("400x400,400x400");
    136   aura::Window::Windows root_windows =
    137       Shell::GetInstance()->GetAllRootWindows();
    138   views::View* draggable_view = new DraggableView();
    139   draggable_view->set_drag_controller(NULL);
    140   draggable_view->SetBounds(0, 0, 100, 100);
    141   views::Widget* source =
    142       CreateWidget(draggable_view, gfx::Rect(0, 0, 100, 100));
    143 
    144   TargetView* target_view = new TargetView();
    145   target_view->SetBounds(0, 0, 100, 100);
    146   views::Widget* target =
    147       CreateWidget(target_view, gfx::Rect(400, 0, 100, 100));
    148 
    149   // Make sure they're on the different root windows.
    150   EXPECT_EQ(root_windows[0], source->GetNativeView()->GetRootWindow());
    151   EXPECT_EQ(root_windows[1], target->GetNativeView()->GetRootWindow());
    152 
    153   ui_controls::SendMouseMoveNotifyWhenDone(
    154       10, 10, base::Bind(&DragDropAcrossMultiDisplay_Step1));
    155 
    156   base::MessageLoop::current()->Run();
    157 
    158   EXPECT_TRUE(target_view->dropped());
    159 
    160   source->Close();
    161   target->Close();
    162 }
    163 
    164 }  // namespace internal
    165 }  // namespace ash
    166