15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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 "chrome/browser/ui/views/tabs/tab_drag_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/ui/browser_list.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab_strip.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/window_finder.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h" 32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/aura/env.h" 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/aura/window.h" 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_constants.h" 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/events/gestures/gesture_recognizer.h" 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/geometry/point_conversions.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/views/focus/view_storage.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/root_view.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/wm/core/coordinate_conversion.h" 42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/wm/core/window_modality_controller.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(USE_ASH) 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ash/accelerators/accelerator_commands.h" 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ash/shell.h" 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ash/wm/maximize_mode/maximize_mode_controller.h" 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ash/wm/window_state.h" 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If non-null there is a drag underway. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static TabDragController* instance_ = NULL; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay, in ms, during dragging before we bring a window to front. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBringToFrontDelay = 750; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initial delay before moving tabs when the dragged tab is close to the edge of 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the stacked tabs. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMoveAttachedInitialDelay = 600; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay for moving tabs after the initial delay has passed. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMoveAttachedSubsequentDelay = 300; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kHorizontalMoveThreshold = 16; // Pixels. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Distance from the next/previous stacked before before we consider the tab 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// close enough to trigger moving. 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kStackedDistance = 36; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(USE_ASH) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetWindowPositionManaged(gfx::NativeWindow window, bool value) { 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ash::wm::GetWindowState(window)->set_window_position_managed(value); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Returns true if |tab_strip| browser window is docked. 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool IsDockedOrSnapped(const TabStrip* tab_strip) { 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(tab_strip); 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::wm::WindowState* window_state = 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::wm::GetWindowState(tab_strip->GetWidget()->GetNativeWindow()); 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return window_state->IsDocked() || window_state->IsSnapped(); 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#else 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SetWindowPositionManaged(gfx::NativeWindow window, bool value) { 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool IsDockedOrSnapped(const TabStrip* tab_strip) { 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |bounds| contains the y-coordinate |y|. The y-coordinate 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of |bounds| is adjusted by |vertical_adjustment|. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoesRectContainVerticalPointExpanded( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& bounds, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int vertical_adjustment, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int upper_threshold = bounds.bottom() + vertical_adjustment; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lower_threshold = bounds.y() - vertical_adjustment; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return y >= lower_threshold && y <= upper_threshold; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Adds |x_offset| to all the rectangles in |rects|. 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OffsetX(int x_offset, std::vector<gfx::Rect>* rects) { 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (x_offset == 0) 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t i = 0; i < rects->size(); ++i) 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (*rects)[i].set_x((*rects)[i].x() + x_offset); 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WidgetObserver implementation that resets the window position managed 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// property on Show. 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// We're forced to do this here since BrowserFrameAsh resets the 'window 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// position managed' property during a show and we need the property set to 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// false before WorkspaceLayoutManager sees the visibility change. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WindowPositionManagedUpdater : public views::WidgetObserver { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnWidgetVisibilityChanged(views::Widget* widget, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool visible) OVERRIDE { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPositionManaged(widget->GetNativeView(), false); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// EscapeTracker installs itself as a pre-target handler on aura::Env and runs a 131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// callback when it receives the escape key. 132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass EscapeTracker : public ui::EventHandler { 133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch explicit EscapeTracker(const base::Closure& callback) 135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : escape_callback_(callback) { 136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch aura::Env::GetInstance()->AddPreTargetHandler(this); 137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual ~EscapeTracker() { 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch aura::Env::GetInstance()->RemovePreTargetHandler(this); 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private: 144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // ui::EventHandler: 145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual void OnKeyEvent(ui::KeyEvent* key) OVERRIDE { 146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (key->type() == ui::ET_KEY_PRESSED && 147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch key->key_code() == ui::VKEY_ESCAPE) { 148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch escape_callback_.Run(); 149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Closure escape_callback_; 153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DISALLOW_COPY_AND_ASSIGN(EscapeTracker); 155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::TabDragData::TabDragData() 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : contents(NULL), 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_model_index(-1), 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tab(NULL), 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pinned(false) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::TabDragData::~TabDragData() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabDragController, public: 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int TabDragController::kTouchVerticalDetachMagnetism = 50; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int TabDragController::kVerticalDetachMagnetism = 15; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::TabDragController() 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : event_source_(EVENT_SOURCE_MOUSE), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_(NULL), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_(NULL), 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen_(NULL), 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci can_release_capture_(true), 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset_to_width_ratio_(0), 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) old_focused_view_id_( 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) views::ViewStorage::GetInstance()->CreateStorageID()), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_move_screen_loc_(0), 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_drag_(false), 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_(true), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tab_index_(std::numeric_limits<size_t>::max()), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_move_(true), 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) detach_behavior_(DETACHABLE), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_behavior_(REORDER), 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_move_direction_(0), 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_dragging_window_(false), 19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) is_dragging_new_browser_(false), 19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) was_source_maximized_(false), 19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) was_source_fullscreen_(false), 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) did_restore_window_(false), 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_run_loop_behavior_(END_RUN_LOOP_STOP_DRAGGING), 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_run_loop_to_exit_(false), 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip_to_attach_to_after_exit_(NULL), 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_(NULL), 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) is_mutating_(false), 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_x_(-1), 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_index_(-1), 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) weak_factory_(this) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_ = this; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::~TabDragController() { 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) views::ViewStorage::GetInstance()->RemoveView(old_focused_view_id_); 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (instance_ == this) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_ = NULL; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (move_loop_widget_) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_->RemoveObserver(this); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPositionManaged(move_loop_widget_->GetNativeView(), true); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (source_tabstrip_) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(source_tabstrip_)->RemoveObserver(this); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (event_source_ == EVENT_SOURCE_TOUCH) { 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TabStrip* capture_tabstrip = attached_tabstrip_ ? 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) attached_tabstrip_ : source_tabstrip_; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capture_tabstrip->GetWidget()->ReleaseCapture(); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::Init( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* source_tabstrip, 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* source_tab, 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<Tab*>& tabs, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& mouse_offset, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_tab_offset, 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::ListSelectionModel& initial_selection_model, 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveBehavior move_behavior, 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EventSource event_source) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!tabs.empty()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_ = source_tabstrip; 24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized(); 24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screen_ = gfx::Screen::GetScreenFor( 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip->GetWidget()->GetNativeView()); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView( 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip->GetWidget()->GetNativeView()); 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Do not release capture when transferring capture between widgets on: 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - Desktop Linux 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Mouse capture is not synchronous on desktop Linux. Chrome makes 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // transferring capture between widgets without releasing capture appear 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // synchronous on desktop Linux, so use that. 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - Ash 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Releasing capture on Ash cancels gestures so avoid it. 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_LINUX) 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci can_release_capture_ = false; 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#else 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci can_release_capture_ = 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (host_desktop_type_ != chrome::HOST_DESKTOP_TYPE_ASH); 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_point_in_screen_ = gfx::Point(source_tab_offset, mouse_offset.y()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToScreen(source_tab, &start_point_in_screen_); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_source_ = event_source; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_offset_ = mouse_offset; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_behavior_ = move_behavior; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_point_in_screen_ = start_point_in_screen_; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_move_screen_loc_ = start_point_in_screen_.x(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetModel(source_tabstrip_)->AddObserver(this); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_.resize(tabs.size()); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < tabs.size(); ++i) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitTabDragData(tabs[i], &(drag_data_[i])); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tab_index_ = 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(tabs.begin(), tabs.end(), source_tab) - tabs.begin(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listen for Esc key presses. 282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch escape_tracker_.reset( 283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch new EscapeTracker(base::Bind(&TabDragController::EndDrag, 284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_factory_.GetWeakPtr(), 285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch END_DRAG_CANCEL))); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_tab->width() > 0) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offset_to_width_ratio_ = static_cast<float>( 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_tab->GetMirroredXInView(source_tab_offset)) / 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<float>(source_tab->width()); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitWindowCreatePoint(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_selection_model_.Copy(initial_selection_model); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Gestures don't automatically do a capture. We don't allow multiple drags at 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the same time, so we explicitly capture. 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (event_source == EVENT_SOURCE_TOUCH) 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_tabstrip_->GetWidget()->SetCapture(source_tabstrip_); 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(USE_ASH) 30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ash::Shell::HasInstance() && 30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ash::Shell::GetInstance()->maximize_mode_controller()-> 30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) IsMaximizeModeWindowManagerEnabled()) { 30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) detach_behavior_ = NOT_DETACHABLE; 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool TabDragController::IsAttachedTo(const TabStrip* tab_strip) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (instance_ && instance_->active() && 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->attached_tabstrip() == tab_strip); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::IsActive() { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return instance_ && instance_->active(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::SetMoveBehavior(MoveBehavior behavior) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_drag()) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_behavior_ = behavior; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::Drag(const gfx::Point& point_in_screen) { 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::Drag", 329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "point_in_screen", point_in_screen.ToString()); 330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bring_to_front_timer_.Stop(); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_stacked_timer_.Stop(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (waiting_for_run_loop_to_exit_) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_drag_) { 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanStartDrag(point_in_screen)) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // User hasn't dragged far enough yet. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // On windows SaveFocus() may trigger a capture lost, which destroys us. 34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) { 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SaveFocus(); 345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!ref) 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_drag_ = true; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Attach(source_tabstrip_, gfx::Point()); 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (static_cast<int>(drag_data_.size()) == 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(source_tabstrip_)->count()) { 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (was_source_maximized_ || was_source_fullscreen_) { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) did_restore_window_ = true; 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // When all tabs in a maximized browser are dragged the browser gets 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // restored during the drag and maximized back when the drag ends. 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::Widget* widget = GetAttachedBrowserWidget(); 357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const int last_tabstrip_width = attached_tabstrip_->tab_area_width(); 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Rect new_bounds(CalculateDraggedBrowserBounds(source_tabstrip_, 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) point_in_screen, 362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &drag_bounds)); 363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new_bounds.Offset(-widget->GetRestoredBounds().x() + 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) point_in_screen.x() - 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mouse_offset_.x(), 0); 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) widget->SetVisibilityChangedAnimationsEnabled(false); 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) widget->Restore(); 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) widget->SetBounds(new_bounds); 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AdjustBrowserAndTabBoundsForDrag(last_tabstrip_width, 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) point_in_screen, 371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &drag_bounds); 372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) widget->SetVisibilityChangedAnimationsEnabled(true); 373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMoveLoop(GetWindowOffset(point_in_screen)); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ContinueDragging(point_in_screen); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::EndDrag(EndDragReason reason) { 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("views", "TabDragController::EndDrag"); 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're dragging a window ignore capture lost since it'll ultimately 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trigger the move loop to end and we'll revert the drag when RunMoveLoop() 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // finishes. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reason == END_DRAG_CAPTURE_LOST && is_dragging_window_) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndDragImpl(reason != END_DRAG_COMPLETE && source_tabstrip_ ? 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CANCELED : NORMAL); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabDragController::InitTabDragData(Tab* tab, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabDragData* drag_data) { 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("views", "TabDragController::InitTabDragData"); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data->source_model_index = 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_tabstrip_->GetModelIndexOfTab(tab); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) drag_data->contents = GetModel(source_tabstrip_)->GetWebContentsAt( 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data->source_model_index); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data->pinned = source_tabstrip_->IsTabPinned(tab); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<WebContents>(drag_data->contents)); 406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabDragController, content::NotificationObserver implementation: 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::Observe( 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* destroyed_web_contents = 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<WebContents>(source).ptr(); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (drag_data_[i].contents == destroyed_web_contents) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // One of the tabs we're dragging has been destroyed. Cancel the drag. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_[i].contents = NULL; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndDragImpl(TAB_DESTROYED); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get here it means we got notification for a tab we don't know about. 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabDragController::OnWidgetBoundsChanged(views::Widget* widget, 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& new_bounds) { 432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::OnWidgetBoundsChanged", 433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "new_bounds", new_bounds.ToString()); 434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Drag(GetCursorScreenPoint()); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::TabStripEmpty() { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(source_tabstrip_)->RemoveObserver(this); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NULL out source_tabstrip_ so that we don't attempt to add back to it (in 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the case of a revert). 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_ = NULL; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabDragController, private: 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::InitWindowCreatePoint() { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window_create_point_ is only used in CompleteDrag() (through 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetWindowCreatePoint() to get the start point of the docked window) when 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the attached_tabstrip_ is NULL and all the window's related bound 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // information are obtained from source_tabstrip_. So, we need to get the 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the window_create_point_ is not in the correct coordinate system. Please 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // refer to http://crbug.com/6223 comment #15 for detailed information. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* first_tab = source_tabstrip_->tab_at(0); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToWidget(first_tab, &first_source_tab_point_); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_create_point_ = first_source_tab_point_; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_create_point_.Offset(mouse_offset_.x(), mouse_offset_.y()); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point TabDragController::GetWindowCreatePoint( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& origin) const { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the cursor is outside the monitor area, move it inside. For example, 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dropping a tab onto the task bar on Windows produces this situation. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect work_area = screen_->GetDisplayNearestPoint(origin).work_area(); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point create_point(origin); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!work_area.IsEmpty()) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_point.x() < work_area.x()) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_point.set_x(work_area.x()); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (create_point.x() > work_area.right()) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_point.set_x(work_area.right()); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_point.y() < work_area.y()) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_point.set_y(work_area.y()); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (create_point.y() > work_area.bottom()) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_point.set_y(work_area.bottom()); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Point(create_point.x() - window_create_point_.x(), 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_point.y() - window_create_point_.y()); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::SaveFocus() { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(source_tabstrip_); 48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) views::View* focused_view = 48558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) source_tabstrip_->GetFocusManager()->GetFocusedView(); 48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (focused_view) 48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) views::ViewStorage::GetInstance()->StoreView(old_focused_view_id_, 48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) focused_view); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_->GetFocusManager()->SetFocusedView(source_tabstrip_); 49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // WARNING: we may have been deleted. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::RestoreFocus() { 494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (attached_tabstrip_ != source_tabstrip_) { 495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_dragging_new_browser_) { 496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::WebContents* active_contents = source_dragged_contents(); 497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (active_contents && !active_contents->FocusLocationBarByDefault()) 498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) active_contents->Focus(); 499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 50058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) views::View* old_focused_view = 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) views::ViewStorage::GetInstance()->RetrieveView(old_focused_view_id_); 50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!old_focused_view) 50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) old_focused_view->GetFocusManager()->SetFocusedView(old_focused_view); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::CanStartDrag(const gfx::Point& point_in_screen) const { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine if the mouse has moved beyond a minimum elasticity distance in 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any direction from the starting point. 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kMinimumDragDistance = 10; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x()); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y()); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sqrt(pow(static_cast<float>(x_offset), 2) + 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::ContinueDragging(const gfx::Point& point_in_screen) { 520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::ContinueDragging", 521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "point_in_screen", point_in_screen.ToString()); 522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(attached_tabstrip_); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) TabStrip* target_tabstrip = detach_behavior_ == DETACHABLE ? 52603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) GetTargetTabStripForPoint(point_in_screen) : source_tabstrip_; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool tab_strip_changed = (target_tabstrip != attached_tabstrip_); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int move_delta = point_in_screen.x() - last_point_in_screen_.x(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (move_delta > 0) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_move_direction_ |= kMovedMouseRight; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (move_delta < 0) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_move_direction_ |= kMovedMouseLeft; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_point_in_screen_ = point_in_screen; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip_changed) { 53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) is_dragging_new_browser_ = false; 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) did_restore_window_ = false; 541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (DragBrowserToNewTabStrip(target_tabstrip, point_in_screen) == 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DRAG_BROWSER_RESULT_STOP) { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_dragging_window_) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<base::Timer*>(&bring_to_front_timer_)->Start(FROM_HERE, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kBringToFrontDelay), 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TabDragController::BringWindowUnderPointToFront, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), point_in_screen)); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!is_dragging_window_ && attached_tabstrip_) { 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (move_only()) { 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DragActiveTabStacked(point_in_screen); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MoveAttached(point_in_screen); 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (tab_strip_changed) { 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Move the corresponding window to the front. We do this after the 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // move as on windows activate triggers a synchronous paint. 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) attached_tabstrip_->GetWidget()->Activate(); 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::DragBrowserResultType 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::DragBrowserToNewTabStrip( 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* target_tabstrip, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::DragBrowserToNewTabStrip", 572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "point_in_screen", point_in_screen.ToString()); 573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!target_tabstrip) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DetachIntoNewBrowserAndRunMoveLoop(point_in_screen); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DRAG_BROWSER_RESULT_STOP; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_dragging_window_) { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ReleaseCapture() is going to result in calling back to us (because it 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // results in a move). That'll cause all sorts of problems. Reset the 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // observer so we don't get notified and process the event. 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) { 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move_loop_widget_->RemoveObserver(this); 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move_loop_widget_ = NULL; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget* browser_widget = GetAttachedBrowserWidget(); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to release the drag controller before starting the move loop as it's 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // going to trigger capture lost, which cancels drag. 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->ReleaseDragController(); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_tabstrip->OwnDragController(this); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable animations so that we don't see a close animation on aero. 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_widget->SetVisibilityChangedAnimationsEnabled(false); 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (can_release_capture_) 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_widget->ReleaseCapture(); 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 5988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // The Gesture recognizer does not work well currently when capture changes 5998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // while a touch gesture is in progress. So we need to manually transfer 6008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // gesture sequence and the GR's touch events queue to the new window. This 6018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // should really be done somewhere in capture change code and or inside the 6028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // GR. But we currently do not have a consistent way for doing it that would 6038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // work in all cases. Hence this hack. 6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ui::GestureRecognizer::Get()->TransferEventsTo( 6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) browser_widget->GetNativeView(), 6068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) target_tabstrip->GetWidget()->GetNativeView()); 6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 6088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window is going away. Since the drag is still on going we don't want 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that to effect the position of any windows. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPositionManaged(browser_widget->GetNativeView(), false); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_LINUX) || defined(OS_CHROMEOS) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EndMoveLoop is going to snap the window back to its original location. 615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Hide it so users don't see this. Hiding a window in Linux aura causes 616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // it to lose capture so skip it. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_widget->Hide(); 618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_widget->EndMoveLoop(); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Ideally we would always swap the tabs now, but on non-ash Windows, it 6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // seems that running the move loop implicitly activates the window when 6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // done, leading to all sorts of flicker. So, on non-ash Windows, instead 6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we process the move after the loop completes. But on chromeos, we can 6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // do tab swapping now to avoid the tab flashing issue 6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (crbug.com/116329). 6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (can_release_capture_) { 6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_strip_to_attach_to_after_exit_ = target_tabstrip; 6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_dragging_window_ = false; 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Detach(DONT_RELEASE_CAPTURE); 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Attach(target_tabstrip, point_in_screen); 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Move the tabs into position. 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveAttached(point_in_screen); 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attached_tabstrip_->GetWidget()->Activate(); 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_run_loop_to_exit_ = true; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_run_loop_behavior_ = END_RUN_LOOP_CONTINUE_DRAGGING; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DRAG_BROWSER_RESULT_STOP; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Detach(DONT_RELEASE_CAPTURE); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Attach(target_tabstrip, point_in_screen); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DRAG_BROWSER_RESULT_CONTINUE; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::DragActiveTabStacked( 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_->tab_count() != 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(initial_tab_positions_.size())) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // TODO: should cancel drag if this happens. 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta = point_in_screen.x() - start_point_in_screen_.x(); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->DragActiveTab(initial_tab_positions_, delta); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::MoveAttachedToNextStackedIndex( 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = attached_tabstrip_->touch_layout_->active_index(); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index + 1 >= attached_tabstrip_->tab_count()) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(attached_tabstrip_)->MoveSelectedTabsTo(index + 1); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartMoveStackedTimerIfNecessary(point_in_screen, 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMoveAttachedSubsequentDelay); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::MoveAttachedToPreviousStackedIndex( 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = attached_tabstrip_->touch_layout_->active_index(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index <= attached_tabstrip_->GetMiniTabCount()) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(attached_tabstrip_)->MoveSelectedTabsTo(index - 1); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartMoveStackedTimerIfNecessary(point_in_screen, 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMoveAttachedSubsequentDelay); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::MoveAttached(const gfx::Point& point_in_screen) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(attached_tabstrip_); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!is_dragging_window_); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point dragged_view_point = GetAttachedDragPoint(point_in_screen); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the horizontal move threshold. This is dependent on the width 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of tabs. The smaller the tabs compared to the standard size, the smaller 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the threshold. 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int threshold = kHorizontalMoveThreshold; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!attached_tabstrip_->touch_layout_.get()) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double unselected, selected; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double ratio = unselected / Tab::GetStandardSize().width(); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else case: touch tabs never shrink. 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> tabs(drag_data_.size()); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs[i] = drag_data_[i].attached_tab; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool did_layout = false; 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the model, moving the WebContents from one index to another. Do this 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only if we have moved a minimum distance since the last reorder (to prevent 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // jitter) or if this the first move and the tabs are not consecutive. 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((abs(point_in_screen.x() - last_move_screen_loc_) > threshold || 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (initial_move_ && !AreTabsConsecutive()))) { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* attached_model = GetModel(attached_tabstrip_); 708f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int to_index = GetInsertionIndexForDraggedBounds( 709f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetDraggedViewTabStripBounds(dragged_view_point)); 7104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool do_move = true; 7114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // While dragging within a tabstrip the expectation is the insertion index 7124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // is based on the left edge of the tabs being dragged. OTOH when dragging 7134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // into a new tabstrip (attaching) the expectation is the insertion index is 7144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // based on the cursor. This proves problematic as insertion may change the 7154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // size of the tabs, resulting in the index calculated before the insert 7164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // differing from the index calculated after the insert. To alleviate this 7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the index is chosen before insertion, and subsequently a new index is 7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // only used once the mouse moves enough such that the index changes based 7194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // on the direction the mouse moved relative to |attach_x_| (smaller 7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // x-coordinate should yield a smaller index or larger x-coordinate yields a 7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // larger index). 7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (attach_index_ != -1) { 7234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Point tab_strip_point(point_in_screen); 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::View::ConvertPointFromScreen(attached_tabstrip_, &tab_strip_point); 7254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int new_x = 7264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_tabstrip_->GetMirroredXInView(tab_strip_point.x()); 7274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (new_x < attach_x_) 7284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) to_index = std::min(to_index, attach_index_); 7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) to_index = std::max(to_index, attach_index_); 7314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (to_index != attach_index_) 7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_index_ = -1; // Once a valid move is detected, don't constrain. 7334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 7344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) do_move = false; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (do_move) { 7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebContents* last_contents = drag_data_[drag_data_.size() - 1].contents; 7384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int index_of_last_item = 7394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_model->GetIndexOfWebContents(last_contents); 7404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (initial_move_) { 7414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TabStrip determines if the tabs needs to be animated based on model 7424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // position. This means we need to invoke LayoutDraggedTabsAt before 7434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // changing the model. 7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_tabstrip_->LayoutDraggedTabsAt( 7454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 7464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initial_move_); 7474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) did_layout = true; 7484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_model->MoveSelectedTabsTo(to_index); 7504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Move may do nothing in certain situations (such as when dragging pinned 7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // tabs). Make sure the tabstrip actually changed before updating 7534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // last_move_screen_loc_. 7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (index_of_last_item != 7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_model->GetIndexOfWebContents(last_contents)) { 7564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) last_move_screen_loc_ = point_in_screen.x(); 7574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!did_layout) { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->LayoutDraggedTabsAt( 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_move_); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartMoveStackedTimerIfNecessary(point_in_screen, kMoveAttachedInitialDelay); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_move_ = false; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::StartMoveStackedTimerIfNecessary( 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen, 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delay_ms) { 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(attached_tabstrip_); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StackedTabStripLayout* touch_layout = attached_tabstrip_->touch_layout_.get(); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!touch_layout) 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point dragged_view_point = GetAttachedDragPoint(point_in_screen); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point); 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = touch_layout->active_index(); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldDragToNextStackedTab(bounds, index)) { 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<base::Timer*>(&move_stacked_timer_)->Start( 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(delay_ms), 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TabDragController::MoveAttachedToNextStackedIndex, 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), point_in_screen)); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ShouldDragToPreviousStackedTab(bounds, index)) { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<base::Timer*>(&move_stacked_timer_)->Start( 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(delay_ms), 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TabDragController::MoveAttachedToPreviousStackedIndex, 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), point_in_screen)); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabDragController::DetachPosition TabDragController::GetDetachPosition( 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(attached_tabstrip_); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point attached_point(point_in_screen); 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::View::ConvertPointFromScreen(attached_tabstrip_, &attached_point); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_point.x() < 0) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DETACH_BEFORE; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_point.x() >= attached_tabstrip_->width()) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DETACH_AFTER; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DETACH_ABOVE_OR_BELOW; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStrip* TabDragController::GetTargetTabStripForPoint( 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 813f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::GetTargetTabStripForPoint", 814f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "point_in_screen", point_in_screen.ToString()); 815f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (move_only() && attached_tabstrip_) { 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // move_only() is intended for touch, in which case we only want to detach 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the touch point moves significantly in the vertical distance. 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect tabstrip_bounds = GetViewScreenBounds(attached_tabstrip_); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DoesRectContainVerticalPointExpanded(tabstrip_bounds, 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kTouchVerticalDetachMagnetism, 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) point_in_screen.y())) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return attached_tabstrip_; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow local_window = 826a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetLocalProcessWindow(point_in_screen, is_dragging_window_); 827a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Do not allow dragging into a window with a modal dialog, it causes a weird 828a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // behavior. See crbug.com/336691 829a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!wm::GetModalTransient(local_window)) { 830a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch TabStrip* tab_strip = GetTabStripForWindow(local_window); 831a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (tab_strip && DoesTabStripContain(tab_strip, point_in_screen)) 832a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return tab_strip; 833a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 834a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_dragging_window_ ? attached_tabstrip_ : NULL; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStrip* TabDragController::GetTabStripForWindow(gfx::NativeWindow window) { 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* browser_view = 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView::GetBrowserViewForNativeWindow(window); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't allow drops on windows that don't have tabstrips. 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser_view || 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !browser_view->browser()->SupportsWindowFeature( 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser::FEATURE_TABSTRIP)) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* other_tabstrip = browser_view->tabstrip(); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* tab_strip = 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_ ? attached_tabstrip_ : source_tabstrip_; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tab_strip); 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return other_tabstrip->controller()->IsCompatibleWith(tab_strip) ? 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_tabstrip : NULL; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::DoesTabStripContain( 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* tabstrip, 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) const { 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the specified screen point is actually within the bounds of the 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified tabstrip... 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return point_in_screen.x() < tabstrip_bounds.right() && 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) point_in_screen.x() >= tabstrip_bounds.x() && 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoesRectContainVerticalPointExpanded(tabstrip_bounds, 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kVerticalDetachMagnetism, 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) point_in_screen.y()); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::Attach(TabStrip* attached_tabstrip, 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::Attach", 874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "point_in_screen", point_in_screen.ToString()); 875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!attached_tabstrip_); // We should already have detached by the time 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we get here. 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_ = attached_tabstrip; 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> tabs = 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTabsMatchingDraggedContents(attached_tabstrip_); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tabs.empty()) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transitioning from detached to attached to a new tabstrip. Add tabs to 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the new model. 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_before_attach_.Copy(attached_tabstrip->GetSelectionModel()); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inserting counts as a move. We don't want the tabs to jitter when the 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user moves the tab immediately after attaching it. 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_move_screen_loc_ = point_in_screen.x(); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out where to insert the tab based on the bounds of the dragged 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // representation and the ideal bounds of the other Tabs already in the 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // strip. ("ideal bounds" are stable even if the Tabs' actual bounds are 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changing due to animation). 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point tab_strip_point(point_in_screen); 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::View::ConvertPointFromScreen(attached_tabstrip_, &tab_strip_point); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip_point.set_x( 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetMirroredXInView(tab_strip_point.x())); 9024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tab_strip_point.Offset(0, -mouse_offset_.y()); 903f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int index = GetInsertionIndexForDraggedBounds( 904f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetDraggedViewTabStripBounds(tab_strip_point)); 9054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_index_ = index; 9064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_x_ = tab_strip_point.x(); 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> setter(&is_mutating_, true); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int add_types = TabStripModel::ADD_NONE; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_->touch_layout_.get()) { 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // StackedTabStripLayout positions relative to the active tab, if we 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // don't add the tab as active things bounce around. 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1u, drag_data_.size()); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) add_types |= TabStripModel::ADD_ACTIVE; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_data_[i].pinned) 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) add_types |= TabStripModel::ADD_PINNED; 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(attached_tabstrip_)->InsertWebContentsAt( 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index + i, drag_data_[i].contents, add_types); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs = GetTabsMatchingDraggedContents(attached_tabstrip_); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(tabs.size(), drag_data_.size()); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_[i].attached_tab = tabs[i]; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->StartedDraggingTabs(tabs); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetSelection(GetModel(attached_tabstrip_)); 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The size of the dragged tab may have changed. Adjust the x offset so that 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ratio of mouse_offset_ to original width is maintained. 9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> tabs_to_source(tabs); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs_to_source.erase(tabs_to_source.begin() + source_tab_index_ + 1, 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs_to_source.end()); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_x = attached_tabstrip_->GetSizeNeededForTabs(tabs_to_source) - 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs[source_tab_index_]->width() + 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(offset_to_width_ratio_ * 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs[source_tab_index_]->width()); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_offset_.set_x(new_x); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transfer ownership of us to the new tabstrip as well as making sure the 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window has capture. This is important so that if activation changes the 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drag isn't prematurely canceled. 946116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch attached_tabstrip_->GetWidget()->SetCapture(attached_tabstrip_); 947116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch attached_tabstrip_->OwnDragController(this); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::Detach(ReleaseCapture release_capture) { 951f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT1("views", "TabDragController::Detach", 952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "release_capture", release_capture); 953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 9544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attach_index_ = -1; 9554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the user detaches we assume they want to reorder. 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_behavior_ = REORDER; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release ownership of the drag controller and mouse capture. When we 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reattach ownership is transfered. 961116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch attached_tabstrip_->ReleaseDragController(); 962116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (release_capture == RELEASE_CAPTURE) 963116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch attached_tabstrip_->GetWidget()->ReleaseCapture(); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_move_direction_ = kMovedMouseLeft | kMovedMouseRight; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* attached_model = GetModel(attached_tabstrip_); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TabRendererData> tab_data; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_data.push_back(drag_data_[i].attached_tab->data()); 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = attached_model->GetIndexOfWebContents(drag_data_[i].contents); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, index); 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hide the tab so that the user doesn't see it animate closed. 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_[i].attached_tab->SetVisible(false); 977116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch drag_data_[i].attached_tab->set_detached(); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attached_model->DetachWebContentsAt(index); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Detaching may end up deleting the tab, drop references to it. 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_[i].attached_tab = NULL; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we've removed the last Tab from the TabStrip, hide the frame now. 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!attached_model->empty()) { 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!selection_model_before_attach_.empty() && 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_before_attach_.active() >= 0 && 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_before_attach_.active() < attached_model->count()) { 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore the selection. 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_model->SetSelectionFromModel(selection_model_before_attach_); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (attached_tabstrip_ == source_tabstrip_ && 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !initial_selection_model_.empty()) { 9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RestoreInitialSelection(); 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->DraggedTabsDetached(); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_ = NULL; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::DetachIntoNewBrowserAndRunMoveLoop( 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetModel(attached_tabstrip_)->count() == 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(drag_data_.size())) { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All the tabs in a browser are being dragged but all the tabs weren't 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initially being dragged. For this to happen the user would have to 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start dragging a set of tabs, the other tabs close, then detach. 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMoveLoop(GetWindowOffset(point_in_screen)); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int last_tabstrip_width = attached_tabstrip_->tab_area_width(); 10144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); 10154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); 10167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Vector2d drag_offset; 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser = CreateBrowserForDrag( 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); 10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 10211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) gfx::NativeView attached_native_view = 10221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) attached_tabstrip_->GetWidget()->GetNativeView(); 10231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 10241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Detach(can_release_capture_ ? RELEASE_CAPTURE : DONT_RELEASE_CAPTURE); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView* dragged_browser_view = 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserView::GetBrowserViewForBrowser(browser); 1027d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) views::Widget* dragged_widget = dragged_browser_view->GetWidget(); 10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) 10291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The Gesture recognizer does not work well currently when capture changes 10301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // while a touch gesture is in progress. So we need to manually transfer 10311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // gesture sequence and the GR's touch events queue to the new window. This 10321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // should really be done somewhere in capture change code and or inside the 10331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // GR. But we currently do not have a consistent way for doing it that would 10341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // work in all cases. Hence this hack. 10351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ui::GestureRecognizer::Get()->TransferEventsTo( 10361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) attached_native_view, 10371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dragged_widget->GetNativeView()); 10381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 1039d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dragged_widget->SetVisibilityChangedAnimationsEnabled(false); 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Attach(dragged_browser_view->tabstrip(), gfx::Point()); 1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AdjustBrowserAndTabBoundsForDrag(last_tabstrip_width, 1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) point_in_screen, 1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &drag_bounds); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowPositionManagedUpdater updater; 1045d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dragged_widget->AddObserver(&updater); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->window()->Show(); 1047d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dragged_widget->RemoveObserver(&updater); 1048d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dragged_widget->SetVisibilityChangedAnimationsEnabled(true); 1049d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Activate may trigger a focus loss, destroying us. 1050d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) { 1051d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); 1052d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) browser->window()->Activate(); 1053d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!ref) 1054d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 1055d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunMoveLoop(drag_offset); 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user drags the whole window we'll assume they are going to attach to 106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // another window and therefore want to reorder. 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_behavior_ = REORDER; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_ = GetAttachedBrowserWidget(); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(move_loop_widget_); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_->AddObserver(this); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_dragging_window_ = true; 1068d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); 10691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (can_release_capture_) { 10701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Running the move loop releases mouse capture, which triggers destroying 10711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the drag loop. Release mouse capture now while the DragController is not 10721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // owned by the TabStrip. 10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attached_tabstrip_->ReleaseDragController(); 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attached_tabstrip_->GetWidget()->ReleaseCapture(); 10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attached_tabstrip_->OwnDragController(this); 10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const views::Widget::MoveLoopSource move_loop_source = 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_source_ == EVENT_SOURCE_MOUSE ? 10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget::MOVE_LOOP_SOURCE_MOUSE : 10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget::MOVE_LOOP_SOURCE_TOUCH; 108168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const views::Widget::MoveLoopEscapeBehavior escape_behavior = 108268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) is_dragging_new_browser_ ? 108368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE : 108468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget::MoveLoopResult result = 108668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) move_loop_widget_->RunMoveLoop( 108768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) drag_offset, move_loop_source, escape_behavior); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllBrowserContextsAndSources(), 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::NoDetails()); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1093d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!ref) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (move_loop_widget_) { 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_->RemoveObserver(this); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_loop_widget_ = NULL; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_dragging_window_ = false; 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_run_loop_to_exit_ = false; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end_run_loop_behavior_ == END_RUN_LOOP_CONTINUE_DRAGGING) { 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_run_loop_behavior_ = END_RUN_LOOP_STOP_DRAGGING; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip_to_attach_to_after_exit_) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point point_in_screen(GetCursorScreenPoint()); 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Detach(DONT_RELEASE_CAPTURE); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Attach(tab_strip_to_attach_to_after_exit_, point_in_screen); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the tabs into position. 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MoveAttached(point_in_screen); 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetWidget()->Activate(); 1110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Activate may trigger a focus loss, destroying us. 1111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!ref) 1112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip_to_attach_to_after_exit_ = NULL; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(attached_tabstrip_); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetWidget()->SetCapture(attached_tabstrip_); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (active_) { 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndDrag(result == views::Widget::MOVE_LOOP_CANCELED ? 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) END_DRAG_CANCEL : END_DRAG_COMPLETE); 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabDragController::GetInsertionIndexFrom(const gfx::Rect& dragged_bounds, 1124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int start) const { 1125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int last_tab = attached_tabstrip_->tab_count() - 1; 1126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Make the actual "drag insertion point" be just after the leading edge of 1127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the first dragged tab. This is closer to where the user thinks of the tab 1128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // as "starting" than just dragged_bounds.x(), especially with narrow tabs. 1129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int dragged_x = dragged_bounds.x() + Tab::leading_width_for_drag(); 1130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (start < 0 || start > last_tab || 1131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dragged_x < attached_tabstrip_->ideal_bounds(start).x()) 1132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return -1; 1133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (int i = start; i <= last_tab; ++i) { 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); 1136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dragged_x < (ideal_bounds.x() + (ideal_bounds.width() / 2))) 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (dragged_x < attached_tabstrip_->ideal_bounds(last_tab).right()) ? 1141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (last_tab + 1) : -1; 1142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int TabDragController::GetInsertionIndexFromReversed( 1145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const gfx::Rect& dragged_bounds, 1146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int start) const { 1147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Make the actual "drag insertion point" be just after the leading edge of 1148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // the first dragged tab. This is closer to where the user thinks of the tab 1149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // as "starting" than just dragged_bounds.x(), especially with narrow tabs. 1150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int dragged_x = dragged_bounds.x() + Tab::leading_width_for_drag(); 1151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (start < 0 || start >= attached_tabstrip_->tab_count() || 1152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dragged_x >= attached_tabstrip_->ideal_bounds(start).right()) 1153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return -1; 1154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (int i = start; i >= 0; --i) { 1156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); 1157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dragged_x >= (ideal_bounds.x() + (ideal_bounds.width() / 2))) 1158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return i + 1; 1159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (dragged_x >= attached_tabstrip_->ideal_bounds(0).x()) ? 0 : -1; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabDragController::GetInsertionIndexForDraggedBounds( 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& dragged_bounds) const { 1166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the strip has no tabs, the only position to insert at is 0. 1167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int tab_count = attached_tabstrip_->tab_count(); 1168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!tab_count) 1169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 1170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = -1; 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_->touch_layout_.get()) { 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = GetInsertionIndexForDraggedBoundsStacked(dragged_bounds); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) { 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only move the tab to the left/right if the user actually moved the 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse that way. This is necessary as tabs with stacked tabs 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before/after them have multiple drag positions. 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int active_index = attached_tabstrip_->touch_layout_->active_index(); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((index < active_index && 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mouse_move_direction_ & kMovedMouseLeft) == 0) || 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (index > active_index && 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mouse_move_direction_ & kMovedMouseRight) == 0)) { 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = active_index; 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) index = GetInsertionIndexFrom(dragged_bounds, 0); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == -1) { 1190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const int last_tab_right = 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->ideal_bounds(tab_count - 1).right(); 1192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) index = (dragged_bounds.right() > last_tab_right) ? tab_count : 0; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Tab* last_visible_tab = attached_tabstrip_->GetLastVisibleTab(); 1196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int last_insertion_point = last_visible_tab ? 1197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (attached_tabstrip_->GetModelIndexOfTab(last_visible_tab) + 1) : 0; 1198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (drag_data_[0].attached_tab) { 1199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // We're not in the process of attaching, so clamp the insertion point to 1200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // keep it within the visible region. 1201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) last_insertion_point = std::max( 1202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 0, last_insertion_point - static_cast<int>(drag_data_.size())); 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ensure the first dragged tab always stays in the visible index range. 1206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return std::min(index, last_insertion_point); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::ShouldDragToNextStackedTab( 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& dragged_bounds, 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) const { 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index + 1 >= attached_tabstrip_->tab_count() || 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !attached_tabstrip_->touch_layout_->IsStacked(index + 1) || 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mouse_move_direction_ & kMovedMouseRight) == 0) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int active_x = attached_tabstrip_->ideal_bounds(index).x(); 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int next_x = attached_tabstrip_->ideal_bounds(index + 1).x(); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mid_x = std::min(next_x - kStackedDistance, 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_x + (next_x - active_x) / 4); 1221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(pkasting): Should this add Tab::leading_width_for_drag() as 1222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GetInsertionIndexFrom() does? 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dragged_bounds.x() >= mid_x; 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::ShouldDragToPreviousStackedTab( 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& dragged_bounds, 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) const { 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index - 1 < attached_tabstrip_->GetMiniTabCount() || 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !attached_tabstrip_->touch_layout_->IsStacked(index - 1) || 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (mouse_move_direction_ & kMovedMouseLeft) == 0) 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int active_x = attached_tabstrip_->ideal_bounds(index).x(); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int previous_x = attached_tabstrip_->ideal_bounds(index - 1).x(); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mid_x = std::max(previous_x + kStackedDistance, 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_x - (active_x - previous_x) / 4); 1238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(pkasting): Should this add Tab::leading_width_for_drag() as 1239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GetInsertionIndexFrom() does? 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dragged_bounds.x() <= mid_x; 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabDragController::GetInsertionIndexForDraggedBoundsStacked( 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& dragged_bounds) const { 12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StackedTabStripLayout* touch_layout = attached_tabstrip_->touch_layout_.get(); 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int active_index = touch_layout->active_index(); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search from the active index to the front of the tabstrip. Do this as tabs 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overlap each other from the active index. 1249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int index = GetInsertionIndexFromReversed(dragged_bounds, active_index); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != active_index) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == -1) 1253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return GetInsertionIndexFrom(dragged_bounds, active_index + 1); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The position to drag to corresponds to the active tab. If the next/previous 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tab is stacked, then shorten the distance used to determine insertion 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bounds. We do this as GetInsertionIndexFrom() uses the bounds of the 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tabs. When tabs are stacked the next/previous tab is on top of the tab. 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active_index + 1 < attached_tabstrip_->tab_count() && 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) touch_layout->IsStacked(active_index + 1)) { 1261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) index = GetInsertionIndexFrom(dragged_bounds, active_index + 1); 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == -1 && ShouldDragToNextStackedTab(dragged_bounds, active_index)) 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = active_index + 1; 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (index == -1) 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = active_index; 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ShouldDragToPreviousStackedTab(dragged_bounds, active_index)) { 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = active_index - 1; 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TabDragController::GetDraggedViewTabStripBounds( 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& tab_strip_point) { 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attached_tab is NULL when inserting into a new tabstrip. 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_tab_drag_data()->attached_tab) { 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tab_drag_data()->attached_tab->width(), 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tab_drag_data()->attached_tab->height()); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double sel_width, unselected_width; 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetCurrentTabWidths(&sel_width, &unselected_width); 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(sel_width), 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Tab::GetStandardSize().height()); 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point TabDragController::GetAttachedDragPoint( 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(attached_tabstrip_); // The tab must be attached. 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point tab_loc(point_in_screen); 1293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::View::ConvertPointFromScreen(attached_tabstrip_, &tab_loc); 12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int x = 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetMirroredXInView(tab_loc.x()) - mouse_offset_.x(); 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: consider caching this. 12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> attached_tabs; 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabs.push_back(drag_data_[i].attached_tab); 13014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int size = attached_tabstrip_->GetSizeNeededForTabs(attached_tabs); 13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int max_x = attached_tabstrip_->width() - size; 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Point(std::min(std::max(x, 0), max_x), 0); 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<Tab*> TabDragController::GetTabsMatchingDraggedContents( 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* tabstrip) { 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* model = GetModel(attached_tabstrip_); 13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> tabs; 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 13112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int model_index = model->GetIndexOfWebContents(drag_data_[i].contents); 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_index == TabStripModel::kNoTab) 13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return std::vector<Tab*>(); 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs.push_back(tabstrip->tab_at(model_index)); 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tabs; 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::vector<gfx::Rect> TabDragController::CalculateBoundsForDraggedTabs() { 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Rect> drag_bounds; 13212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> attached_tabs; 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabs.push_back(drag_data_[i].attached_tab); 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->CalculateBoundsForDraggedTabs(attached_tabs, 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &drag_bounds); 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return drag_bounds; 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::EndDragImpl(EndDragType type) { 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(active_); 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_ = false; 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bring_to_front_timer_.Stop(); 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_stacked_timer_.Stop(); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_dragging_window_) { 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_run_loop_to_exit_ = true; 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == NORMAL || (type == TAB_DESTROYED && drag_data_.size() > 1)) { 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPositionManaged(GetAttachedBrowserWidget()->GetNativeView(), 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // End the nested drag loop. 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAttachedBrowserWidget()->EndMoveLoop(); 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != TAB_DESTROYED) { 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only finish up the drag if we were actually dragging. If start_drag_ 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is false, the user just clicked and released and didn't move the mouse 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enough to trigger a drag. 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (started_drag_) { 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RestoreFocus(); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == CANCELED) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RevertDrag(); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompleteDrag(); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (drag_data_.size() > 1) { 1360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) initial_selection_model_.Clear(); 13611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (started_drag_) 13621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RevertDrag(); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // else case the only tab we were dragging was deleted. Nothing to do. 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear out drag data so we don't attempt to do anything with it. 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_.clear(); 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TabStrip* owning_tabstrip = attached_tabstrip_ ? 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_ : source_tabstrip_; 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owning_tabstrip->DestroyDragController(); 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::RevertDrag() { 13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Tab*> tabs; 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_data_[i].contents) { 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Contents is NULL if a tab was destroyed while the drag was under way. 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs.push_back(drag_data_[i].attached_tab); 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RevertDragAt(i); 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_) { 13845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (did_restore_window_) 13855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MaximizeAttachedWindow(); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_ == source_tabstrip_) { 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_->StoppedDraggingTabs( 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs, initial_tab_positions_, move_behavior_ == MOVE_VISIBILE_TABS, 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->DraggedTabsDetached(); 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initial_selection_model_.empty()) 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetSelection(GetModel(source_tabstrip_)); 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(source_tabstrip_)->SetSelectionFromModel(initial_selection_model_); 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (source_tabstrip_) 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_tabstrip_->GetWidget()->Activate(); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::ResetSelection(TabStripModel* model) { 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model); 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel selection_model; 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_one_valid_tab = false; 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |contents| is NULL if a tab was deleted out from under us. 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_data_[i].contents) { 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = model->GetIndexOfWebContents(drag_data_[i].contents); 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, index); 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model.AddIndexToSelection(index); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_one_valid_tab || i == source_tab_index_) { 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the active/lead to the first tab. If the source tab is still 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid we'll reset these again later on. 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model.set_active(index); 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model.set_anchor(index); 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_one_valid_tab = true; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_one_valid_tab) 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->SetSelectionFromModel(selection_model); 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TabDragController::RestoreInitialSelection() { 14305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // First time detaching from the source tabstrip. Reset selection model to 14315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // initial_selection_model_. Before resetting though we have to remove all 14325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the tabs from initial_selection_model_ as it was created with the tabs 14335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // still there. 14345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::ListSelectionModel selection_model; 14355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) selection_model.Copy(initial_selection_model_); 14365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DragData::const_reverse_iterator i(drag_data_.rbegin()); 14375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) i != drag_data_.rend(); ++i) { 14385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) selection_model.DecrementFrom(i->source_model_index); 14395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 14405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We may have cleared out the selection model. Only reset it if it 14415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // contains something. 14425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (selection_model.empty()) 14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 14455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The anchor/active may have been among the tabs that were dragged out. Force 14465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the anchor/active to be valid. 14475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (selection_model.anchor() == ui::ListSelectionModel::kUnselectedIndex) 14485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) selection_model.set_anchor(selection_model.selected_indices()[0]); 14495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (selection_model.active() == ui::ListSelectionModel::kUnselectedIndex) 14505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) selection_model.set_active(selection_model.selected_indices()[0]); 14515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetModel(source_tabstrip_)->SetSelectionFromModel(selection_model); 14525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 14535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::RevertDragAt(size_t drag_index) { 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(started_drag_); 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(source_tabstrip_); 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> setter(&is_mutating_, true); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabDragData* data = &(drag_data_[drag_index]); 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_) { 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = 14622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(attached_tabstrip_)->GetIndexOfWebContents(data->contents); 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_ != source_tabstrip_) { 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Tab was inserted into another TabStrip. We need to put it back 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // into the original one. 14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(attached_tabstrip_)->DetachWebContentsAt(index); 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(beng): (Cleanup) seems like we should use Attach() for this 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // somehow. 14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(source_tabstrip_)->InsertWebContentsAt( 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->source_model_index, data->contents, 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (data->pinned ? TabStripModel::ADD_PINNED : 0)); 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Tab was moved within the TabStrip where the drag was initiated. 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move it back to the starting location. 14752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(source_tabstrip_)->MoveWebContentsAt( 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index, data->source_model_index, false); 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Tab was detached from the TabStrip where the drag began, and has not 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been attached to any other TabStrip. We need to put it back into the 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // source TabStrip. 14822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetModel(source_tabstrip_)->InsertWebContentsAt( 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->source_model_index, data->contents, 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (data->pinned ? TabStripModel::ADD_PINNED : 0)); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::CompleteDrag() { 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(started_drag_); 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attached_tabstrip_) { 14925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_dragging_new_browser_ || did_restore_window_) { 1493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IsDockedOrSnapped(attached_tabstrip_)) { 14941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) was_source_maximized_ = false; 14951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) was_source_fullscreen_ = false; 14961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 149868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If source window was maximized - maximize the new window as well. 1499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (was_source_maximized_ || was_source_fullscreen_) 15005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MaximizeAttachedWindow(); 150168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 15024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) attached_tabstrip_->StoppedDraggingTabs( 15034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetTabsMatchingDraggedContents(attached_tabstrip_), 15044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) initial_tab_positions_, 15054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) move_behavior_ == MOVE_VISIBILE_TABS, 15064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) true); 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compel the model to construct a new window for the detached 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WebContentses. 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget* widget = source_tabstrip_->GetWidget(); 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_bounds(widget->GetRestoredBounds()); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.set_origin(GetWindowCreatePoint(last_point_in_screen_)); 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> setter(&is_mutating_, true); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TabStripModelDelegate::NewStripContents> contentses; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < drag_data_.size(); ++i) { 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModelDelegate::NewStripContents item; 15192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item.web_contents = drag_data_[i].contents; 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.add_types = drag_data_[i].pinned ? TabStripModel::ADD_PINNED 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : TabStripModel::ADD_NONE; 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contentses.push_back(item); 15234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* new_browser = 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModel(source_tabstrip_)->delegate()->CreateNewStripWithContents( 1527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) contentses, window_bounds, widget->IsMaximized()); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetSelection(new_browser->tab_strip_model()); 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_browser->window()->Show(); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TabDragController::MaximizeAttachedWindow() { 15345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetAttachedBrowserWidget()->Maximize(); 153503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(USE_ASH) 15365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (was_source_fullscreen_ && 15375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) { 15385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In fullscreen mode it is only possible to get here if the source 15395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // was in "immersive fullscreen" mode, so toggle it back on. 15405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ash::accelerators::ToggleFullscreen(); 15415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 154203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif 15435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 15445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect TabDragController::GetViewScreenBounds( 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view) const { 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point view_topleft; 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToScreen(view, &view_topleft); 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect view_screen_bounds = view->GetLocalBounds(); 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_screen_bounds.Offset(view_topleft.x(), view_topleft.y()); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view_screen_bounds; 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabDragController::BringWindowUnderPointToFront( 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 1556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) aura::Window* window = GetLocalProcessWindow(point_in_screen, true); 1557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Only bring browser windows to front - only windows with a TabStrip can 1559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // be tab drag targets. 1560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!GetTabStripForWindow(window)) 1561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 1562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window) { 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget* widget_window = views::Widget::GetWidgetForNativeView( 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window); 15663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!widget_window) 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) { 1570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(varkha): The code below ensures that the phantom drag widget 1571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // is shown on top of browser windows. The code should be moved to ash/ 1572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // and the phantom should be able to assert its top-most state on its own. 1573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // One strategy would be for DragWindowController to 1574d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // be able to observe stacking changes to the phantom drag widget's 1575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // siblings in order to keep it on top. One way is to implement a 1576d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // notification that is sent to a window parent's observers when a 1577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // stacking order is changed among the children of that same parent. 1578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note that OnWindowStackingChanged is sent only to the child that is the 1579d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // argument of one of the Window::StackChildX calls and not to all its 1580d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // siblings affected by the stacking change. 1581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) aura::Window* browser_window = widget_window->GetNativeView(); 1582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Find a topmost non-popup window and stack the recipient browser above 1583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // it in order to avoid stacking the browser window on top of the phantom 1584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // drag widget created by DragWindowController in a second display. 1585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (aura::Window::Windows::const_reverse_iterator it = 1586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) browser_window->parent()->children().rbegin(); 1587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) it != browser_window->parent()->children().rend(); ++it) { 1588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the iteration reached the recipient browser window then it is 1589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // already topmost and it is safe to return with no stacking change. 1590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (*it == browser_window) 1591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 15925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((*it)->type() != ui::wm::WINDOW_TYPE_POPUP) { 1593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) widget_window->StackAbove(*it); 1594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) break; 1595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 15963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 1598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) widget_window->StackAtTop(); 15993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 16003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The previous call made the window appear on top of the dragged window, 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // move the dragged window to the front. 16035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_dragging_window_) 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_->GetWidget()->StackAtTop(); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStripModel* TabDragController::GetModel( 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* tabstrip) const { 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<BrowserTabStripController*>(tabstrip->controller())-> 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model(); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::Widget* TabDragController::GetAttachedBrowserWidget() { 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return attached_tabstrip_->GetWidget(); 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabDragController::AreTabsConsecutive() { 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 1; i < drag_data_.size(); ++i) { 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_data_[i - 1].source_model_index + 1 != 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data_[i].source_model_index) { 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Rect TabDragController::CalculateDraggedBrowserBounds( 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStrip* source, 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen, 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Rect>* drag_bounds) { 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point center(0, source->height() / 2); 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToWidget(source, ¢er); 16347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch gfx::Rect new_bounds(source->GetWidget()->GetRestoredBounds()); 163568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (source->GetWidget()->IsMaximized()) { 163668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If the restore bounds is really small, we don't want to honor it 163768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // (dragging a really small window looks wrong), instead make sure the new 163868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // window is at least 50% the size of the old. 163968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const gfx::Size max_size( 164068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) source->GetWidget()->GetWindowBoundsInScreen().size()); 164168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new_bounds.set_width( 164268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::max(max_size.width() / 2, new_bounds.width())); 164368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new_bounds.set_height( 1644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::max(max_size.height() / 2, new_bounds.height())); 164568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bounds.set_y(point_in_screen.y() - center.y()); 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (GetDetachPosition(point_in_screen)) { 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DETACH_BEFORE: 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bounds.set_x(point_in_screen.x() - center.x()); 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bounds.Offset(-mouse_offset_.x(), 0); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DETACH_AFTER: { 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point right_edge(source->width(), 0); 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToWidget(source, &right_edge); 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bounds.set_x(point_in_screen.x() - right_edge.x()); 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_bounds.Offset(drag_bounds->back().right() - mouse_offset_.x(), 0); 16574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OffsetX(-(*drag_bounds)[0].x(), drag_bounds); 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Nothing to do for DETACH_ABOVE_OR_BELOW. 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // To account for the extra vertical on restored windows that is absent on 16654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // maximized windows, add an additional vertical offset extracted from the tab 16664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // strip. 16674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (source->GetWidget()->IsMaximized()) 1668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new_bounds.Offset(0, -source->kNewTabButtonVerticalOffset); 1669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return new_bounds; 1670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TabDragController::AdjustBrowserAndTabBoundsForDrag( 1673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int last_tabstrip_width, 1674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::Point& point_in_screen, 1675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<gfx::Rect>* drag_bounds) { 1676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) attached_tabstrip_->InvalidateLayout(); 1677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) attached_tabstrip_->DoLayout(); 1678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const int dragged_tabstrip_width = attached_tabstrip_->tab_area_width(); 1679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If the new tabstrip is smaller than the old resize the tabs. 1681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (dragged_tabstrip_width < last_tabstrip_width) { 1682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const float leading_ratio = 1683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_bounds->front().x() / static_cast<float>(last_tabstrip_width); 1684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *drag_bounds = CalculateBoundsForDraggedTabs(); 1685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (drag_bounds->back().right() < dragged_tabstrip_width) { 1687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const int delta_x = 1688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::min(static_cast<int>(leading_ratio * dragged_tabstrip_width), 1689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_tabstrip_width - 1690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (drag_bounds->back().right() - 1691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_bounds->front().x())); 1692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OffsetX(delta_x, drag_bounds); 1693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 16944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Reposition the restored window such that the tab that was dragged remains 1696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // under the mouse cursor. 1697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Point offset( 1698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<int>((*drag_bounds)[source_tab_index_].width() * 1699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) offset_to_width_ratio_) + 1700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (*drag_bounds)[source_tab_index_].x(), 0); 1701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) views::View::ConvertPointToWidget(attached_tabstrip_, &offset); 1702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Rect bounds = GetAttachedBrowserWidget()->GetWindowBoundsInScreen(); 1703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bounds.set_x(point_in_screen.x() - offset.x()); 1704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetAttachedBrowserWidget()->SetBounds(bounds); 1705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) attached_tabstrip_->SetTabBoundsForDrag(*drag_bounds); 1707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1708a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1709a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Browser* TabDragController::CreateBrowserForDrag( 1710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TabStrip* source, 1711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::Point& point_in_screen, 1712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Vector2d* drag_offset, 1713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<gfx::Rect>* drag_bounds) { 1714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gfx::Rect new_bounds(CalculateDraggedBrowserBounds(source, 1715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) point_in_screen, 1716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_bounds)); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *drag_offset = point_in_screen - new_bounds.origin(); 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = 17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile::FromBrowserContext(drag_data_[0].contents->GetBrowserContext()); 17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser::CreateParams create_params(Browser::TYPE_TABBED, 17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile, 17232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_desktop_type_); 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_params.initial_bounds = new_bounds; 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser = new Browser(create_params); 172668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) is_dragging_new_browser_ = true; 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPositionManaged(browser->window()->GetNativeWindow(), false); 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the window is created maximized then the bounds we supplied are ignored. 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to reset them again so they are honored. 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->window()->SetBounds(new_bounds); 173190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser; 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point TabDragController::GetCursorScreenPoint() { 17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH && 17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_source_ == EVENT_SOURCE_TOUCH && 17382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Env::GetInstance()->is_touch_down()) { 17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget* widget = GetAttachedBrowserWidget(); 17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(widget); 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* widget_window = widget->GetNativeWindow(); 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(widget_window->GetRootWindow()); 17435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::PointF touch_point_f; 17448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool got_touch_point = ui::GestureRecognizer::Get()-> 17455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetLastTouchPointForTarget(widget_window, &touch_point_f); 17465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(tdresser): Switch to using gfx::PointF. See crbug.com/337824. 17475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Point touch_point = gfx::ToFlooredPoint(touch_point_f); 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(got_touch_point); 17496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) wm::ConvertPointToScreen(widget_window->GetRootWindow(), &touch_point); 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return touch_point; 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return screen_->GetCursorScreenPoint(); 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Vector2d TabDragController::GetWindowOffset( 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_screen) { 1758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TabStrip* owning_tabstrip = attached_tabstrip_ ? 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attached_tabstrip_ : source_tabstrip_; 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* toplevel_view = owning_tabstrip->GetWidget()->GetContentsView(); 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point point = point_in_screen; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointFromScreen(toplevel_view, &point); 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return point.OffsetFromOrigin(); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1766a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1767a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::NativeWindow TabDragController::GetLocalProcessWindow( 1768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Point& screen_point, 1769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool exclude_dragged_view) { 1770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::set<aura::Window*> exclude; 1771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (exclude_dragged_view) { 1772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) aura::Window* dragged_window = 1773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attached_tabstrip_->GetWidget()->GetNativeView(); 1774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (dragged_window) 1775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) exclude.insert(dragged_window); 1776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1777e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 1778e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Exclude windows which are pending deletion via Browser::TabStripEmpty(). 1779e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // These windows can be returned in the Linux Aura port because the browser 1780e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // window which was used for dragging is not hidden once all of its tabs are 1781e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // attached to another browser window in DragBrowserToNewTabStrip(). 1782e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // TODO(pkotwicz): Fix this properly (crbug.com/358482) 1783e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch BrowserList* browser_list = BrowserList::GetInstance( 1784e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch chrome::HOST_DESKTOP_TYPE_NATIVE); 1785e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (BrowserList::const_iterator it = browser_list->begin(); 1786e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch it != browser_list->end(); ++it) { 1787e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if ((*it)->tab_strip_model()->empty()) 1788e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch exclude.insert((*it)->window()->GetNativeWindow()); 1789e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 1790e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif 1791a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetLocalProcessWindowAtPoint(host_desktop_type_, 1792a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) screen_point, 1793a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) exclude); 1794a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1796