| Index: chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
|
| deleted file mode 100644
|
| index 4aa07393b0d4561ec3824146ff989fb1e6c3f474..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.cc
|
| +++ /dev/null
|
| @@ -1,898 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "chrome/browser/chrome_notification_types.h"
|
| -#include "chrome/browser/platform_util.h"
|
| -#include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/gtk/browser_window_gtk.h"
|
| -#include "chrome/browser/ui/gtk/gtk_util.h"
|
| -#include "chrome/browser/ui/gtk/tabs/dragged_view_gtk.h"
|
| -#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
|
| -#include "chrome/browser/ui/gtk/tabs/window_finder.h"
|
| -#include "chrome/browser/ui/media_utils.h"
|
| -#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| -#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
|
| -#include "content/public/browser/notification_source.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "content/public/browser/web_contents_view.h"
|
| -#include "ui/base/gtk/gtk_screen_util.h"
|
| -#include "ui/gfx/screen.h"
|
| -
|
| -using content::OpenURLParams;
|
| -using content::WebContents;
|
| -
|
| -namespace {
|
| -
|
| -// Delay, in ms, during dragging before we bring a window to front.
|
| -const int kBringToFrontDelay = 750;
|
| -
|
| -// Used to determine how far a tab must obscure another tab in order to swap
|
| -// their indexes.
|
| -const int kHorizontalMoveThreshold = 16; // pixels
|
| -
|
| -// How far a drag must pull a tab out of the tabstrip in order to detach it.
|
| -const int kVerticalDetachMagnetism = 15; // pixels
|
| -
|
| -// Returns the bounds that will be used for insertion index calculation.
|
| -// |bounds| is the actual tab bounds, but subtracting the overlapping areas from
|
| -// both sides makes the calculations much simpler.
|
| -gfx::Rect GetEffectiveBounds(const gfx::Rect& bounds) {
|
| - gfx::Rect effective_bounds(bounds);
|
| - effective_bounds.set_width(effective_bounds.width() - 2 * 16);
|
| - effective_bounds.set_x(effective_bounds.x() + 16);
|
| - return effective_bounds;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -DraggedTabControllerGtk::DraggedTabControllerGtk(
|
| - TabStripGtk* source_tabstrip,
|
| - TabGtk* source_tab,
|
| - const std::vector<TabGtk*>& tabs)
|
| - : source_tabstrip_(source_tabstrip),
|
| - attached_tabstrip_(source_tabstrip),
|
| - in_destructor_(false),
|
| - last_move_screen_x_(0),
|
| - initial_move_(true) {
|
| - DCHECK(!tabs.empty());
|
| - DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end());
|
| -
|
| - std::vector<DraggedTabData> drag_data;
|
| - for (size_t i = 0; i < tabs.size(); i++)
|
| - drag_data.push_back(InitDraggedTabData(tabs[i]));
|
| -
|
| - int source_tab_index =
|
| - std::find(tabs.begin(), tabs.end(), source_tab) - tabs.begin();
|
| - drag_data_.reset(new DragData(drag_data, source_tab_index));
|
| -}
|
| -
|
| -DraggedTabControllerGtk::~DraggedTabControllerGtk() {
|
| - in_destructor_ = true;
|
| - // Need to delete the dragged tab here manually _before_ we reset the dragged
|
| - // contents to NULL, otherwise if the view is animating to its destination
|
| - // bounds, it won't be able to clean up properly since its cleanup routine
|
| - // uses GetIndexForDraggedContents, which will be invalid.
|
| - CleanUpDraggedTabs();
|
| - dragged_view_.reset();
|
| - drag_data_.reset();
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::CaptureDragInfo(const gfx::Point& mouse_offset) {
|
| - start_screen_point_ = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
|
| - mouse_offset_ = mouse_offset;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::Drag() {
|
| - if (!drag_data_->GetSourceTabData()->tab_ ||
|
| - !drag_data_->GetSourceWebContents()) {
|
| - return;
|
| - }
|
| -
|
| - bring_to_front_timer_.Stop();
|
| -
|
| - EnsureDraggedView();
|
| -
|
| - // Before we get to dragging anywhere, ensure that we consider ourselves
|
| - // attached to the source tabstrip.
|
| - if (drag_data_->GetSourceTabData()->tab_->IsVisible()) {
|
| - Attach(source_tabstrip_, gfx::Point());
|
| - }
|
| -
|
| - if (!drag_data_->GetSourceTabData()->tab_->IsVisible()) {
|
| - // TODO(jhawkins): Save focus.
|
| - ContinueDragging();
|
| - }
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::EndDrag(bool canceled) {
|
| - return EndDragImpl(canceled ? CANCELED : NORMAL);
|
| -}
|
| -
|
| -TabGtk* DraggedTabControllerGtk::GetDraggedTabForContents(
|
| - WebContents* contents) {
|
| - if (attached_tabstrip_ == source_tabstrip_) {
|
| - for (size_t i = 0; i < drag_data_->size(); i++) {
|
| - if (contents == drag_data_->get(i)->contents_)
|
| - return drag_data_->get(i)->tab_;
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::IsDraggingTab(const TabGtk* tab) {
|
| - for (size_t i = 0; i < drag_data_->size(); i++) {
|
| - if (tab == drag_data_->get(i)->tab_)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::IsDraggingWebContents(
|
| - const WebContents* web_contents) {
|
| - for (size_t i = 0; i < drag_data_->size(); i++) {
|
| - if (web_contents == drag_data_->get(i)->contents_)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::IsTabDetached(const TabGtk* tab) {
|
| - return IsDraggingTab(tab) && attached_tabstrip_ == NULL;
|
| -}
|
| -
|
| -DraggedTabData DraggedTabControllerGtk::InitDraggedTabData(TabGtk* tab) {
|
| - int source_model_index = source_tabstrip_->GetIndexOfTab(tab);
|
| - WebContents* contents =
|
| - source_tabstrip_->model()->GetWebContentsAt(source_model_index);
|
| - bool pinned = source_tabstrip_->IsTabPinned(tab);
|
| - bool mini = source_tabstrip_->model()->IsMiniTab(source_model_index);
|
| - // We need to be the delegate so we receive messages about stuff,
|
| - // otherwise our dragged_contents() may be replaced and subsequently
|
| - // collected/destroyed while the drag is in process, leading to
|
| - // nasty crashes.
|
| - content::WebContentsDelegate* original_delegate = contents->GetDelegate();
|
| - contents->SetDelegate(this);
|
| -
|
| - DraggedTabData dragged_tab_data(tab, contents, original_delegate,
|
| - source_model_index, pinned, mini);
|
| - registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| - content::Source<WebContents>(contents));
|
| - return dragged_tab_data;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// DraggedTabControllerGtk, content::WebContentsDelegate implementation:
|
| -
|
| -WebContents* DraggedTabControllerGtk::OpenURLFromTab(
|
| - WebContents* source,
|
| - const OpenURLParams& params) {
|
| - if (drag_data_->GetSourceTabData()->original_delegate_) {
|
| - OpenURLParams forward_params = params;
|
| - if (params.disposition == CURRENT_TAB)
|
| - forward_params.disposition = NEW_WINDOW;
|
| -
|
| - return drag_data_->GetSourceTabData()->original_delegate_->
|
| - OpenURLFromTab(source, forward_params);
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::NavigationStateChanged(const WebContents* source,
|
| - unsigned changed_flags) {
|
| - if (dragged_view_.get())
|
| - dragged_view_->Update();
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::AddNewContents(WebContents* source,
|
| - WebContents* new_contents,
|
| - WindowOpenDisposition disposition,
|
| - const gfx::Rect& initial_pos,
|
| - bool user_gesture,
|
| - bool* was_blocked) {
|
| - DCHECK(disposition != CURRENT_TAB);
|
| -
|
| - // Theoretically could be called while dragging if the page tries to
|
| - // spawn a window. Route this message back to the browser in most cases.
|
| - if (drag_data_->GetSourceTabData()->original_delegate_) {
|
| - drag_data_->GetSourceTabData()->original_delegate_->AddNewContents(
|
| - source, new_contents, disposition, initial_pos, user_gesture,
|
| - was_blocked);
|
| - }
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::LoadingStateChanged(WebContents* source,
|
| - bool to_different_document) {
|
| - // TODO(jhawkins): It would be nice to respond to this message by changing the
|
| - // screen shot in the dragged tab.
|
| - if (dragged_view_.get())
|
| - dragged_view_->Update();
|
| -}
|
| -
|
| -content::JavaScriptDialogManager*
|
| -DraggedTabControllerGtk::GetJavaScriptDialogManager() {
|
| - return GetJavaScriptDialogManagerInstance();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// DraggedTabControllerGtk, content::NotificationObserver implementation:
|
| -
|
| -void DraggedTabControllerGtk::Observe(
|
| - int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, type);
|
| - WebContents* destroyed_web_contents =
|
| - content::Source<WebContents>(source).ptr();
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (drag_data_->get(i)->contents_ == destroyed_web_contents) {
|
| - // One of the tabs we're dragging has been destroyed. Cancel the drag.
|
| - if (destroyed_web_contents->GetDelegate() == this)
|
| - destroyed_web_contents->SetDelegate(NULL);
|
| - drag_data_->get(i)->contents_ = NULL;
|
| - drag_data_->get(i)->original_delegate_ = NULL;
|
| - EndDragImpl(TAB_DESTROYED);
|
| - return;
|
| - }
|
| - }
|
| - // If we get here it means we got notification for a tab we don't know about.
|
| - NOTREACHED();
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::RequestMediaAccessPermission(
|
| - content::WebContents* web_contents,
|
| - const content::MediaStreamRequest& request,
|
| - const content::MediaResponseCallback& callback) {
|
| - ::RequestMediaAccessPermission(
|
| - web_contents,
|
| - Profile::FromBrowserContext(web_contents->GetBrowserContext()),
|
| - request,
|
| - callback);
|
| -}
|
| -
|
| -gfx::Point DraggedTabControllerGtk::GetWindowCreatePoint() const {
|
| - gfx::Point creation_point =
|
| - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
|
| - gfx::Point distance_from_origin =
|
| - dragged_view_->GetDistanceFromTabStripOriginToMousePointer();
|
| - // TODO(dpapad): offset also because of tabstrip origin being different than
|
| - // window origin.
|
| - creation_point.Offset(-distance_from_origin.x(), -distance_from_origin.y());
|
| - return creation_point;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::ContinueDragging() {
|
| - // TODO(jhawkins): We don't handle the situation where the last tab is dragged
|
| - // out of a window, so we'll just go with the way Windows handles dragging for
|
| - // now.
|
| - gfx::Point screen_point =
|
| - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
|
| -
|
| - // Determine whether or not we have dragged over a compatible TabStrip in
|
| - // another browser window. If we have, we should attach to it and start
|
| - // dragging within it.
|
| - TabStripGtk* target_tabstrip = GetTabStripForPoint(screen_point);
|
| - if (target_tabstrip != attached_tabstrip_) {
|
| - // Make sure we're fully detached from whatever TabStrip we're attached to
|
| - // (if any).
|
| - if (attached_tabstrip_)
|
| - Detach();
|
| -
|
| - if (target_tabstrip)
|
| - Attach(target_tabstrip, screen_point);
|
| - }
|
| -
|
| - if (!target_tabstrip) {
|
| - bring_to_front_timer_.Start(FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this,
|
| - &DraggedTabControllerGtk::BringWindowUnderMouseToFront);
|
| - }
|
| -
|
| - if (attached_tabstrip_)
|
| - MoveAttached(screen_point);
|
| - else
|
| - MoveDetached(screen_point);
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::RestoreSelection(TabStripModel* model) {
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - WebContents* contents = drag_data_->get(i)->contents_;
|
| - // If a tab is destroyed while dragging contents might be null. See
|
| - // http://crbug.com/115409.
|
| - if (contents) {
|
| - int index = model->GetIndexOfWebContents(contents);
|
| - CHECK(index != TabStripModel::kNoTab);
|
| - model->AddTabAtToSelection(index);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::MoveAttached(const gfx::Point& screen_point) {
|
| - DCHECK(attached_tabstrip_);
|
| -
|
| - gfx::Point dragged_view_point = GetDraggedViewPoint(screen_point);
|
| - TabStripModel* attached_model = attached_tabstrip_->model();
|
| -
|
| - std::vector<TabGtk*> tabs(drag_data_->GetDraggedTabs());
|
| -
|
| - // Determine the horizontal move threshold. This is dependent on the width
|
| - // of tabs. The smaller the tabs compared to the standard size, the smaller
|
| - // the threshold.
|
| - double unselected, selected;
|
| - attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
|
| - double ratio = unselected / TabGtk::GetStandardSize().width();
|
| - int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold);
|
| -
|
| - // Update the model, moving the WebContents from one index to another.
|
| - // Do this only if we have moved a minimum distance since the last reorder (to
|
| - // prevent jitter) or if this is the first move and the tabs are not
|
| - // consecutive.
|
| - if (abs(screen_point.x() - last_move_screen_x_) > threshold ||
|
| - (initial_move_ && !AreTabsConsecutive())) {
|
| - if (initial_move_ && !AreTabsConsecutive()) {
|
| - // Making dragged tabs adjacent, this is done only once, if necessary.
|
| - attached_tabstrip_->model()->MoveSelectedTabsTo(
|
| - drag_data_->GetSourceTabData()->source_model_index_ -
|
| - drag_data_->source_tab_index());
|
| - }
|
| - gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point);
|
| - int to_index = GetInsertionIndexForDraggedBounds(
|
| - GetEffectiveBounds(bounds));
|
| - to_index = NormalizeIndexToAttachedTabStrip(to_index);
|
| - last_move_screen_x_ = screen_point.x();
|
| - attached_model->MoveSelectedTabsTo(to_index);
|
| - }
|
| -
|
| - dragged_view_->MoveAttachedTo(dragged_view_point);
|
| - initial_move_ = false;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::MoveDetached(const gfx::Point& screen_point) {
|
| - DCHECK(!attached_tabstrip_);
|
| - // Just moving the dragged view. There are no changes to the model if we're
|
| - // detached.
|
| - dragged_view_->MoveDetachedTo(screen_point);
|
| -}
|
| -
|
| -TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint(
|
| - const gfx::Point& screen_point) {
|
| - gfx::NativeWindow local_window = GetLocalProcessWindow(screen_point);
|
| - if (!local_window)
|
| - return NULL;
|
| -
|
| - BrowserWindowGtk* browser =
|
| - BrowserWindowGtk::GetBrowserWindowForNativeWindow(local_window);
|
| - if (!browser)
|
| - return NULL;
|
| -
|
| - TabStripGtk* other_tabstrip = browser->tabstrip();
|
| - if (!other_tabstrip->IsCompatibleWith(source_tabstrip_))
|
| - return NULL;
|
| -
|
| - return GetTabStripIfItContains(other_tabstrip, screen_point);
|
| -}
|
| -
|
| -TabStripGtk* DraggedTabControllerGtk::GetTabStripIfItContains(
|
| - TabStripGtk* tabstrip, const gfx::Point& screen_point) const {
|
| - // Make sure the specified screen point is actually within the bounds of the
|
| - // specified tabstrip...
|
| - gfx::Rect tabstrip_bounds =
|
| - ui::GetWidgetScreenBounds(tabstrip->tabstrip_.get());
|
| - if (screen_point.x() < tabstrip_bounds.right() &&
|
| - screen_point.x() >= tabstrip_bounds.x()) {
|
| - // TODO(beng): make this be relative to the start position of the mouse for
|
| - // the source TabStrip.
|
| - int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism;
|
| - int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism;
|
| - if (screen_point.y() >= lower_threshold &&
|
| - screen_point.y() <= upper_threshold) {
|
| - return tabstrip;
|
| - }
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::Attach(TabStripGtk* attached_tabstrip,
|
| - const gfx::Point& screen_point) {
|
| - attached_tabstrip_ = attached_tabstrip;
|
| - attached_tabstrip_->GenerateIdealBounds();
|
| -
|
| - std::vector<TabGtk*> attached_dragged_tabs =
|
| - GetTabsMatchingDraggedContents(attached_tabstrip_);
|
| -
|
| - // Update the tab first, so we can ask it for its bounds and determine
|
| - // where to insert the hidden tab.
|
| -
|
| - // If this is the first time Attach is called for this drag, we're attaching
|
| - // to the source tabstrip, and we should assume the tab count already
|
| - // includes this tab since we haven't been detached yet. If we don't do this,
|
| - // the dragged representation will be a different size to others in the
|
| - // tabstrip.
|
| - int tab_count = attached_tabstrip_->GetTabCount();
|
| - int mini_tab_count = attached_tabstrip_->GetMiniTabCount();
|
| - if (attached_dragged_tabs.size() == 0) {
|
| - tab_count += drag_data_->size();
|
| - mini_tab_count += drag_data_->mini_tab_count();
|
| - }
|
| -
|
| - double unselected_width = 0, selected_width = 0;
|
| - attached_tabstrip_->GetDesiredTabWidths(tab_count, mini_tab_count,
|
| - &unselected_width, &selected_width);
|
| -
|
| - GtkWidget* parent_window = gtk_widget_get_parent(
|
| - gtk_widget_get_parent(attached_tabstrip_->tabstrip_.get()));
|
| - gfx::Rect window_bounds = ui::GetWidgetScreenBounds(parent_window);
|
| - dragged_view_->Attach(static_cast<int>(floor(selected_width + 0.5)),
|
| - TabGtk::GetMiniWidth(), window_bounds.width());
|
| -
|
| - if (attached_dragged_tabs.size() == 0) {
|
| - // There is no tab in |attached_tabstrip| that corresponds to the dragged
|
| - // WebContents. We must now create one.
|
| -
|
| - // Remove ourselves as the delegate now that the dragged WebContents
|
| - // is being inserted back into a Browser.
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - drag_data_->get(i)->contents_->SetDelegate(NULL);
|
| - drag_data_->get(i)->original_delegate_ = NULL;
|
| - }
|
| -
|
| - // We need to ask the tabstrip we're attached to ensure that the ideal
|
| - // bounds for all its tabs are correctly generated, because the calculation
|
| - // in GetInsertionIndexForDraggedBounds needs them to be to figure out the
|
| - // appropriate insertion index.
|
| - attached_tabstrip_->GenerateIdealBounds();
|
| -
|
| - // Inserting counts as a move. We don't want the tabs to jitter when the
|
| - // user moves the tab immediately after attaching it.
|
| - last_move_screen_x_ = screen_point.x();
|
| -
|
| - // Figure out where to insert the tab based on the bounds of the dragged
|
| - // representation and the ideal bounds of the other tabs already in the
|
| - // strip. ("ideal bounds" are stable even if the tabs' actual bounds are
|
| - // changing due to animation).
|
| - gfx::Rect bounds =
|
| - GetDraggedViewTabStripBounds(GetDraggedViewPoint(screen_point));
|
| - int index = GetInsertionIndexForDraggedBounds(GetEffectiveBounds(bounds));
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - attached_tabstrip_->model()->InsertWebContentsAt(
|
| - index + i, drag_data_->get(i)->contents_,
|
| - drag_data_->GetAddTypesForDraggedTabAt(i));
|
| - }
|
| - RestoreSelection(attached_tabstrip_->model());
|
| - attached_dragged_tabs = GetTabsMatchingDraggedContents(attached_tabstrip_);
|
| - }
|
| - // We should now have a tab.
|
| - DCHECK(attached_dragged_tabs.size() == drag_data_->size());
|
| - SetDraggedTabsVisible(false, false);
|
| - // TODO(jhawkins): Move the corresponding window to the front.
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::Detach() {
|
| - // Update the Model.
|
| - TabStripModel* attached_model = attached_tabstrip_->model();
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - int index =
|
| - attached_model->GetIndexOfWebContents(drag_data_->get(i)->contents_);
|
| - if (index >= 0 && index < attached_model->count()) {
|
| - // Sometimes, DetachWebContentsAt has consequences that result in
|
| - // attached_tabstrip_ being set to NULL, so we need to save it first.
|
| - attached_model->DetachWebContentsAt(index);
|
| - }
|
| - }
|
| -
|
| - // If we've removed the last tab from the tabstrip, hide the frame now.
|
| - if (attached_model->empty())
|
| - HideWindow();
|
| -
|
| - // Update the dragged tab. This NULL check is necessary apparently in some
|
| - // conditions during automation where the view_ is destroyed inside a
|
| - // function call preceding this point but after it is created.
|
| - if (dragged_view_.get()) {
|
| - dragged_view_->Detach();
|
| - }
|
| -
|
| - // Detaching resets the delegate, but we still want to be the delegate.
|
| - for (size_t i = 0; i < drag_data_->size(); ++i)
|
| - drag_data_->get(i)->contents_->SetDelegate(this);
|
| -
|
| - attached_tabstrip_ = NULL;
|
| -}
|
| -
|
| -gfx::Point DraggedTabControllerGtk::ConvertScreenPointToTabStripPoint(
|
| - TabStripGtk* tabstrip, const gfx::Point& screen_point) {
|
| - return screen_point - ui::GetWidgetScreenOffset(tabstrip->tabstrip_.get());
|
| -}
|
| -
|
| -gfx::Rect DraggedTabControllerGtk::GetDraggedViewTabStripBounds(
|
| - const gfx::Point& screen_point) {
|
| - gfx::Point client_point =
|
| - ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point);
|
| - gfx::Size tab_size = dragged_view_->attached_tab_size();
|
| - return gfx::Rect(client_point.x(), client_point.y(),
|
| - dragged_view_->GetTotalWidthInTabStrip(), tab_size.height());
|
| -}
|
| -
|
| -int DraggedTabControllerGtk::GetInsertionIndexForDraggedBounds(
|
| - const gfx::Rect& dragged_bounds) {
|
| - int dragged_bounds_start = gtk_util::MirroredLeftPointForRect(
|
| - attached_tabstrip_->widget(),
|
| - dragged_bounds);
|
| - int dragged_bounds_end = gtk_util::MirroredRightPointForRect(
|
| - attached_tabstrip_->widget(),
|
| - dragged_bounds);
|
| - int right_tab_x = 0;
|
| - int index = -1;
|
| -
|
| - for (int i = 0; i < attached_tabstrip_->GetTabCount(); i++) {
|
| - // Divides each tab into two halves to see if the dragged tab has crossed
|
| - // the halfway boundary necessary to move past the next tab.
|
| - gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i);
|
| - gfx::Rect left_half, right_half;
|
| - ideal_bounds.SplitVertically(&left_half, &right_half);
|
| - right_tab_x = right_half.x();
|
| -
|
| - if (dragged_bounds_start >= right_half.x() &&
|
| - dragged_bounds_start < right_half.right()) {
|
| - index = i + 1;
|
| - break;
|
| - } else if (dragged_bounds_start >= left_half.x() &&
|
| - dragged_bounds_start < left_half.right()) {
|
| - index = i;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (index == -1) {
|
| - if (dragged_bounds_end > right_tab_x)
|
| - index = attached_tabstrip_->GetTabCount();
|
| - else
|
| - index = 0;
|
| - }
|
| -
|
| - TabGtk* tab = GetTabMatchingDraggedContents(
|
| - attached_tabstrip_, drag_data_->GetSourceWebContents());
|
| - if (tab == NULL) {
|
| - // If dragged tabs are not attached yet, we don't need to constrain the
|
| - // index.
|
| - return index;
|
| - }
|
| -
|
| - int max_index =
|
| - attached_tabstrip_-> GetTabCount() - static_cast<int>(drag_data_->size());
|
| - return std::max(0, std::min(max_index, index));
|
| -}
|
| -
|
| -gfx::Point DraggedTabControllerGtk::GetDraggedViewPoint(
|
| - const gfx::Point& screen_point) {
|
| - int x = screen_point.x() -
|
| - dragged_view_->GetWidthInTabStripUpToMousePointer();
|
| - int y = screen_point.y() - mouse_offset_.y();
|
| -
|
| - // If we're not attached, we just use x and y from above.
|
| - if (attached_tabstrip_) {
|
| - gfx::Rect tabstrip_bounds =
|
| - ui::GetWidgetScreenBounds(attached_tabstrip_->tabstrip_.get());
|
| - // Snap the dragged tab to the tabstrip if we are attached, detaching
|
| - // only when the mouse position (screen_point) exceeds the screen bounds
|
| - // of the tabstrip.
|
| - if (x < tabstrip_bounds.x() && screen_point.x() >= tabstrip_bounds.x())
|
| - x = tabstrip_bounds.x();
|
| -
|
| - gfx::Size tab_size = dragged_view_->attached_tab_size();
|
| - int vertical_drag_magnetism = tab_size.height() * 2;
|
| - int vertical_detach_point = tabstrip_bounds.y() - vertical_drag_magnetism;
|
| - if (y < tabstrip_bounds.y() && screen_point.y() >= vertical_detach_point)
|
| - y = tabstrip_bounds.y();
|
| -
|
| - // Make sure the tab can't be dragged off the right side of the tabstrip
|
| - // unless the mouse pointer passes outside the bounds of the strip by
|
| - // clamping the position of the dragged window to the tabstrip width less
|
| - // the width of one tab until the mouse pointer (screen_point) exceeds the
|
| - // screen bounds of the tabstrip.
|
| - int max_x =
|
| - tabstrip_bounds.right() - dragged_view_->GetTotalWidthInTabStrip();
|
| - int max_y = tabstrip_bounds.bottom() - tab_size.height();
|
| - if (x > max_x && screen_point.x() <= tabstrip_bounds.right())
|
| - x = max_x;
|
| - if (y > max_y && screen_point.y() <=
|
| - (tabstrip_bounds.bottom() + vertical_drag_magnetism)) {
|
| - y = max_y;
|
| - }
|
| - }
|
| - return gfx::Point(x, y);
|
| -}
|
| -
|
| -int DraggedTabControllerGtk::NormalizeIndexToAttachedTabStrip(int index) const {
|
| - if (index >= attached_tabstrip_->model_->count())
|
| - return attached_tabstrip_->model_->count() - 1;
|
| - if (index == TabStripModel::kNoTab)
|
| - return 0;
|
| - return index;
|
| -}
|
| -
|
| -TabGtk* DraggedTabControllerGtk::GetTabMatchingDraggedContents(
|
| - TabStripGtk* tabstrip, WebContents* web_contents) {
|
| - int index = tabstrip->model()->GetIndexOfWebContents(web_contents);
|
| - return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index);
|
| -}
|
| -
|
| -std::vector<TabGtk*> DraggedTabControllerGtk::GetTabsMatchingDraggedContents(
|
| - TabStripGtk* tabstrip) {
|
| - std::vector<TabGtk*> dragged_tabs;
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (!drag_data_->get(i)->contents_)
|
| - continue;
|
| - TabGtk* tab = GetTabMatchingDraggedContents(tabstrip,
|
| - drag_data_->get(i)->contents_);
|
| - if (tab)
|
| - dragged_tabs.push_back(tab);
|
| - }
|
| - return dragged_tabs;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::SetDraggedTabsVisible(bool visible,
|
| - bool repaint) {
|
| - std::vector<TabGtk*> dragged_tabs(GetTabsMatchingDraggedContents(
|
| - attached_tabstrip_));
|
| - for (size_t i = 0; i < dragged_tabs.size(); ++i) {
|
| - dragged_tabs[i]->SetVisible(visible);
|
| - dragged_tabs[i]->set_dragging(!visible);
|
| - if (repaint)
|
| - dragged_tabs[i]->SchedulePaint();
|
| - }
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::EndDragImpl(EndDragType type) {
|
| - bring_to_front_timer_.Stop();
|
| -
|
| - // WARNING: this may be invoked multiple times. In particular, if deletion
|
| - // occurs after a delay (as it does when the tab is released in the original
|
| - // tab strip) and the navigation controller/tab contents is deleted before
|
| - // the animation finishes, this is invoked twice. The second time through
|
| - // type == TAB_DESTROYED.
|
| -
|
| - bool destroy_now = true;
|
| - if (type != TAB_DESTROYED) {
|
| - // If we never received a drag-motion event, the drag will never have
|
| - // started in the sense that |dragged_view_| will be NULL. We don't need to
|
| - // revert or complete the drag in that case.
|
| - if (dragged_view_.get()) {
|
| - if (type == CANCELED) {
|
| - RevertDrag();
|
| - } else {
|
| - destroy_now = CompleteDrag();
|
| - }
|
| - }
|
| - } else if (drag_data_->size() > 0) {
|
| - RevertDrag();
|
| - }
|
| -
|
| - ResetDelegates();
|
| -
|
| - // If we're not destroyed now, we'll be destroyed asynchronously later.
|
| - if (destroy_now)
|
| - source_tabstrip_->DestroyDragController();
|
| -
|
| - return destroy_now;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::RevertDrag() {
|
| - // We save this here because code below will modify |attached_tabstrip_|.
|
| - bool restore_window = attached_tabstrip_ != source_tabstrip_;
|
| - if (attached_tabstrip_) {
|
| - if (attached_tabstrip_ != source_tabstrip_) {
|
| - // The tabs were inserted into another tabstrip. We need to put them back
|
| - // into the original one.
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (!drag_data_->get(i)->contents_)
|
| - continue;
|
| - int index = attached_tabstrip_->model()->GetIndexOfWebContents(
|
| - drag_data_->get(i)->contents_);
|
| - attached_tabstrip_->model()->DetachWebContentsAt(index);
|
| - }
|
| - // TODO(beng): (Cleanup) seems like we should use Attach() for this
|
| - // somehow.
|
| - attached_tabstrip_ = source_tabstrip_;
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (!drag_data_->get(i)->contents_)
|
| - continue;
|
| - attached_tabstrip_->model()->InsertWebContentsAt(
|
| - drag_data_->get(i)->source_model_index_,
|
| - drag_data_->get(i)->contents_,
|
| - drag_data_->GetAddTypesForDraggedTabAt(i));
|
| - }
|
| - } else {
|
| - // The tabs were moved within the tabstrip where the drag was initiated.
|
| - // Move them back to their starting locations.
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (!drag_data_->get(i)->contents_)
|
| - continue;
|
| - int index = attached_tabstrip_->model()->GetIndexOfWebContents(
|
| - drag_data_->get(i)->contents_);
|
| - source_tabstrip_->model()->MoveWebContentsAt(
|
| - index, drag_data_->get(i)->source_model_index_, true);
|
| - }
|
| - }
|
| - } else {
|
| - // TODO(beng): (Cleanup) seems like we should use Attach() for this
|
| - // somehow.
|
| - attached_tabstrip_ = source_tabstrip_;
|
| - // The tab was detached from the tabstrip where the drag began, and has not
|
| - // been attached to any other tabstrip. We need to put it back into the
|
| - // source tabstrip.
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (!drag_data_->get(i)->contents_)
|
| - continue;
|
| - source_tabstrip_->model()->InsertWebContentsAt(
|
| - drag_data_->get(i)->source_model_index_,
|
| - drag_data_->get(i)->contents_,
|
| - drag_data_->GetAddTypesForDraggedTabAt(i));
|
| - }
|
| - }
|
| - RestoreSelection(source_tabstrip_->model());
|
| -
|
| - // If we're not attached to any tab strip, or attached to some other tab
|
| - // strip, we need to restore the bounds of the original tab strip's frame, in
|
| - // case it has been hidden.
|
| - if (restore_window)
|
| - ShowWindow();
|
| -
|
| - SetDraggedTabsVisible(true, false);
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::CompleteDrag() {
|
| - bool destroy_immediately = true;
|
| - if (attached_tabstrip_) {
|
| - // We don't need to do anything other than make the tabs visible again,
|
| - // since the dragged view is going away.
|
| - dragged_view_->AnimateToBounds(GetAnimateBounds(),
|
| - base::Bind(&DraggedTabControllerGtk::OnAnimateToBoundsComplete,
|
| - base::Unretained(this)));
|
| - destroy_immediately = false;
|
| - } else {
|
| - // Compel the model to construct a new window for the detached
|
| - // WebContentses.
|
| - BrowserWindowGtk* window = source_tabstrip_->window();
|
| - gfx::Rect window_bounds = window->GetRestoredBounds();
|
| - window_bounds.set_origin(GetWindowCreatePoint());
|
| -
|
| - std::vector<TabStripModelDelegate::NewStripContents> contentses;
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - TabStripModelDelegate::NewStripContents item;
|
| - item.web_contents = drag_data_->get(i)->contents_;
|
| - item.add_types = drag_data_->GetAddTypesForDraggedTabAt(i);
|
| - contentses.push_back(item);
|
| - };
|
| -
|
| - Browser* new_browser =
|
| - source_tabstrip_->model()->delegate()->CreateNewStripWithContents(
|
| - contentses, window_bounds, window->IsMaximized());
|
| - RestoreSelection(new_browser->tab_strip_model());
|
| - new_browser->window()->Show();
|
| - CleanUpHiddenFrame();
|
| - }
|
| -
|
| - return destroy_immediately;
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::ResetDelegates() {
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (drag_data_->get(i)->contents_ &&
|
| - drag_data_->get(i)->contents_->GetDelegate() == this) {
|
| - drag_data_->get(i)->ResetDelegate();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::EnsureDraggedView() {
|
| - if (!dragged_view_.get()) {
|
| - gfx::Rect rect;
|
| - drag_data_->GetSourceWebContents()->GetView()->GetContainerBounds(&rect);
|
| - dragged_view_.reset(new DraggedViewGtk(drag_data_.get(), mouse_offset_,
|
| - rect.size()));
|
| - }
|
| -}
|
| -
|
| -gfx::Rect DraggedTabControllerGtk::GetAnimateBounds() {
|
| - // A hidden widget moved with gtk_fixed_move in a GtkFixed container doesn't
|
| - // update its allocation until after the widget is shown, so we have to use
|
| - // the tab bounds we keep track of.
|
| - //
|
| - // We use the requested bounds instead of the allocation because the
|
| - // allocation is relative to the first windowed widget ancestor of the tab.
|
| - // Because of this, we can't use the tabs allocation to get the screen bounds.
|
| - std::vector<TabGtk*> tabs = GetTabsMatchingDraggedContents(
|
| - attached_tabstrip_);
|
| - TabGtk* tab = !base::i18n::IsRTL() ? tabs.front() : tabs.back();
|
| - gfx::Rect bounds = tab->GetRequisition();
|
| - GtkWidget* widget = tab->widget();
|
| - GtkWidget* parent = gtk_widget_get_parent(widget);
|
| - bounds.Offset(ui::GetWidgetScreenOffset(parent));
|
| -
|
| - return gfx::Rect(bounds.x(), bounds.y(),
|
| - dragged_view_->GetTotalWidthInTabStrip(), bounds.height());
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::HideWindow() {
|
| - GtkWidget* tabstrip = source_tabstrip_->widget();
|
| - GtkWindow* window = platform_util::GetTopLevel(tabstrip);
|
| - gtk_widget_hide(GTK_WIDGET(window));
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::ShowWindow() {
|
| - GtkWidget* tabstrip = source_tabstrip_->widget();
|
| - GtkWindow* window = platform_util::GetTopLevel(tabstrip);
|
| - gtk_window_present(window);
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::CleanUpHiddenFrame() {
|
| - // If the model we started dragging from is now empty, we must ask the
|
| - // delegate to close the frame.
|
| - if (source_tabstrip_->model()->empty())
|
| - source_tabstrip_->model()->delegate()->CloseFrameAfterDragSession();
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::CleanUpDraggedTabs() {
|
| - // If we were attached to the source tabstrip, dragged tabs will be in use. If
|
| - // we were detached or attached to another tabstrip, we can safely remove
|
| - // them and delete them now.
|
| - if (attached_tabstrip_ != source_tabstrip_) {
|
| - for (size_t i = 0; i < drag_data_->size(); ++i) {
|
| - if (drag_data_->get(i)->contents_) {
|
| - registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| - content::Source<WebContents>(drag_data_->get(i)->contents_));
|
| - }
|
| - source_tabstrip_->DestroyDraggedTab(drag_data_->get(i)->tab_);
|
| - drag_data_->get(i)->tab_ = NULL;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::OnAnimateToBoundsComplete() {
|
| - // Sometimes, for some reason, in automation we can be called back on a
|
| - // detach even though we aren't attached to a tabstrip. Guard against that.
|
| - if (attached_tabstrip_)
|
| - SetDraggedTabsVisible(true, true);
|
| -
|
| - CleanUpHiddenFrame();
|
| -
|
| - if (!in_destructor_)
|
| - source_tabstrip_->DestroyDragController();
|
| -}
|
| -
|
| -void DraggedTabControllerGtk::BringWindowUnderMouseToFront() {
|
| - // If we're going to dock to another window, bring it to the front.
|
| - gfx::NativeWindow window = GetLocalProcessWindow(
|
| - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
|
| - if (window)
|
| - gtk_window_present(GTK_WINDOW(window));
|
| -}
|
| -
|
| -bool DraggedTabControllerGtk::AreTabsConsecutive() {
|
| - for (size_t i = 1; i < drag_data_->size(); ++i) {
|
| - if (drag_data_->get(i - 1)->source_model_index_ + 1 !=
|
| - drag_data_->get(i)->source_model_index_) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -gfx::NativeWindow DraggedTabControllerGtk::GetLocalProcessWindow(
|
| - const gfx::Point& screen_point) {
|
| - std::set<GtkWidget*> dragged_window;
|
| - dragged_window.insert(dragged_view_->widget());
|
| - return GetLocalProcessWindowAtPoint(
|
| - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(),
|
| - dragged_window);
|
| -
|
| -}
|
|
|