172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/dragged_tab_controller.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <math.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_function_dispatcher.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/tabs/tab_strip_model.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/base_tab.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/base_tab_strip.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/dragged_tab_view.h" 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/native_view_photobooth.h" 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/side_tab.h" 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/side_tab_strip.h" 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/tab.h" 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/tab_strip.h" 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/animation.h" 323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/animation_delegate.h" 333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/slide_animation.h" 3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h" 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/events/event.h" 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/screen.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h" 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h" 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_win.h" 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <gdk/gdk.h> // NOLINT 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <gdk/gdkkeysyms.h> // NOLINT 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kHorizontalMoveThreshold = 16; // Pixels. 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Distance in pixels the user must move the mouse before we consider moving 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// an attached vertical tab. 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kVerticalMoveThreshold = 8; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// If non-null there is a drag underway. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic DraggedTabController* instance_; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Delay, in ms, during dragging before we bring a window to front. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBringToFrontDelay = 750; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Radius of the rect drawn by DockView. 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRoundedRectRadius = 4; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Spacing between tab icons when DockView is showing a docking location that 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// contains more than one tab. 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTabSpacing = 4; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DockView is the view responsible for giving a visual indicator of where a 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dock is going to occur. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DockView : public views::View { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit DockView(DockInfo::Type type) : type_(type) {} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual gfx::Size GetPreferredSize() { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Size(DockInfo::popup_width(), DockInfo::popup_height()); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual void OnPaintBackground(gfx::Canvas* canvas) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkRect outer_rect = { SkIntToScalar(0), SkIntToScalar(0), 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(width()), 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(height()) }; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fill the background rect. 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkPaint paint; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setColor(SkColorSetRGB(108, 108, 108)); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setStyle(SkPaint::kFill_Style); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->drawRoundRect( 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch outer_rect, SkIntToScalar(kRoundedRectRadius), 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(kRoundedRectRadius), paint); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* high_icon = rb.GetBitmapNamed(IDR_DOCK_HIGH); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* wide_icon = rb.GetBitmapNamed(IDR_DOCK_WIDE); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick canvas->Save(); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool rtl_ui = base::i18n::IsRTL(); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rtl_ui) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Flip canvas to draw the mirrored tab images for RTL UI. 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TranslateInt(width(), 0); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->ScaleInt(-1, 1); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int x_of_active_tab = width() / 2 + kTabSpacing / 2; 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int x_of_inactive_tab = width() / 2 - high_icon->width() - kTabSpacing / 2; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type_) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::LEFT_OF_WINDOW: 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::LEFT_HALF: 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!rtl_ui) 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::swap(x_of_active_tab, x_of_inactive_tab); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*high_icon, x_of_active_tab, 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (height() - high_icon->height()) / 2); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_ == DockInfo::LEFT_OF_WINDOW) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (height() - high_icon->height()) / 2); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::RIGHT_OF_WINDOW: 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::RIGHT_HALF: 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rtl_ui) 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::swap(x_of_active_tab, x_of_inactive_tab); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*high_icon, x_of_active_tab, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (height() - high_icon->height()) / 2); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_ == DockInfo::RIGHT_OF_WINDOW) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (height() - high_icon->height()) / 2); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::TOP_OF_WINDOW: 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() / 2 - high_icon->height()); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::MAXIMIZE: { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* max_icon = rb.GetBitmapNamed(IDR_DOCK_MAX); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*max_icon, (width() - max_icon->width()) / 2, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (height() - max_icon->height()) / 2); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::BOTTOM_HALF: 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::BOTTOM_OF_WINDOW: 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() / 2 + kTabSpacing / 2); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_ == DockInfo::BOTTOM_OF_WINDOW) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DrawBitmapWithAlpha(canvas, *wide_icon, 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (width() - wide_icon->width()) / 2, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() / 2 - kTabSpacing / 2 - wide_icon->height()); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick canvas->Restore(); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DrawBitmapWithAlpha(gfx::Canvas* canvas, const SkBitmap& image, 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x, int y) { 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkPaint paint; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setAlpha(128); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(image, x, y, paint); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockInfo::Type type_; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(DockView); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the the x-coordinate of |point| if the type of tabstrip is horizontal 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// otherwise returns the y-coordinate. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint MajorAxisValue(const gfx::Point& point, BaseTabStrip* tabstrip) { 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) ? 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch point.x() : point.y(); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DockDisplayer 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DockDisplayer is responsible for giving the user a visual indication of a 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// possible dock position (as represented by DockInfo). DockDisplayer shows 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a window with a DockView in it. Two animations are used that correspond to 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the state of DockInfo::in_enable_area. 1953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass DraggedTabController::DockDisplayer : public ui::AnimationDelegate { 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockDisplayer(DraggedTabController* controller, 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DockInfo& info) 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : controller_(controller), 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_(NULL), 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_view_(NULL), 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(animation_(this)), 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hidden_(false), 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_enable_area_(info.in_enable_area()) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(sky): This should "just work" on Gtk now. 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP); 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.transparent = true; 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.keep_on_top = true; 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen popup_ = views::Widget::CreateWidget(params); 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen popup_->SetOpacity(0x00); 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen popup_->Init(NULL, info.GetPopupRect()); 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen popup_->SetContentsView(new DockView(info.type())); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (info.in_enable_area()) 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_.Reset(1); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_.Show(); 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen popup_->Show(); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_view_ = popup_->GetNativeView(); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~DockDisplayer() { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (controller_) 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->DockDisplayerDestroyed(this); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the state based on |in_enable_area|. 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateInEnabledArea(bool in_enable_area) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (in_enable_area != in_enable_area_) { 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_enable_area_ = in_enable_area; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateLayeredAlpha(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Resets the reference to the hosting DraggedTabController. This is invoked 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the DraggedTabController is destoryed. 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void clear_controller() { controller_ = NULL; } 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NativeView of the window we create. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView popup_view() { return popup_view_; } 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Starts the hide animation. When the window is closed the 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DraggedTabController is notified by way of the DockDisplayerDestroyed 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // method 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Hide() { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (hidden_) 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!popup_) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete this; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hidden_ = true; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_.Hide(); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationProgressed(const ui::Animation* animation) { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateLayeredAlpha(); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationEnded(const ui::Animation* animation) { 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!hidden_) 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<views::WidgetWin*>(popup_)->Close(); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete this; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void UpdateLayeredAlpha() { 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double scale = in_enable_area_ ? 1 : .5; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<views::WidgetWin*>(popup_)->SetOpacity( 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<BYTE>(animation_.GetCurrentValue() * scale * 255.0)); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup_->GetRootView()->SchedulePaint(); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DraggedTabController that created us. 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DraggedTabController* controller_; 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Window we're showing. 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Widget* popup_; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NativeView of |popup_|. We cache this to avoid the possibility of 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // invoking a method on popup_ after we close it. 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView popup_view_; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Animation for when first made visible. 2983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ui::SlideAnimation animation_; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Have we been hidden? 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool hidden_; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Value of DockInfo::in_enable_area. 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool in_enable_area_; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDraggedTabController::TabDragData::TabDragData() 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : contents(NULL), 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen original_delegate(NULL), 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_model_index(-1), 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tab(NULL), 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pinned(false) { 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDraggedTabController::TabDragData::~TabDragData() { 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, public: 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDraggedTabController::DraggedTabController() 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : source_tabstrip_(NULL), 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_(NULL), 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_offset_(0), 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_to_width_ratio_(0), 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_focused_view_(NULL), 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_move_screen_loc_(0), 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch started_drag_(false), 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen active_(true), 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_index_(std::numeric_limits<size_t>::max()), 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen initial_move_(true) { 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instance_ = this; 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDraggedTabController::~DraggedTabController() { 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (instance_ == this) 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instance_ = NULL; 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoopForUI::current()->RemoveObserver(this); 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Need to delete the view here manually _before_ we reset the dragged 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // contents to NULL, otherwise if the view is animating to its destination 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bounds, it won't be able to clean up properly since its cleanup routine 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // uses GetIndexForDraggedContents, which will be invalid. 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view_.reset(NULL); 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Reset the delegate of the dragged TabContents. This ends up doing nothing 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // if the drag was completed. 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetDelegates(); 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::Init(BaseTabStrip* source_tabstrip, 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTab* source_tab, 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<BaseTab*>& tabs, 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Point& mouse_offset, 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int source_tab_offset) { 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!tabs.empty()); 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tabstrip_ = source_tabstrip; 359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_offset_ = source_tab_offset; 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_screen_point_ = GetCursorScreenPoint(); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mouse_offset_ = mouse_offset; 362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_.resize(tabs.size()); 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InitTabDragData(tabs[i], &(drag_data_[i])); 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_index_ = 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(tabs.begin(), tabs.end(), source_tab) - tabs.begin(); 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Listen for Esc key presses. 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoopForUI::current()->AddObserver(this); 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (source_tab->width() > 0) { 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen offset_to_width_ratio_ = static_cast<float>(source_tab_offset_) / 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<float>(source_tab->width()); 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitWindowCreatePoint(); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DraggedTabController::IsAttachedTo(BaseTabStrip* tab_strip) { 381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return instance_ && instance_->active_ && 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen instance_->attached_tabstrip_ == tab_strip; 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::Drag() { 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bring_to_front_timer_.Stop(); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!started_drag_) { 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!CanStartDrag()) 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; // User hasn't dragged far enough yet. 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch started_drag_ = true; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SaveFocus(); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Attach(source_tabstrip_, gfx::Point()); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ContinueDragging(); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::EndDrag(bool canceled) { 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndDragImpl(canceled ? CANCELED : NORMAL); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::InitTabDragData(BaseTab* tab, 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabDragData* drag_data) { 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->source_model_index = 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tabstrip_->GetModelIndexOfBaseTab(tab); 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->contents = GetModel(source_tabstrip_)->GetTabContentsAt( 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->source_model_index); 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->pinned = source_tabstrip_->IsTabPinned(tab); 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_.Add(this, 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationType::TAB_CONTENTS_DESTROYED, 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<TabContents>(drag_data->contents->tab_contents())); 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We need to be the delegate so we receive messages about stuff, otherwise 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // our dragged TabContents may be replaced and subsequently 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // collected/destroyed while the drag is in process, leading to nasty crashes. 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->original_delegate = 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->contents->tab_contents()->delegate(); 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data->contents->tab_contents()->set_delegate(this); 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, PageNavigator implementation: 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::OpenURLFromTab(TabContents* source, 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& referrer, 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition disposition, 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition) { 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (source_tab_drag_data()->original_delegate) { 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (disposition == CURRENT_TAB) 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disposition = NEW_WINDOW; 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_drag_data()->original_delegate->OpenURLFromTab( 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source, url, referrer, disposition, transition); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, TabContentsDelegate implementation: 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::NavigationStateChanged(const TabContents* source, 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unsigned changed_flags) { 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (view_.get()) 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view_->Update(); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::AddNewContents(TabContents* source, 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* new_contents, 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition disposition, 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& initial_pos, 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool user_gesture) { 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(CURRENT_TAB, disposition); 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Theoretically could be called while dragging if the page tries to 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // spawn a window. Route this message back to the browser in most cases. 458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (source_tab_drag_data()->original_delegate) { 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_drag_data()->original_delegate->AddNewContents( 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source, new_contents, disposition, initial_pos, user_gesture); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::ActivateContents(TabContents* contents) { 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignored. 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DraggedTabController::DeactivateContents(TabContents* contents) { 4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Ignored. 4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::LoadingStateChanged(TabContents* source) { 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It would be nice to respond to this message by changing the 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // screen shot in the dragged tab. 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (view_.get()) 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view_->Update(); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::CloseContents(TabContents* source) { 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Theoretically could be called by a window. Should be ignored 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because window.close() is ignored (usually, even though this 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // method gets called.) 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::MoveContents(TabContents* source, 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& pos) { 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Theoretically could be called by a web page trying to move its 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // own window. Should be ignored since we're moving the window... 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::UpdateTargetURL(TabContents* source, 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url) { 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignored. 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DraggedTabController::ShouldSuppressDialogs() { 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When a dialog is about to be shown we revert the drag. Otherwise a modal 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // dialog might appear and attempt to parent itself to a hidden tabcontents. 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EndDragImpl(CANCELED); 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, NotificationObserver implementation: 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::Observe(NotificationType type, 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(type.value, NotificationType::TAB_CONTENTS_DESTROYED); 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContents* destroyed_contents = Source<TabContents>(source).ptr(); 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i].contents->tab_contents() == destroyed_contents) { 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // One of the tabs we're dragging has been destroyed. Cancel the drag. 514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (destroyed_contents->delegate() == this) 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destroyed_contents->set_delegate(NULL); 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents = NULL; 517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].original_delegate = NULL; 518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EndDragImpl(TAB_DESTROYED); 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we get here it means we got notification for a tab we don't know about. 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, MessageLoop::Observer implementation: 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::WillProcessMessage(const MSG& msg) { 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::DidProcessMessage(const MSG& msg) { 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the user presses ESC during a drag, we need to abort and revert things 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the way they were. This is the most reliable way to do this since no 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // single view or window reliably receives events throughout all the various 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // kinds of tab dragging. 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndDrag(true); 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::WillProcessEvent(GdkEvent* event) { 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::DidProcessEvent(GdkEvent* event) { 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->type == GDK_KEY_PRESS && 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<GdkEventKey*>(event)->keyval == GDK_Escape) { 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndDrag(true); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DraggedTabController, private: 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::InitWindowCreatePoint() { 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window_create_point_ is only used in CompleteDrag() (through 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetWindowCreatePoint() to get the start point of the docked window) when 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the attached_tabstrip_ is NULL and all the window's related bound 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // information are obtained from source_tabstrip_. So, we need to get the 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise, 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the window_create_point_ is not in the correct coordinate system. Please 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // refer to http://crbug.com/6223 comment #15 for detailed information. 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::View* first_tab = source_tabstrip_->base_tab_at_tab_index(0); 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::View::ConvertPointToWidget(first_tab, &first_source_tab_point_); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_create_point_ = first_source_tab_point_; 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_create_point_.Offset(mouse_offset_.x(), mouse_offset_.y()); 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point DraggedTabController::GetWindowCreatePoint() const { 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point cursor_point = GetCursorScreenPoint(); 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (dock_info_.type() != DockInfo::NONE && dock_info_.in_enable_area()) { 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're going to dock, we need to return the exact coordinate, 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // otherwise we may attempt to maximize on the wrong monitor. 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return cursor_point; 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the cursor is outside the monitor area, move it inside. For example, 57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // dropping a tab onto the task bar on Windows produces this situation. 57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::Rect work_area = views::Screen::GetMonitorWorkAreaNearestPoint( 58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cursor_point); 58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!work_area.IsEmpty()) { 58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (cursor_point.x() < work_area.x()) 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cursor_point.set_x(work_area.x()); 58472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (cursor_point.x() > work_area.right()) 58572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cursor_point.set_x(work_area.right()); 58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (cursor_point.y() < work_area.y()) 58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cursor_point.set_y(work_area.y()); 58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (cursor_point.y() > work_area.bottom()) 58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cursor_point.set_y(work_area.bottom()); 59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Point(cursor_point.x() - window_create_point_.x(), 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cursor_point.y() - window_create_point_.y()); 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::UpdateDockInfo(const gfx::Point& screen_point) { 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the DockInfo for the current mouse coordinates. 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockInfo dock_info = GetDockInfoAtPoint(screen_point); 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (source_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((dock_info.type() == DockInfo::LEFT_OF_WINDOW && 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !base::i18n::IsRTL()) || 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (dock_info.type() == DockInfo::RIGHT_OF_WINDOW && 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::i18n::IsRTL()))) { 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For side tabs it's way to easy to trigger to docking along the left/right 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // edge, so we disable it. 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_info = DockInfo(); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dock_info.equals(dock_info_)) { 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DockInfo for current position differs. 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dock_info_.type() != DockInfo::NONE && 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !dock_controllers_.empty()) { 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Hide old visual indicator. 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_.back()->Hide(); 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_info_ = dock_info; 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dock_info_.type() != DockInfo::NONE) { 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Show new docking position. 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockDisplayer* controller = new DockDisplayer(this, dock_info_); 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (controller->popup_view()) { 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_.push_back(controller); 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.insert(controller->popup_view()); 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete controller; 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (dock_info_.type() != DockInfo::NONE && 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !dock_controllers_.empty()) { 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Current dock position is the same as last, update the controller's 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in_enable_area state as it may have changed. 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_.back()->UpdateInEnabledArea(dock_info_.in_enable_area()); 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::SaveFocus() { 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!old_focused_view_); // This should only be invoked once. 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_focused_view_ = source_tabstrip_->GetFocusManager()->GetFocusedView(); 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tabstrip_->GetFocusManager()->SetFocusedView(source_tabstrip_); 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::RestoreFocus() { 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (old_focused_view_ && attached_tabstrip_ == source_tabstrip_) 641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen old_focused_view_->GetFocusManager()->SetFocusedView(old_focused_view_); 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_focused_view_ = NULL; 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DraggedTabController::CanStartDrag() const { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine if the mouse has moved beyond a minimum elasticity distance in 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // any direction from the starting point. 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kMinimumDragDistance = 10; 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point screen_point = GetCursorScreenPoint(); 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x_offset = abs(screen_point.x() - start_screen_point_.x()); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y_offset = abs(screen_point.y() - start_screen_point_.y()); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return sqrt(pow(static_cast<float>(x_offset), 2) + 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::ContinueDragging() { 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that the coordinates given to us by |drag_event| are basically 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // useless, since they're in source_tab_ coordinates. On the surface, you'd 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // think we could just convert them to screen coordinates, however in the 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // situation where we're dragging the last tab in a window when multiple 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windows are open, the coordinates of |source_tab_| are way off in 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // hyperspace since the window was moved there instead of being closed so 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that we'd keep receiving events. And our ConvertPointToScreen methods 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // aren't really multi-screen aware. So really it's just safer to get the 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // actual position of the mouse cursor directly from Windows here, which is 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // guaranteed to be correct regardless of monitor config. 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point screen_point = GetCursorScreenPoint(); 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_LINUX) 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't allow detaching in chrome os. 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTabStrip* target_tabstrip = source_tabstrip_; 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine whether or not we have dragged over a compatible TabStrip in 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // another browser window. If we have, we should attach to it and start 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // dragging within it. 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTabStrip* target_tabstrip = GetTabStripForPoint(screen_point); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_tabstrip != attached_tabstrip_) { 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we're fully detached from whatever TabStrip we're attached to 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (if any). 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_) 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Detach(); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_tabstrip) 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Attach(target_tabstrip, screen_point); 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!target_tabstrip) { 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bring_to_front_timer_.Start( 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this, 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &DraggedTabController::BringWindowUnderMouseToFront); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateDockInfo(screen_point); 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_) 695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MoveAttached(screen_point); 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MoveDetached(screen_point); 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::MoveAttached(const gfx::Point& screen_point) { 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(attached_tabstrip_); 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!view_.get()); 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point dragged_view_point = GetAttachedDragPoint(screen_point); 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int threshold = kVerticalMoveThreshold; 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStrip* tab_strip = static_cast<TabStrip*>(attached_tabstrip_); 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine the horizontal move threshold. This is dependent on the width 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of tabs. The smaller the tabs compared to the standard size, the smaller 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the threshold. 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double unselected, selected; 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_strip->GetCurrentTabWidths(&unselected, &selected); 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double ratio = unselected / Tab::GetStandardSize().width(); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs(drag_data_.size()); 720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) 721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs[i] = drag_data_[i].attached_tab; 722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool did_layout = false; 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the model, moving the TabContents from one index to another. Do this 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only if we have moved a minimum distance since the last reorder (to prevent 726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // jitter) or if this the first move and the tabs are not consecutive. 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (abs(MajorAxisValue(screen_point, attached_tabstrip_) - 728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen last_move_screen_loc_) > threshold || 729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (initial_move_ && !AreTabsConsecutive())) { 730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabStripModel* attached_model = GetModel(attached_tabstrip_); 731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point); 732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int to_index = GetInsertionIndexForDraggedBounds(bounds); 733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper* last_contents = 734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[drag_data_.size() - 1].contents; 735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index_of_last_item = 736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_model->GetIndexOfTabContents(last_contents); 737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (initial_move_) { 738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TabStrip determines if the tabs needs to be animated based on model 739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // position. This means we need to invoke LayoutDraggedTabsAt before 740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // changing the model. 741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->LayoutDraggedTabsAt( 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen initial_move_); 744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen did_layout = true; 745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_model->MoveSelectedTabsTo(to_index); 747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Move may do nothing in certain situations (such as when dragging pinned 748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // tabs). Make sure the tabstrip actually changed before updating 749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // last_move_screen_loc_. 750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (index_of_last_item != 751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_model->GetIndexOfTabContents(last_contents)) { 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip_); 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!did_layout) { 757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->LayoutDraggedTabsAt( 758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen initial_move_); 760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen initial_move_ = false; 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::MoveDetached(const gfx::Point& screen_point) { 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!attached_tabstrip_); 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(view_.get()); 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move the View. There are no changes to the model if we're detached. 770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen view_->MoveTo(screen_point); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDockInfo DraggedTabController::GetDockInfoAtPoint( 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Point& screen_point) { 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_) { 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the mouse is over a tab strip, don't offer a dock position. 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DockInfo(); 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dock_info_.IsValidForPoint(screen_point)) { 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It's possible any given screen coordinate has multiple docking 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // positions. Check the current info first to avoid having the docking 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // position bounce around. 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dock_info_; 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView dragged_hwnd = view_->GetWidget()->GetNativeView(); 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.insert(dragged_hwnd); 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockInfo info = DockInfo::GetDockInfoAtPoint(screen_point, dock_windows_); 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.erase(dragged_hwnd); 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return info; 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTabStrip* DraggedTabController::GetTabStripForPoint( 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Point& screen_point) { 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView dragged_view = NULL; 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (view_.get()) { 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dragged_view = view_->GetWidget()->GetNativeView(); 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.insert(dragged_view); 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeWindow local_window = 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dragged_view) 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.erase(dragged_view); 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!local_window) 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserView* browser = 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserView::GetBrowserViewForNativeWindow(local_window); 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't allow drops on windows that don't have tabstrips. 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !browser->browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This cast seems ugly, but the controller and the view are tighly coupled at 815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // creation time, so it will be okay. 816ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTabStrip* other_tabstrip = 817ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<BaseTabStrip*>(browser->tabstrip()); 818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!other_tabstrip->controller()->IsCompatibleWith(source_tabstrip_)) 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetTabStripIfItContains(other_tabstrip, screen_point); 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTabStrip* DraggedTabController::GetTabStripIfItContains( 825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTabStrip* tabstrip, 826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Point& screen_point) const { 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kVerticalDetachMagnetism = 15; 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kHorizontalDetachMagnetism = 15; 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure the specified screen point is actually within the bounds of the 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // specified tabstrip... 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_point.x() < tabstrip_bounds.right() && 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_point.x() >= tabstrip_bounds.x()) { 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(beng): make this be relative to the start position of the mouse 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for the source TabStrip. 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism; 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism; 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_point.y() >= lower_threshold && 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_point.y() <= upper_threshold) { 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tabstrip; 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_point.y() < tabstrip_bounds.bottom() && 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_point.y() >= tabstrip_bounds.y()) { 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int upper_threshold = tabstrip_bounds.right() + 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kHorizontalDetachMagnetism; 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int lower_threshold = tabstrip_bounds.x() - kHorizontalDetachMagnetism; 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (screen_point.x() >= lower_threshold && 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_point.x() <= upper_threshold) { 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tabstrip; 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::Attach(BaseTabStrip* attached_tabstrip, 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Point& screen_point) { 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!attached_tabstrip_); // We should already have detached by the time 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we get here. 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_ = attached_tabstrip; 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And we don't need the dragged view. 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view_.reset(); 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs = 870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetTabsMatchingDraggedContents(attached_tabstrip_); 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tabs.empty()) { 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There is no Tab in |attached_tabstrip| that corresponds to the dragged 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabContents. We must now create one. 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove ourselves as the delegate now that the dragged TabContents is 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // being inserted back into a Browser. 878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents->tab_contents()->set_delegate(NULL); 880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].original_delegate = NULL; 881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return the TabContents' to normalcy. 884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_dragged_contents()->tab_contents()->set_capturing_contents(false); 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Inserting counts as a move. We don't want the tabs to jitter when the 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // user moves the tab immediately after attaching it. 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip); 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Figure out where to insert the tab based on the bounds of the dragged 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // representation and the ideal bounds of the other Tabs already in the 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // strip. ("ideal bounds" are stable even if the Tabs' actual bounds are 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // changing due to animation). 894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point tab_strip_point(screen_point); 895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_strip_point); 896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_strip_point.set_x( 897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->GetMirroredXInView(tab_strip_point.x())); 898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_strip_point.Offset(-mouse_offset_.x(), -mouse_offset_.y()); 899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect bounds = GetDraggedViewTabStripBounds(tab_strip_point); 900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index = GetInsertionIndexForDraggedBounds(bounds); 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_->set_attaching_dragged_tab(true); 902ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 903ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int add_types = TabStripModel::ADD_NONE; 904ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i].pinned) 905ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen add_types |= TabStripModel::ADD_PINNED; 906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetModel(attached_tabstrip_)->InsertTabContentsAt( 907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen index + i, drag_data_[i].contents, add_types); 908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_->set_attaching_dragged_tab(false); 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs = GetTabsMatchingDraggedContents(attached_tabstrip_); 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 913ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(tabs.size(), drag_data_.size()); 914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) 915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].attached_tab = tabs[i]; 916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->StartedDraggingTabs(tabs); 918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetSelection(GetModel(attached_tabstrip_)); 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The size of the dragged tab may have changed. Adjust the x offset so that 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ratio of mouse_offset_ to original width is maintained. 924ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs_to_source(tabs); 925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs_to_source.erase(tabs_to_source.begin() + source_tab_index_ + 1, 926ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs_to_source.end()); 927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int new_x = attached_tabstrip_->GetSizeNeededForTabs(tabs_to_source) - 928ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs[source_tab_index_]->width() + 929ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<int>(offset_to_width_ratio_ * 930ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs[source_tab_index_]->width()); 931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mouse_offset_.set_x(new_x); 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move the corresponding window to the front. 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_->GetWindow()->Activate(); 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::Detach() { 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prevent the TabContents' HWND from being hidden by any of the model 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // operations performed during the drag. 941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_dragged_contents()->tab_contents()->set_capturing_contents(true); 942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 943ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Calculate the drag bounds. 944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<gfx::Rect> drag_bounds; 945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> attached_tabs; 946ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) 947ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabs.push_back(drag_data_[i].attached_tab); 948ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->CalculateBoundsForDraggedTabs(attached_tabs, 949ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &drag_bounds); 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* attached_model = GetModel(attached_tabstrip_); 952ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<TabRendererData> tab_data; 953ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 954ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_data.push_back(drag_data_[i].attached_tab->data()); 955ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index = attached_model->GetIndexOfTabContents(drag_data_[i].contents); 956ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(-1, index); 957ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 958ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Hide the tab so that the user doesn't see it animate closed. 959ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].attached_tab->SetVisible(false); 960ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 961ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_model->DetachTabContentsAt(index); 962ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 963ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Detaching resets the delegate, but we still want to be the delegate. 964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents->tab_contents()->set_delegate(this); 965ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 966ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Detaching may end up deleting the tab, drop references to it. 967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].attached_tab = NULL; 968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we've removed the last Tab from the TabStrip, hide the frame now. 971731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (attached_model->empty()) 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HideFrame(); 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create the dragged view. 975ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CreateDraggedView(tab_data, drag_bounds); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_ = NULL; 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DraggedTabController::GetInsertionIndexForDraggedBounds( 981ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Rect& dragged_bounds) const { 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int right_tab_x = 0; 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bottom_tab_y = 0; 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index = -1; 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < attached_tabstrip_->tab_count(); ++i) { 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect left_half = ideal_bounds; 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left_half.set_width(left_half.width() / 2); 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect right_half = ideal_bounds; 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right_half.set_width(ideal_bounds.width() - left_half.width()); 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right_half.set_x(left_half.right()); 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right_tab_x = right_half.right(); 994ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (dragged_bounds.x() >= right_half.x() && 995ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragged_bounds.x() < right_half.right()) { 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = i + 1; 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (dragged_bounds.x() >= left_half.x() && 999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragged_bounds.x() < left_half.right()) { 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = i; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Vertical tab strip. 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_y = ideal_bounds.bottom(); 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int mid_y = ideal_bounds.y() + ideal_bounds.height() / 2; 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bottom_tab_y = max_y; 1008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (dragged_bounds.y() < mid_y) { 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = i; 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1011ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (dragged_bounds.y() >= mid_y && dragged_bounds.y() < max_y) { 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = i + 1; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == -1) { 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP && 1019ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragged_bounds.right() > right_tab_x) || 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (attached_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && 1021ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragged_bounds.y() >= bottom_tab_y)) { 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = GetModel(attached_tabstrip_)->count(); 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = 0; 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1028ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!drag_data_[0].attached_tab) { 1029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If 'attached_tab' is NULL, it means we're in the process of attaching and 1030ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // don't need to constrain the index. 1031ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return index; 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1033ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1034ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int max_index = GetModel(attached_tabstrip_)->count() - 1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<int>(drag_data_.size()); 1036ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return std::max(0, std::min(max_index, index)); 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect DraggedTabController::GetDraggedViewTabStripBounds( 1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Point& tab_strip_point) { 1041ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // attached_tab is NULL when inserting into a new tabstrip. 1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (source_tab_drag_data()->attached_tab) { 1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_drag_data()->attached_tab->width(), 1045ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tab_drag_data()->attached_tab->height()); 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double sel_width, unselected_width; 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<TabStrip*>(attached_tabstrip_)->GetCurrentTabWidths( 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &sel_width, &unselected_width); 1052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(sel_width), 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Tab::GetStandardSize().height()); 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch attached_tabstrip_->width(), 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SideTab::GetPreferredHeight()); 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsengfx::Point DraggedTabController::GetAttachedDragPoint( 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Point& screen_point) { 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(attached_tabstrip_); // The tab must be attached. 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point tab_loc(screen_point); 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_loc); 1068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int x = 1069ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->GetMirroredXInView(tab_loc.x()) - mouse_offset_.x(); 1070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = tab_loc.y() - mouse_offset_.y(); 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO: consider caching this. 1073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> attached_tabs; 1074ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) 1075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabs.push_back(drag_data_[i].attached_tab); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int size = attached_tabstrip_->GetSizeNeededForTabs(attached_tabs); 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { 1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int max_x = attached_tabstrip_->width() - size; 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x = std::min(std::max(x, 0), max_x); 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y = 0; 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x = SideTabStrip::kTabStripInset; 1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int max_y = attached_tabstrip_->height() - size; 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y = std::min(std::max(y, SideTabStrip::kTabStripInset), max_y); 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Point(x, y); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::vector<BaseTab*> DraggedTabController::GetTabsMatchingDraggedContents( 1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTabStrip* tabstrip) { 1093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabStripModel* model = GetModel(attached_tabstrip_); 1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs; 1095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 1096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = model->GetIndexOfTabContents(drag_data_[i].contents); 1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (model_index == TabStripModel::kNoTab) 1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return std::vector<BaseTab*>(); 1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs.push_back(tabstrip->GetBaseTabAtModelIndex(model_index)); 1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return tabs; 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::EndDragImpl(EndDragType type) { 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch active_ = false; 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bring_to_front_timer_.Stop(); 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Hide the current dock controllers. 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < dock_controllers_.size(); ++i) { 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Be sure and clear the controller first, that way if Hide ends up 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deleting the controller it won't call us back. 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_[i]->clear_controller(); 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_[i]->Hide(); 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_.clear(); 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.clear(); 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type != TAB_DESTROYED) { 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only finish up the drag if we were actually dragging. If start_drag_ 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is false, the user just clicked and released and didn't move the mouse 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // enough to trigger a drag. 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (started_drag_) { 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RestoreFocus(); 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == CANCELED) 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RevertDrag(); 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompleteDrag(); 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (drag_data_.size() > 1) { 1131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RevertDrag(); 1132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } // else case the only tab we were dragging was deleted. Nothing to do. 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetDelegates(); 1135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Clear out drag data so we don't attempt to do anything with it. 1137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_.clear(); 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_tabstrip_->DestroyDragController(); 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::RevertDrag() { 1143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> tabs; 1144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 1145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i].contents) { 1146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Contents is NULL if a tab was destroyed while the drag was under way. 1147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tabs.push_back(drag_data_[i].attached_tab); 1148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RevertDragAt(i); 1149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool restore_frame = attached_tabstrip_ != source_tabstrip_; 1153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (attached_tabstrip_ && attached_tabstrip_ == source_tabstrip_) 1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_tabstrip_->StoppedDraggingTabs(tabs); 1155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_ = source_tabstrip_; 1157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetSelection(GetModel(attached_tabstrip_)); 1159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we're not attached to any TabStrip, or attached to some other TabStrip, 1161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // we need to restore the bounds of the original TabStrip's frame, in case 1162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // it has been hidden. 1163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (restore_frame) { 1164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!restore_bounds_.IsEmpty()) { 1165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 1166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HWND frame_hwnd = source_tabstrip_->GetWidget()->GetNativeView(); 1167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MoveWindow(frame_hwnd, restore_bounds_.x(), restore_bounds_.y(), 1168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen restore_bounds_.width(), restore_bounds_.height(), TRUE); 1169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 1170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTIMPLEMENTED(); 1171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 1172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::ResetSelection(TabStripModel* model) { 1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(model); 1178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabStripSelectionModel selection_model; 1179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_one_valid_tab = false; 1180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 1181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |contents| is NULL if a tab was deleted out from under us. 1182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i].contents) { 1183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index = model->GetIndexOfTabContents(drag_data_[i].contents); 1184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(-1, index); 1185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen selection_model.AddIndexToSelection(index); 1186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!has_one_valid_tab || i == source_tab_index_) { 1187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Reset the active/lead to the first tab. If the source tab is still 1188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // valid we'll reset these again later on. 1189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen selection_model.set_active(index); 1190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen selection_model.set_anchor(index); 1191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen has_one_valid_tab = true; 1192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!has_one_valid_tab) 1196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 1197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model->SetSelectionFromModel(selection_model); 1199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::RevertDragAt(size_t drag_index) { 1202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(started_drag_); 1203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabDragData* data = &(drag_data_[drag_index]); 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_) { 1206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index = 1207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetModel(attached_tabstrip_)->GetIndexOfTabContents(data->contents); 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_ != source_tabstrip_) { 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The Tab was inserted into another TabStrip. We need to put it back 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // into the original one. 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModel(attached_tabstrip_)->DetachTabContentsAt(index); 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(beng): (Cleanup) seems like we should use Attach() for this 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // somehow. 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModel(source_tabstrip_)->InsertTabContentsAt( 1215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data->source_model_index, data->contents, 1216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (data->pinned ? TabStripModel::ADD_PINNED : 0)); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The Tab was moved within the TabStrip where the drag was initiated. 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move it back to the starting location. 1220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetModel(source_tabstrip_)->MoveTabContentsAt( 1221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen index, data->source_model_index, false); 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The Tab was detached from the TabStrip where the drag began, and has not 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // been attached to any other TabStrip. We need to put it back into the 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // source TabStrip. 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModel(source_tabstrip_)->InsertTabContentsAt( 1228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data->source_model_index, data->contents, 1229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (data->pinned ? TabStripModel::ADD_PINNED : 0)); 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::CompleteDrag() { 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(started_drag_); 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (attached_tabstrip_) { 1237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen attached_tabstrip_->StoppedDraggingTabs( 1238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetTabsMatchingDraggedContents(attached_tabstrip_)); 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dock_info_.type() != DockInfo::NONE) { 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = GetModel(source_tabstrip_)->profile(); 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (dock_info_.type()) { 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::LEFT_OF_WINDOW: 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Left"), 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::RIGHT_OF_WINDOW: 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Right"), 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::BOTTOM_OF_WINDOW: 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Bottom"), 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::TOP_OF_WINDOW: 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Top"), 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::MAXIMIZE: 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Maximize"), 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::LEFT_HALF: 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction(UserMetricsAction("DockingWindow_LeftHalf"), 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::RIGHT_HALF: 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction( 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetricsAction("DockingWindow_RightHalf"), 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DockInfo::BOTTOM_HALF: 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordAction( 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetricsAction("DockingWindow_BottomHalf"), 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compel the model to construct a new window for the detached TabContents. 12913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick views::Window* window = source_tabstrip_->GetWindow(); 12923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gfx::Rect window_bounds(window->GetNormalBounds()); 12933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick window_bounds.set_origin(GetWindowCreatePoint()); 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When modifying the following if statement, please make sure not to 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // introduce issue listed in http://crbug.com/6223 comment #11. 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool rtl_ui = base::i18n::IsRTL(); 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_dock_position = (dock_info_.type() != DockInfo::NONE); 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rtl_ui && has_dock_position) { 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Mirror X axis so the docked tab is aligned using the mouse click as 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the top-right corner. 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_bounds.set_x(window_bounds.x() - window_bounds.width()); 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* new_browser = 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModel(source_tabstrip_)->delegate()->CreateNewStripWithContents( 1305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[0].contents, window_bounds, dock_info_, 1306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window->IsMaximized()); 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* new_model = new_browser->tabstrip_model(); 1308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_model->SetTabPinned( 1309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_model->GetIndexOfTabContents(drag_data_[0].contents), 1310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[0].pinned); 1311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 1; i < drag_data_.size(); ++i) { 1312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_model->InsertTabContentsAt( 1313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<int>(i), 1314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents, 1315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].pinned ? TabStripModel::ADD_PINNED : 1316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabStripModel::ADD_NONE); 1317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetSelection(new_browser->tabstrip_model()); 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_browser->window()->Show(); 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CleanUpHiddenFrame(); 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::ResetDelegates() { 1326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 1327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i].contents && 1328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents->tab_contents()->delegate() == this) { 1329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].contents->tab_contents()->set_delegate( 1330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].original_delegate); 1331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DraggedTabController::CreateDraggedView( 1336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<TabRendererData>& data, 1337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<gfx::Rect>& renderer_bounds) { 1338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!view_.get()); 1339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(data.size(), drag_data_.size()); 1340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set up the photo booth to start capturing the contents of the dragged 1342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TabContents. 1343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NativeViewPhotobooth* photobooth = 1344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NativeViewPhotobooth::Create( 1345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_dragged_contents()->tab_contents()->GetNativeView()); 1346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect content_bounds; 1348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen source_dragged_contents()->tab_contents()->GetContainerBounds( 1349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &content_bounds); 1350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<views::View*> renderers; 1352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < drag_data_.size(); ++i) { 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* renderer = source_tabstrip_->CreateTabForDragging(); 1354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen renderer->SetData(data[i]); 1355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen renderers.push_back(renderer); 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // DraggedTabView takes ownership of the renderers. 1358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen view_.reset(new DraggedTabView(renderers, renderer_bounds, mouse_offset_, 1359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen content_bounds.size(), photobooth)); 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point DraggedTabController::GetCursorScreenPoint() const { 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD pos = GetMessagePos(); 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Point(pos); 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint x, y; 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_display_get_pointer(gdk_display_get_default(), NULL, &x, &y, NULL); 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Point(x, y); 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect DraggedTabController::GetViewScreenBounds(views::View* view) const { 1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point view_topleft; 1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::View::ConvertPointToScreen(view, &view_topleft); 137672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::Rect view_screen_bounds = view->GetLocalBounds(); 1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch view_screen_bounds.Offset(view_topleft.x(), view_topleft.y()); 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return view_screen_bounds; 1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::HideFrame() { 1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 1383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't actually hide the window, rather we just move it way off-screen. 1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we actually hide it, we stop receiving drag events. 1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND frame_hwnd = source_tabstrip_->GetWidget()->GetNativeView(); 1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RECT wr; 1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindowRect(frame_hwnd, &wr); 1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MoveWindow(frame_hwnd, 0xFFFF, 0xFFFF, wr.right - wr.left, 1389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wr.bottom - wr.top, TRUE); 1390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We also save the bounds of the window prior to it being moved, so that if 1392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the drag session is aborted we can restore them. 1393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch restore_bounds_ = gfx::Rect(wr); 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::CleanUpHiddenFrame() { 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the model we started dragging from is now empty, we must ask the 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // delegate to close the frame. 1402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (GetModel(source_tabstrip_)->empty()) 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModel(source_tabstrip_)->delegate()->CloseFrameAfterDragSession(); 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::DockDisplayerDestroyed( 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockDisplayer* controller) { 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DockWindows::iterator dock_i = 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.find(controller->popup_view()); 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dock_i != dock_windows_.end()) 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.erase(dock_i); 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<DockDisplayer*>::iterator i = 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::find(dock_controllers_.begin(), dock_controllers_.end(), 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller); 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i != dock_controllers_.end()) 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_controllers_.erase(i); 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DraggedTabController::BringWindowUnderMouseToFront() { 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're going to dock to another window, bring it to the front. 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeWindow window = dock_info_.window(); 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!window) { 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView dragged_view = view_->GetWidget()->GetNativeView(); 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.insert(dragged_view); 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window = DockInfo::GetLocalProcessWindowAtPoint(GetCursorScreenPoint(), 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_); 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dock_windows_.erase(dragged_view); 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window) { 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move the window to the front. 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The previous call made the window appear on top of the dragged window, 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // move the dragged window to the front. 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetWindowPos(view_->GetWidget()->GetNativeView(), HWND_TOP, 0, 0, 0, 0, 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabStripModel* DraggedTabController::GetModel(BaseTabStrip* tabstrip) const { 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<BrowserTabStripController*>(tabstrip->controller())-> 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model(); 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DraggedTabController::AreTabsConsecutive() { 1456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 1; i < drag_data_.size(); ++i) { 1457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (drag_data_[i - 1].source_model_index + 1 != 1458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_data_[i].source_model_index) { 1459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 1460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 1463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1464