menu_view_drag_and_drop_test.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/menu_test_base.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/interactive_test_utils.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/dragdrop/drag_drop_types.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_controller.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/views/controls/menu/menu_runner.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/submenu_view.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Borrowed from chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// since these are also disabled on Linux for drag and drop. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(erg): Fix DND tests on linux_aura. crbug.com/163931 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) && defined(USE_AURA) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAYBE(x) DISABLED_##x 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAYBE(x) x 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestNestedDragData[] = "test_nested_drag_data"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestTopLevelDragData[] = "test_top_level_drag_data"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple view which can be dragged. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestDragView : public views::View { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestDragView(); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~TestDragView(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::View: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int GetDragOperations(const gfx::Point& point) OVERRIDE; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void WriteDragData(const gfx::Point& point, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::OSExchangeData* data) OVERRIDE; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestDragView); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestDragView::TestDragView() { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestDragView::~TestDragView() { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestDragView::GetDragOperations(const gfx::Point& point) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestDragView::WriteDragData(const gfx::Point& point, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::OSExchangeData* data) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->SetString(base::ASCIIToUTF16(kTestNestedDragData)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple view to serve as a drop target. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestTargetView : public views::View { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestTargetView(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~TestTargetView(); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes this view to have the same bounds as |parent| and two draggable 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // child views. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Init(views::View* parent); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool dragging() const { return dragging_; } 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool dropped() const { return dropped_; } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::View: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool GetDropFormats( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool AreDropTypesRequired() OVERRIDE; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool CanDrop(const OSExchangeData& data) OVERRIDE; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnDragExited() OVERRIDE; 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Whether or not we are currently dragging. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool dragging_; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Whether or not a drop has been performed on the view. 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool dropped_; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestTargetView); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestTargetView::TestTargetView() : dragging_(false), dropped_(false) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestTargetView::Init(views::View* parent) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, match the parent's size. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSize(parent->size()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then add two draggable views, each 10x2. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* first = new TestDragView(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(first); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first->SetBounds(2, 2, 10, 2); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* second = new TestDragView(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(second); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) second->SetBounds(15, 2, 10, 2); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestTargetView::~TestTargetView() { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestTargetView::GetDropFormats( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *formats = ui::OSExchangeData::STRING; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestTargetView::AreDropTypesRequired() { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestTargetView::CanDrop(const OSExchangeData& data) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::string16 contents; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data.GetString(&contents) && 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents == base::ASCIIToUTF16(kTestNestedDragData); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestTargetView::OnDragEntered(const ui::DropTargetEvent& event) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dragging_ = true; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint TestTargetView::OnDragUpdated(const ui::DropTargetEvent& event) { 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ui::DragDropTypes::DRAG_MOVE; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestTargetView::OnPerformDrop(const ui::DropTargetEvent& event) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dragging_ = false; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dropped_ = true; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestTargetView::OnDragExited() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dragging_ = false; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuViewDragAndDropTest : public MenuTestBase { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuViewDragAndDropTest(); 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~MenuViewDragAndDropTest(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected: 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TestTargetView* target_view() { return target_view_; } 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool asked_to_close() const { return asked_to_close_; } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool performed_in_menu_drop() const { return performed_in_menu_drop_; } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MenuTestBase: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::MenuDelegate: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool GetDropFormats( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::MenuItemView* menu, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool AreDropTypesRequired(views::MenuItemView* menu) OVERRIDE; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool CanDrop(views::MenuItemView* menu, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::OSExchangeData& data) OVERRIDE; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int GetDropOperation(views::MenuItemView* item, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DropPosition* position) OVERRIDE; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnPerformDrop(views::MenuItemView* menu, 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DropPosition position, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) OVERRIDE; 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual bool CanDrag(views::MenuItemView* menu) OVERRIDE; 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void WriteDragData(views::MenuItemView* sender, 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::OSExchangeData* data) OVERRIDE; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int GetDragOperations(views::MenuItemView* sender) OVERRIDE; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool ShouldCloseOnDragComplete() OVERRIDE; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The special view in the menu, which supports its own drag and drop. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestTargetView* target_view_; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether or not we have been asked to close on drag complete. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool asked_to_close_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether or not a drop was performed in-menu (i.e., not including drops 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in separate child views). 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool performed_in_menu_drop_; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MenuViewDragAndDropTest); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MenuViewDragAndDropTest::MenuViewDragAndDropTest() 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : target_view_(NULL), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) asked_to_close_(false), 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) performed_in_menu_drop_(false) { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MenuViewDragAndDropTest::~MenuViewDragAndDropTest() { 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MenuViewDragAndDropTest::BuildMenu(views::MenuItemView* menu) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build a menu item that has a nested view that supports its own drag and 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drop... 208 views::MenuItemView* menu_item_view = 209 menu->AppendMenuItem(1, 210 base::ASCIIToUTF16("item 1"), 211 views::MenuItemView::NORMAL); 212 target_view_ = new TestTargetView(); 213 menu_item_view->AddChildView(target_view_); 214 // ... as well as two other, normal items. 215 menu->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("item 2")); 216 menu->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("item 3")); 217} 218 219bool MenuViewDragAndDropTest::GetDropFormats( 220 views::MenuItemView* menu, 221 int* formats, 222 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { 223 *formats = ui::OSExchangeData::STRING; 224 return true; 225} 226 227bool MenuViewDragAndDropTest::AreDropTypesRequired(views::MenuItemView* menu) { 228 return true; 229} 230 231bool MenuViewDragAndDropTest::CanDrop(views::MenuItemView* menu, 232 const ui::OSExchangeData& data) { 233 base::string16 contents; 234 return data.GetString(&contents) && 235 contents == base::ASCIIToUTF16(kTestTopLevelDragData); 236} 237 238int MenuViewDragAndDropTest::GetDropOperation(views::MenuItemView* item, 239 const ui::DropTargetEvent& event, 240 DropPosition* position) { 241 return ui::DragDropTypes::DRAG_MOVE; 242} 243 244 245int MenuViewDragAndDropTest::OnPerformDrop(views::MenuItemView* menu, 246 DropPosition position, 247 const ui::DropTargetEvent& event) { 248 performed_in_menu_drop_ = true; 249 return ui::DragDropTypes::DRAG_MOVE; 250} 251 252bool MenuViewDragAndDropTest::CanDrag(views::MenuItemView* menu) { 253 return true; 254} 255 256void MenuViewDragAndDropTest::WriteDragData( 257 views::MenuItemView* sender, ui::OSExchangeData* data) { 258 data->SetString(base::ASCIIToUTF16(kTestTopLevelDragData)); 259} 260 261int MenuViewDragAndDropTest::GetDragOperations(views::MenuItemView* sender) { 262 return ui::DragDropTypes::DRAG_MOVE; 263} 264 265bool MenuViewDragAndDropTest::ShouldCloseOnDragComplete() { 266 asked_to_close_ = true; 267 return false; 268} 269 270class MenuViewDragAndDropTestTestInMenuDrag : public MenuViewDragAndDropTest { 271 public: 272 MenuViewDragAndDropTestTestInMenuDrag() {} 273 virtual ~MenuViewDragAndDropTestTestInMenuDrag() {} 274 275 private: 276 // MenuViewDragAndDropTest: 277 virtual void DoTestWithMenuOpen() OVERRIDE; 278 279 void Step2(); 280 void Step3(); 281 void Step4(); 282}; 283 284void MenuViewDragAndDropTestTestInMenuDrag::DoTestWithMenuOpen() { 285 // A few sanity checks to make sure the menu built correctly. 286 views::SubmenuView* submenu = menu()->GetSubmenu(); 287 ASSERT_TRUE(submenu); 288 ASSERT_TRUE(submenu->IsShowing()); 289 ASSERT_EQ(3, submenu->GetMenuItemCount()); 290 291 // We do this here (instead of in BuildMenu()) so that the menu is already 292 // built and the bounds are correct. 293 target_view()->Init(submenu->GetMenuItemAt(0)); 294 295 // We're going to drag the second menu element. 296 views::MenuItemView* drag_view = submenu->GetMenuItemAt(1); 297 ASSERT_TRUE(drag_view != NULL); 298 299 // Move mouse to center of menu and press button. 300 ui_test_utils::MoveMouseToCenterAndPress( 301 drag_view, 302 ui_controls::LEFT, 303 ui_controls::DOWN, 304 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step2)); 305} 306 307void MenuViewDragAndDropTestTestInMenuDrag::Step2() { 308 views::MenuItemView* drop_target = menu()->GetSubmenu()->GetMenuItemAt(2); 309 gfx::Point loc(1, drop_target->height() - 1); 310 views::View::ConvertPointToScreen(drop_target, &loc); 311 312 // Start a drag. 313 ui_controls::SendMouseMoveNotifyWhenDone( 314 loc.x() + 10, 315 loc.y(), 316 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step3)); 317 318 ScheduleMouseMoveInBackground(loc.x(), loc.y()); 319} 320 321void MenuViewDragAndDropTestTestInMenuDrag::Step3() { 322 // Drop the item on the target. 323 views::MenuItemView* drop_target = menu()->GetSubmenu()->GetMenuItemAt(2); 324 gfx::Point loc(1, drop_target->height() - 2); 325 views::View::ConvertPointToScreen(drop_target, &loc); 326 ui_controls::SendMouseMove(loc.x(), loc.y()); 327 328 ui_controls::SendMouseEventsNotifyWhenDone( 329 ui_controls::LEFT, 330 ui_controls::UP, 331 CreateEventTask(this, &MenuViewDragAndDropTestTestInMenuDrag::Step4)); 332} 333 334void MenuViewDragAndDropTestTestInMenuDrag::Step4() { 335 // Verify our state. 336 // We should have performed an in-menu drop, and the nested view should not 337 // have had a drag and drop. Since the drag happened in menu code, the 338 // delegate should not have been asked whether or not to close, and the menu 339 // should simply be closed. 340 EXPECT_TRUE(performed_in_menu_drop()); 341 EXPECT_FALSE(target_view()->dropped()); 342 EXPECT_FALSE(asked_to_close()); 343 EXPECT_FALSE(menu()->GetSubmenu()->IsShowing()); 344 345 Done(); 346} 347 348// Test that an in-menu (i.e., entirely implemented in the menu code) closes the 349// menu automatically once the drag is complete, and does not ask the delegate 350// to stay open. 351VIEW_TEST(MenuViewDragAndDropTestTestInMenuDrag, MAYBE(TestInMenuDrag)) 352 353class MenuViewDragAndDropTestNestedDrag : public MenuViewDragAndDropTest { 354 public: 355 MenuViewDragAndDropTestNestedDrag() {} 356 virtual ~MenuViewDragAndDropTestNestedDrag() {} 357 358 private: 359 // MenuViewDragAndDropTest: 360 virtual void DoTestWithMenuOpen() OVERRIDE; 361 362 void Step2(); 363 void Step3(); 364 void Step4(); 365}; 366 367void MenuViewDragAndDropTestNestedDrag::DoTestWithMenuOpen() { 368 // Sanity checks: We should be showing the menu, it should have three 369 // children, and the first of those children should have a nested view of the 370 // TestTargetView. 371 views::SubmenuView* submenu = menu()->GetSubmenu(); 372 ASSERT_TRUE(submenu); 373 ASSERT_TRUE(submenu->IsShowing()); 374 ASSERT_EQ(3, submenu->GetMenuItemCount()); 375 views::View* first_view = submenu->GetMenuItemAt(0); 376 ASSERT_EQ(1, first_view->child_count()); 377 views::View* child_view = first_view->child_at(0); 378 ASSERT_EQ(child_view, target_view()); 379 380 // We do this here (instead of in BuildMenu()) so that the menu is already 381 // built and the bounds are correct. 382 target_view()->Init(submenu->GetMenuItemAt(0)); 383 384 // The target view should now have two children. 385 ASSERT_EQ(2, target_view()->child_count()); 386 387 views::View* drag_view = target_view()->child_at(0); 388 ASSERT_TRUE(drag_view != NULL); 389 390 // Move mouse to center of menu and press button. 391 ui_test_utils::MoveMouseToCenterAndPress( 392 drag_view, 393 ui_controls::LEFT, 394 ui_controls::DOWN, 395 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step2)); 396} 397 398void MenuViewDragAndDropTestNestedDrag::Step2() { 399 views::View* drop_target = target_view()->child_at(1); 400 gfx::Point loc(2, 0); 401 views::View::ConvertPointToScreen(drop_target, &loc); 402 403 // Start a drag. 404 ui_controls::SendMouseMoveNotifyWhenDone( 405 loc.x() + 3, 406 loc.y(), 407 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step3)); 408 409 ScheduleMouseMoveInBackground(loc.x(), loc.y()); 410} 411 412void MenuViewDragAndDropTestNestedDrag::Step3() { 413 // The view should be dragging now. 414 EXPECT_TRUE(target_view()->dragging()); 415 416 // Drop the item so that it's now the second item. 417 views::View* drop_target = target_view()->child_at(1); 418 gfx::Point loc(5, 0); 419 views::View::ConvertPointToScreen(drop_target, &loc); 420 ui_controls::SendMouseMove(loc.x(), loc.y()); 421 422 ui_controls::SendMouseEventsNotifyWhenDone( 423 ui_controls::LEFT, 424 ui_controls::UP, 425 CreateEventTask(this, &MenuViewDragAndDropTestNestedDrag::Step4)); 426} 427 428void MenuViewDragAndDropTestNestedDrag::Step4() { 429 // Check our state. 430 // The target view should have finished its drag, and should have dropped the 431 // view. The main menu should not have done any drag, and the delegate should 432 // have been asked if it wanted to close. Since the delegate did not want to 433 // close, the menu should still be open. 434 EXPECT_FALSE(target_view()->dragging()); 435 EXPECT_TRUE(target_view()->dropped()); 436 EXPECT_FALSE(performed_in_menu_drop()); 437 EXPECT_TRUE(asked_to_close()); 438 EXPECT_TRUE(menu()->GetSubmenu()->IsShowing()); 439 440 // Clean up. 441 menu()->GetSubmenu()->Close(); 442 443 Done(); 444} 445 446// Test that a nested drag (i.e. one via a child view, and not entirely 447// implemented in menu code) will consult the delegate before closing the view 448// after the drag. 449VIEW_TEST(MenuViewDragAndDropTestNestedDrag, 450 MAYBE(MenuViewDragAndDropNestedDrag)) 451 452class MenuViewDragAndDropForDropStayOpen : public MenuViewDragAndDropTest { 453 public: 454 MenuViewDragAndDropForDropStayOpen() {} 455 virtual ~MenuViewDragAndDropForDropStayOpen() {} 456 457 private: 458 // MenuViewDragAndDropTest: 459 virtual int GetMenuRunnerFlags() OVERRIDE; 460 virtual void DoTestWithMenuOpen() OVERRIDE; 461}; 462 463int MenuViewDragAndDropForDropStayOpen::GetMenuRunnerFlags() { 464 return views::MenuRunner::HAS_MNEMONICS | 465 views::MenuRunner::NESTED_DRAG | 466 views::MenuRunner::FOR_DROP; 467} 468 469void MenuViewDragAndDropForDropStayOpen::DoTestWithMenuOpen() { 470 views::SubmenuView* submenu = menu()->GetSubmenu(); 471 ASSERT_TRUE(submenu); 472 ASSERT_TRUE(submenu->IsShowing()); 473 474 views::MenuController* controller = menu()->GetMenuController(); 475 ASSERT_TRUE(controller); 476 EXPECT_FALSE(controller->IsCancelAllTimerRunningForTest()); 477 478 Done(); 479} 480 481// Test that if a menu is opened for a drop which is handled by a child view 482// that the menu does not immediately try to close. 483VIEW_TEST(MenuViewDragAndDropForDropStayOpen, MenuViewStaysOpenForNestedDrag) 484 485class MenuViewDragAndDropForDropCancel : public MenuViewDragAndDropTest { 486 public: 487 MenuViewDragAndDropForDropCancel() {} 488 virtual ~MenuViewDragAndDropForDropCancel() {} 489 490 private: 491 // MenuViewDragAndDropTest: 492 virtual int GetMenuRunnerFlags() OVERRIDE; 493 virtual void DoTestWithMenuOpen() OVERRIDE; 494}; 495 496int MenuViewDragAndDropForDropCancel::GetMenuRunnerFlags() { 497 return views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::FOR_DROP; 498} 499 500void MenuViewDragAndDropForDropCancel::DoTestWithMenuOpen() { 501 views::SubmenuView* submenu = menu()->GetSubmenu(); 502 ASSERT_TRUE(submenu); 503 ASSERT_TRUE(submenu->IsShowing()); 504 505 views::MenuController* controller = menu()->GetMenuController(); 506 ASSERT_TRUE(controller); 507 EXPECT_TRUE(controller->IsCancelAllTimerRunningForTest()); 508 509 Done(); 510} 511 512// Test that if a menu is opened for a drop handled entirely by menu code, the 513// menu will try to close if it does not receive any drag updates. 514VIEW_TEST(MenuViewDragAndDropForDropCancel, MenuViewCancelsForOwnDrag) 515