tab_drag_controller.h revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of this source code is governed by a BSD-style license that can be 383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius// found in the LICENSE file. 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_ 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_ 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <vector> 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/memory/scoped_ptr.h" 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/memory/weak_ptr.h" 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/message_loop/message_loop.h" 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/timer/timer.h" 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/tabs/dock_info.h" 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/views/tabs/tab_strip_types.h" 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/notification_observer.h" 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/notification_registrar.h" 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/web_contents_delegate.h" 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/base/models/list_selection_model.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/gfx/rect.h" 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/views/widget/widget_observer.h" 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace gfx { 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Screen; 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace ui { 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass ListSelectionModel; 2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace views { 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass View; 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Browser; 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass DraggedTabView; 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Tab; 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct TabRendererData; 37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabStrip; 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabStripModel; 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TabDragController is responsible for managing the tab dragging session. When 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the user presses the mouse on a tab a new TabDragController is created and 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Drag() is invoked as the mouse is dragged. If the mouse is dragged far enough 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TabDragController starts a drag session. The drag session is completed when 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// EndDrag() is invoked (or the TabDragController is destroyed). 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// While dragging within a tab strip TabDragController sets the bounds of the 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// tabs (this is referred to as attached). When the user drags far enough such 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// that the tabs should be moved out of the tab strip two possible things 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// can happen (this state is referred to as detached): 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// . If |detach_into_browser_| is true then a new Browser is created and 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// RunMoveLoop() is invoked on the Widget to drag the browser around. This is 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the default on aura. 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// . If |detach_into_browser_| is false a small representation of the active tab 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// is created and that is dragged around. This mode does not run a nested 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// message loop. 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabDragController : public content::WebContentsDelegate, 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public content::NotificationObserver, 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public base::MessageLoopForUI::Observer, 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public views::WidgetObserver, 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public TabStripModelObserver { 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public: 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum DetachBehavior { 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DETACHABLE, 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NOT_DETACHABLE 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // What should happen as the mouse is dragged within the tabstrip. 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum MoveBehavior { 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Only the set of visible tabs should change. This is only applicable when 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // using touch layout. 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru MOVE_VISIBILE_TABS, 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Typical behavior where tabs are dragged around. 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru REORDER 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Indicates the event source that initiated the drag. 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum EventSource { 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru EVENT_SOURCE_MOUSE, 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru EVENT_SOURCE_TOUCH, 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Amount above or below the tabstrip the user has to drag before detaching. 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru static const int kTouchVerticalDetachMagnetism; 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru static const int kVerticalDetachMagnetism; 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TabDragController(); 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual ~TabDragController(); 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initializes TabDragController to drag the tabs in |tabs| originating from 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // |source_tabstrip|. |source_tab| is the tab that initiated the drag and is 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // contained in |tabs|. |mouse_offset| is the distance of the mouse pointer 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // from the origin of the first tab in |tabs| and |source_tab_offset| the 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // offset from |source_tab|. |source_tab_offset| is the horizontal offset of 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // |mouse_offset| relative to |source_tab|. |initial_selection_model| is the 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // selection model before the drag started and is only non-empty if 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // |source_tab| was not initially selected. 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void Init(TabStrip* source_tabstrip, 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Tab* source_tab, 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const std::vector<Tab*>& tabs, 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const gfx::Point& mouse_offset, 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int source_tab_offset, 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const ui::ListSelectionModel& initial_selection_model, 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DetachBehavior detach_behavior, 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru MoveBehavior move_behavior, 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru EventSource event_source); 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Returns true if there is a drag underway and the drag is attached to 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // |tab_strip|. 11083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius // NOTE: this returns false if the TabDragController is in the process of 11183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius // finishing the drag. 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru static bool IsAttachedTo(TabStrip* tab_strip); 11383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 11483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius // Returns true if there is a drag underway. 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru static bool IsActive(); 11683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 11783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius // Used to determine whether the tab drag controller detaches dragged tabs 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // into new browser windows while the drag is in process. 11983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius static bool ShouldDetachIntoNewBrowser(); 12083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Sets the move behavior. Has no effect if started_drag() is true. 12283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius void SetMoveBehavior(MoveBehavior behavior); 12383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius MoveBehavior move_behavior() const { return move_behavior_; } 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius EventSource event_source() const { return event_source_; } 12683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // See description above fields for details on these. 12883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius bool active() const { return active_; } 12983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius const TabStrip* attached_tabstrip() const { return attached_tabstrip_; } 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Returns true if a drag started. 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool started_drag() const { return started_drag_; } 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Returns true if mutating the TabStripModel. 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool is_mutating() const { return is_mutating_; } 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Returns true if we've detached from a tabstrip and are running a nested 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // move message loop. 13983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius bool is_dragging_window() const { return is_dragging_window_; } 14083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Invoked to drag to the new location, in screen coordinates. 14283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius void Drag(const gfx::Point& point_in_screen); 14383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Complete the current drag session. 14583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius void EndDrag(EndDragReason reason); 14683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private: 14883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius class DockDisplayer; 14983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius friend class DockDisplayer; 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 15183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius typedef std::set<gfx::NativeView> DockWindows; 15283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Used to indicate the direction the mouse has moved when attached. 15483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius static const int kMovedMouseLeft = 1 << 0; 15583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius static const int kMovedMouseRight = 1 << 1; 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 15783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius // Enumeration of the ways a drag session can end. 15883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius enum EndDragType { 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Drag session exited normally: the user released the mouse. 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NORMAL, 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The drag session was canceled (alt-tab during drag, escape ...) 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CANCELED, 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The tab (NavigationController) was destroyed during the drag. 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TAB_DESTROYED 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Whether Detach() should release capture or not. 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum ReleaseCapture { 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru RELEASE_CAPTURE, 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DONT_RELEASE_CAPTURE, 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Specifies what should happen when RunMoveLoop completes. 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum EndRunLoopBehavior { 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Indicates the drag should end. 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru END_RUN_LOOP_STOP_DRAGGING, 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Indicates the drag should continue. 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru END_RUN_LOOP_CONTINUE_DRAGGING 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Enumeration of the possible positions the detached tab may detach from. 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum DetachPosition { 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DETACH_BEFORE, 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DETACH_AFTER, 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DETACH_ABOVE_OR_BELOW 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Indicates what should happen after invoking DragBrowserToNewTabStrip(). 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru enum DragBrowserResultType { 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The caller should return immediately. This return value is used if a 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // nested message loop was created or we're in a nested message loop and 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // need to exit it. 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DRAG_BROWSER_RESULT_STOP, 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The caller should continue. 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DRAG_BROWSER_RESULT_CONTINUE, 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Stores the date associated with a single tab that is being dragged. 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct TabDragData { 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TabDragData(); 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ~TabDragData(); 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The WebContents being dragged. 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru content::WebContents* contents; 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // content::WebContentsDelegate for |contents| before it was detached from 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the browser window. We store this so that we can forward certain delegate 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // notifications back to it if we can't handle them locally. 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru content::WebContentsDelegate* original_delegate; 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This is the index of the tab in |source_tabstrip_| when the drag 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // began. This is used to restore the previous state if the drag is aborted. 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int source_model_index; 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If attached this is the tab in |attached_tabstrip_|. 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Tab* attached_tab; 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Is the tab pinned? 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool pinned; 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru typedef std::vector<TabDragData> DragData; 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Sets |drag_data| from |tab|. This also registers for necessary 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // notifications and resets the delegate of the WebContents. 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void InitTabDragData(Tab* tab, TabDragData* drag_data); 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Overridden from content::WebContentsDelegate: 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual content::WebContents* OpenURLFromTab( 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru content::WebContents* source, 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const content::OpenURLParams& params) OVERRIDE; 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void NavigationStateChanged(const content::WebContents* source, 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unsigned changed_flags) OVERRIDE; 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void AddNewContents(content::WebContents* source, 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru content::WebContents* new_contents, 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru WindowOpenDisposition disposition, 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const gfx::Rect& initial_pos, 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool user_gesture, 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool* was_blocked) OVERRIDE; 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE; 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual bool ShouldSuppressDialogs() OVERRIDE; 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual content::JavaScriptDialogManager* 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru GetJavaScriptDialogManager() OVERRIDE; 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void RequestMediaAccessPermission( 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru content::WebContents* web_contents, 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const content::MediaStreamRequest& request, 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const content::MediaResponseCallback& callback) OVERRIDE; 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Overridden from content::NotificationObserver: 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void Observe(int type, 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const content::NotificationSource& source, 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const content::NotificationDetails& details) OVERRIDE; 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Overridden from MessageLoop::Observer: 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual base::EventStatus WillProcessEvent( 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const base::NativeEvent& event) OVERRIDE; 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Overriden from views::WidgetObserver: 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void OnWidgetBoundsChanged(views::Widget* widget, 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const gfx::Rect& new_bounds) OVERRIDE; 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Overriden from TabStripModelObserver: 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void TabStripEmpty() OVERRIDE; 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initialize the offset used to calculate the position to create windows 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in |GetWindowCreatePoint|. This should only be invoked from |Init|. 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void InitWindowCreatePoint(); 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Returns the point where a detached window should be created given the 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // current mouse position |origin|. 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gfx::Point GetWindowCreatePoint(const gfx::Point& origin) const; 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void UpdateDockInfo(const gfx::Point& point_in_screen); 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Saves focus in the window that the drag initiated from. Focus will be 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // restored appropriately if the drag ends within this same window. 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void SaveFocus(); 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Restore focus to the View that had focus before the drag was started, if 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the drag ends within the same Window as it began. 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void RestoreFocus(); 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Tests whether |point_in_screen| is past a minimum elasticity threshold 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // required to start a drag. 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bool CanStartDrag(const gfx::Point& point_in_screen) const; 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Move the DraggedTabView according to the current mouse screen position, 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // potentially updating the source and other TabStrips. 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void ContinueDragging(const gfx::Point& point_in_screen); 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Transitions dragging from |attached_tabstrip_| to |target_tabstrip|. 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // |target_tabstrip| is NULL if the mouse is not over a valid tab strip. See 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // DragBrowserResultType for details of the return type. 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DragBrowserResultType DragBrowserToNewTabStrip( 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TabStrip* target_tabstrip, 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const gfx::Point& point_in_screen); 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Handles dragging for a touch tabstrip when the tabs are stacked. Doesn't 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // actually reorder the tabs in anyway, just changes what's visible. 30527f654740f2a26ad62a5c155af9199af9e69b889claireho void DragActiveTabStacked(const gfx::Point& point_in_screen); 30627f654740f2a26ad62a5c155af9199af9e69b889claireho 30727f654740f2a26ad62a5c155af9199af9e69b889claireho // Moves the active tab to the next/previous tab. Used when the next/previous 30827f654740f2a26ad62a5c155af9199af9e69b889claireho // tab is stacked. 30927f654740f2a26ad62a5c155af9199af9e69b889claireho void MoveAttachedToNextStackedIndex(const gfx::Point& point_in_screen); 31027f654740f2a26ad62a5c155af9199af9e69b889claireho void MoveAttachedToPreviousStackedIndex(const gfx::Point& point_in_screen); 31127f654740f2a26ad62a5c155af9199af9e69b889claireho 31227f654740f2a26ad62a5c155af9199af9e69b889claireho // Handles dragging tabs while the tabs are attached. 31327f654740f2a26ad62a5c155af9199af9e69b889claireho void MoveAttached(const gfx::Point& point_in_screen); 31427f654740f2a26ad62a5c155af9199af9e69b889claireho 31527f654740f2a26ad62a5c155af9199af9e69b889claireho // Handles dragging while the tabs are detached. 31627f654740f2a26ad62a5c155af9199af9e69b889claireho void MoveDetached(const gfx::Point& point_in_screen); 31727f654740f2a26ad62a5c155af9199af9e69b889claireho 31827f654740f2a26ad62a5c155af9199af9e69b889claireho // If necessary starts the |move_stacked_timer_|. The timer is started if 31927f654740f2a26ad62a5c155af9199af9e69b889claireho // close enough to an edge with stacked tabs. 32027f654740f2a26ad62a5c155af9199af9e69b889claireho void StartMoveStackedTimerIfNecessary( 32127f654740f2a26ad62a5c155af9199af9e69b889claireho const gfx::Point& point_in_screen, 32227f654740f2a26ad62a5c155af9199af9e69b889claireho int delay_ms); 32327f654740f2a26ad62a5c155af9199af9e69b889claireho 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Returns the TabStrip for the specified window, or NULL if one doesn't exist 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // or isn't compatible. 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TabStrip* GetTabStripForWindow(gfx::NativeWindow window); 32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Returns the compatible TabStrip to drag to at the specified point (screen 32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // coordinates), or NULL if there is none. 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TabStrip* GetTargetTabStripForPoint(const gfx::Point& point_in_screen); 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Returns true if |tabstrip| contains the specified point in screen 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // coordinates. 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bool DoesTabStripContain(TabStrip* tabstrip, 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const gfx::Point& point_in_screen) const; 33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Returns the DetachPosition given the specified location in screen 33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // coordinates. 33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DetachPosition GetDetachPosition(const gfx::Point& point_in_screen); 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho DockInfo GetDockInfoAtPoint(const gfx::Point& point_in_screen); 342 343 // Attach the dragged Tab to the specified TabStrip. 344 void Attach(TabStrip* attached_tabstrip, const gfx::Point& point_in_screen); 345 346 // Detach the dragged Tab from the current TabStrip. 347 void Detach(ReleaseCapture release_capture); 348 349 // Detaches the tabs being dragged, creates a new Browser to contain them and 350 // runs a nested move loop. 351 void DetachIntoNewBrowserAndRunMoveLoop(const gfx::Point& point_in_screen); 352 353 // Runs a nested message loop that handles moving the current 354 // Browser. |drag_offset| is the offset from the window origin and is used in 355 // calculating the location of the window offset from the cursor while 356 // dragging. 357 void RunMoveLoop(const gfx::Vector2d& drag_offset); 358 359 // Determines the index to insert tabs at. |dragged_bounds| is the bounds of 360 // the tabs being dragged, |start| the index of the tab to start looking from 361 // and |delta| the amount to increment (1 or -1). 362 int GetInsertionIndexFrom(const gfx::Rect& dragged_bounds, 363 int start, 364 int delta) const; 365 366 // Returns the index where the dragged WebContents should be inserted into 367 // |attached_tabstrip_| given the DraggedTabView's bounds |dragged_bounds| in 368 // coordinates relative to |attached_tabstrip_| and has had the mirroring 369 // transformation applied. 370 // NOTE: this is invoked from Attach() before the tabs have been inserted. 371 int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds) const; 372 373 // Returns true if |dragged_bounds| is close enough to the next stacked tab 374 // so that the active tab should be dragged there. 375 bool ShouldDragToNextStackedTab(const gfx::Rect& dragged_bounds, 376 int index) const; 377 378 // Returns true if |dragged_bounds| is close enough to the previous stacked 379 // tab so that the active tab should be dragged there. 380 bool ShouldDragToPreviousStackedTab(const gfx::Rect& dragged_bounds, 381 int index) const; 382 383 // Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked. 384 int GetInsertionIndexForDraggedBoundsStacked( 385 const gfx::Rect& dragged_bounds) const; 386 387 // Retrieve the bounds of the DraggedTabView relative to the attached 388 // TabStrip. |tab_strip_point| is in the attached TabStrip's coordinate 389 // system. 390 gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& tab_strip_point); 391 392 // Get the position of the dragged tab view relative to the attached tab 393 // strip with the mirroring transform applied. 394 gfx::Point GetAttachedDragPoint(const gfx::Point& point_in_screen); 395 396 // Finds the Tabs within the specified TabStrip that corresponds to the 397 // WebContents of the dragged tabs. Returns an empty vector if not attached. 398 std::vector<Tab*> GetTabsMatchingDraggedContents(TabStrip* tabstrip); 399 400 // Returns the bounds for the tabs based on the attached tab strip. 401 std::vector<gfx::Rect> CalculateBoundsForDraggedTabs(); 402 403 // Does the work for EndDrag(). If we actually started a drag and |how_end| is 404 // not TAB_DESTROYED then one of EndDrag() or RevertDrag() is invoked. 405 void EndDragImpl(EndDragType how_end); 406 407 // Reverts a cancelled drag operation. 408 void RevertDrag(); 409 410 // Reverts the tab at |drag_index| in |drag_data_|. 411 void RevertDragAt(size_t drag_index); 412 413 // Selects the dragged tabs in |model|. Does nothing if there are no longer 414 // any dragged contents (as happens when a WebContents is deleted out from 415 // under us). 416 void ResetSelection(TabStripModel* model); 417 418 // Finishes a succesful drag operation. 419 void CompleteDrag(); 420 421 // Resets the delegates of the WebContents. 422 void ResetDelegates(); 423 424 // Create the DraggedTabView. 425 void CreateDraggedView(const std::vector<TabRendererData>& data, 426 const std::vector<gfx::Rect>& renderer_bounds); 427 428 // Returns the bounds (in screen coordinates) of the specified View. 429 gfx::Rect GetViewScreenBounds(views::View* tabstrip) const; 430 431 // Hides the frame for the window that contains the TabStrip the current 432 // drag session was initiated from. 433 void HideFrame(); 434 435 // Closes a hidden frame at the end of a drag session. 436 void CleanUpHiddenFrame(); 437 438 void DockDisplayerDestroyed(DockDisplayer* controller); 439 440 void BringWindowUnderPointToFront(const gfx::Point& point_in_screen); 441 442 // Convenience for getting the TabDragData corresponding to the tab the user 443 // started dragging. 444 TabDragData* source_tab_drag_data() { 445 return &(drag_data_[source_tab_index_]); 446 } 447 448 // Convenience for |source_tab_drag_data()->contents|. 449 content::WebContents* source_dragged_contents() { 450 return source_tab_drag_data()->contents; 451 } 452 453 // Returns the Widget of the currently attached TabStrip's BrowserView. 454 views::Widget* GetAttachedBrowserWidget(); 455 456 // Returns true if the tabs were originality one after the other in 457 // |source_tabstrip_|. 458 bool AreTabsConsecutive(); 459 460 // Creates and returns a new Browser to handle the drag. 461 Browser* CreateBrowserForDrag(TabStrip* source, 462 const gfx::Point& point_in_screen, 463 gfx::Vector2d* drag_offset, 464 std::vector<gfx::Rect>* drag_bounds); 465 466 // Returns the TabStripModel for the specified tabstrip. 467 TabStripModel* GetModel(TabStrip* tabstrip) const; 468 469 // Returns the location of the cursor. This is either the location of the 470 // mouse or the location of the current touch point. 471 gfx::Point GetCursorScreenPoint(); 472 473 // Returns the offset from the top left corner of the window to 474 // |point_in_screen|. 475 gfx::Vector2d GetWindowOffset(const gfx::Point& point_in_screen); 476 477 // Returns true if moving the mouse only changes the visible tabs. 478 bool move_only() const { 479 return (move_behavior_ == MOVE_VISIBILE_TABS) != 0; 480 } 481 482 // If true detaching creates a new browser and enters a nested message loop. 483 bool detach_into_browser_; 484 485 // Handles registering for notifications. 486 content::NotificationRegistrar registrar_; 487 488 EventSource event_source_; 489 490 // The TabStrip the drag originated from. 491 TabStrip* source_tabstrip_; 492 493 // The TabStrip the dragged Tab is currently attached to, or NULL if the 494 // dragged Tab is detached. 495 TabStrip* attached_tabstrip_; 496 497 // The screen that this drag is associated with. Cached, because other UI 498 // elements are NULLd at various points during the lifetime of this object. 499 gfx::Screen* screen_; 500 501 // The desktop type that this drag is associated with. Cached, because other 502 // UI elements are NULLd at various points during the lifetime of this 503 // object. 504 chrome::HostDesktopType host_desktop_type_; 505 506 // The visual representation of the dragged Tab. 507 scoped_ptr<DraggedTabView> view_; 508 509 // The position of the mouse (in screen coordinates) at the start of the drag 510 // operation. This is used to calculate minimum elasticity before a 511 // DraggedTabView is constructed. 512 gfx::Point start_point_in_screen_; 513 514 // This is the offset of the mouse from the top left of the first Tab where 515 // dragging began. This is used to ensure that the dragged view is always 516 // positioned at the correct location during the drag, and to ensure that the 517 // detached window is created at the right location. 518 gfx::Point mouse_offset_; 519 520 // Ratio of the x-coordinate of the |source_tab_offset| to the width of the 521 // tab. 522 float offset_to_width_ratio_; 523 524 // A hint to use when positioning new windows created by detaching Tabs. This 525 // is the distance of the mouse from the top left of the dragged tab as if it 526 // were the distance of the mouse from the top left of the first tab in the 527 // attached TabStrip from the top left of the window. 528 gfx::Point window_create_point_; 529 530 // Location of the first tab in the source tabstrip in screen coordinates. 531 // This is used to calculate |window_create_point_|. 532 gfx::Point first_source_tab_point_; 533 534 // The bounds of the browser window before the last Tab was detached. When 535 // the last Tab is detached, rather than destroying the frame (which would 536 // abort the drag session), the frame is moved off-screen. If the drag is 537 // aborted (e.g. by the user pressing Esc, or capture being lost), the Tab is 538 // attached to the hidden frame and the frame moved back to these bounds. 539 gfx::Rect restore_bounds_; 540 541 // ID of the last view that had focus in the window containing 542 // |source_tab_|. This is saved so that focus can be restored properly when a 543 // drag begins and ends within this same window. 544 const int old_focused_view_id_; 545 546 // The horizontal position of the mouse cursor in screen coordinates at the 547 // time of the last re-order event. 548 int last_move_screen_loc_; 549 550 DockInfo dock_info_; 551 552 DockWindows dock_windows_; 553 554 std::vector<DockDisplayer*> dock_controllers_; 555 556 // Timer used to bring the window under the cursor to front. If the user 557 // stops moving the mouse for a brief time over a browser window, it is 558 // brought to front. 559 base::OneShotTimer<TabDragController> bring_to_front_timer_; 560 561 // Timer used to move the stacked tabs. See comment aboue 562 // StartMoveStackedTimerIfNecessary(). 563 base::OneShotTimer<TabDragController> move_stacked_timer_; 564 565 // Did the mouse move enough that we started a drag? 566 bool started_drag_; 567 568 // Is the drag active? 569 bool active_; 570 571 DragData drag_data_; 572 573 // Index of the source tab in |drag_data_|. 574 size_t source_tab_index_; 575 576 // True until MoveAttached() is first invoked. 577 bool initial_move_; 578 579 // The selection model before the drag started. See comment above Init() for 580 // details. 581 ui::ListSelectionModel initial_selection_model_; 582 583 // The selection model of |attached_tabstrip_| before the tabs were attached. 584 ui::ListSelectionModel selection_model_before_attach_; 585 586 // Initial x-coordinates of the tabs when the drag started. Only used for 587 // touch mode. 588 std::vector<int> initial_tab_positions_; 589 590 DetachBehavior detach_behavior_; 591 MoveBehavior move_behavior_; 592 593 // Updated as the mouse is moved when attached. Indicates whether the mouse 594 // has ever moved to the left or right. If the tabs are ever detached this 595 // is set to kMovedMouseRight | kMovedMouseLeft. 596 int mouse_move_direction_; 597 598 // Last location used in screen coordinates. 599 gfx::Point last_point_in_screen_; 600 601 // The following are needed when detaching into a browser 602 // (|detach_into_browser_| is true). 603 604 // See description above getter. 605 bool is_dragging_window_; 606 607 // True if |attached_tabstrip_| is in a browser specifically created for 608 // the drag. 609 bool is_dragging_new_browser_; 610 611 // True if |source_tabstrip_| was maximized before the drag. 612 bool was_source_maximized_; 613 614 // True if |source_tabstrip_| was in immersive fullscreen before the drag. 615 bool was_source_fullscreen_; 616 617 EndRunLoopBehavior end_run_loop_behavior_; 618 619 // If true, we're waiting for a move loop to complete. 620 bool waiting_for_run_loop_to_exit_; 621 622 // The TabStrip to attach to after the move loop completes. 623 TabStrip* tab_strip_to_attach_to_after_exit_; 624 625 // Non-null for the duration of RunMoveLoop. 626 views::Widget* move_loop_widget_; 627 628 // See description above getter. 629 bool is_mutating_; 630 631 // |attach_x_| and |attach_index_| are set to the x-coordinate of the mouse 632 // (in terms of the tabstrip) and the insertion index at the time tabs are 633 // dragged into a new browser (attached). They are used to ensure we don't 634 // shift the tabs around in the wrong direction. The two are only valid if 635 // |attach_index_| is not -1. 636 // See comment around use for more details. 637 int attach_x_; 638 int attach_index_; 639 640 base::WeakPtrFactory<TabDragController> weak_factory_; 641 642 DISALLOW_COPY_AND_ASSIGN(TabDragController); 643}; 644 645#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_ 646