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