Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc

Issue 113532: Implement DraggedTabGtk, the object that handles rendering either a dragged t... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h" 5 #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h"
6 6
7 #include "chrome/browser/gtk/tabs/dragged_tab_gtk.h"
7 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h" 8 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
8 #include "chrome/browser/tabs/tab_strip_model.h" 9 #include "chrome/browser/tabs/tab_strip_model.h"
9 #include "chrome/browser/tab_contents/tab_contents.h" 10 #include "chrome/browser/tab_contents/tab_contents.h"
11 #include "chrome/common/gtk_util.h"
10 #include "chrome/common/notification_service.h" 12 #include "chrome/common/notification_service.h"
11 13
12 namespace { 14 namespace {
13 15
14 // Used to determine how far a tab must obscure another tab in order to swap 16 // Used to determine how far a tab must obscure another tab in order to swap
15 // their indexes. 17 // their indexes.
16 const int kHorizontalMoveThreshold = 16; // pixels 18 const int kHorizontalMoveThreshold = 16; // pixels
17 19
18 } // namespace 20 } // namespace
19 21
20 DraggedTabControllerGtk::DraggedTabControllerGtk(TabGtk* source_tab, 22 DraggedTabControllerGtk::DraggedTabControllerGtk(TabGtk* source_tab,
21 TabStripGtk* source_tabstrip) 23 TabStripGtk* source_tabstrip)
22 : dragged_contents_(NULL), 24 : dragged_contents_(NULL),
23 original_delegate_(NULL), 25 original_delegate_(NULL),
24 source_tab_(source_tab), 26 source_tab_(source_tab),
25 source_tabstrip_(source_tabstrip), 27 source_tabstrip_(source_tabstrip),
26 source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)), 28 source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)),
27 attached_tabstrip_(source_tabstrip), 29 attached_tabstrip_(source_tabstrip),
30 in_destructor_(false),
28 last_move_screen_x_(0) { 31 last_move_screen_x_(0) {
29 SetDraggedContents( 32 SetDraggedContents(
30 source_tabstrip_->model()->GetTabContentsAt(source_model_index_)); 33 source_tabstrip_->model()->GetTabContentsAt(source_model_index_));
31 } 34 }
32 35
33 DraggedTabControllerGtk::~DraggedTabControllerGtk() { 36 DraggedTabControllerGtk::~DraggedTabControllerGtk() {
37 in_destructor_ = true;
38 // Need to delete the dragged tab here manually _before_ we reset the dragged
39 // contents to NULL, otherwise if the view is animating to its destination
40 // bounds, it won't be able to clean up properly since its cleanup routine
41 // uses GetIndexForDraggedContents, which will be invalid.
42 dragged_tab_.reset();
43 SetDraggedContents(NULL);
34 } 44 }
35 45
36 void DraggedTabControllerGtk::CaptureDragInfo(const gfx::Point& mouse_offset) { 46 void DraggedTabControllerGtk::CaptureDragInfo(const gfx::Point& mouse_offset) {
37 start_screen_point_ = GetCursorScreenPoint(); 47 start_screen_point_ = GetCursorScreenPoint();
38 mouse_offset_ = mouse_offset; 48 mouse_offset_ = mouse_offset;
39 snap_bounds_ = source_tab_->bounds();
40 } 49 }
41 50
42 void DraggedTabControllerGtk::Drag() { 51 void DraggedTabControllerGtk::Drag() {
43 ContinueDragging(); 52 if (!source_tab_)
53 return;
54
55 // Before we get to dragging anywhere, ensure that we consider ourselves
56 // attached to the source tabstrip.
57 if (source_tab_->IsVisible()) {
58 Attach(source_tabstrip_, gfx::Point());
59 }
60
61 if (!source_tab_->IsVisible()) {
62 // TODO(jhawkins): Save focus.
63 ContinueDragging();
64 }
44 } 65 }
45 66
46 bool DraggedTabControllerGtk::EndDrag(bool canceled) { 67 bool DraggedTabControllerGtk::EndDrag(bool canceled) {
47 return EndDragImpl(canceled ? CANCELED : NORMAL); 68 return EndDragImpl(canceled ? CANCELED : NORMAL);
48 } 69 }
49 70
50 //////////////////////////////////////////////////////////////////////////////// 71 ////////////////////////////////////////////////////////////////////////////////
51 // DraggedTabControllerGtk, TabContentsDelegate implementation: 72 // DraggedTabControllerGtk, TabContentsDelegate implementation:
52 73
53 void DraggedTabControllerGtk::OpenURLFromTab(TabContents* source, 74 void DraggedTabControllerGtk::OpenURLFromTab(TabContents* source,
54 const GURL& url, 75 const GURL& url,
55 const GURL& referrer, 76 const GURL& referrer,
56 WindowOpenDisposition disposition, 77 WindowOpenDisposition disposition,
57 PageTransition::Type transition) { 78 PageTransition::Type transition) {
58 if (original_delegate_) { 79 if (original_delegate_) {
59 if (disposition == CURRENT_TAB) 80 if (disposition == CURRENT_TAB)
60 disposition = NEW_WINDOW; 81 disposition = NEW_WINDOW;
61 82
62 original_delegate_->OpenURLFromTab(source, url, referrer, 83 original_delegate_->OpenURLFromTab(source, url, referrer,
63 disposition, transition); 84 disposition, transition);
64 } 85 }
65 } 86 }
66 87
67 void DraggedTabControllerGtk::NavigationStateChanged(const TabContents* source, 88 void DraggedTabControllerGtk::NavigationStateChanged(const TabContents* source,
68 unsigned changed_flags) { 89 unsigned changed_flags) {
90 if (dragged_tab_.get())
91 dragged_tab_->Update();
69 } 92 }
70 93
71 void DraggedTabControllerGtk::AddNewContents(TabContents* source, 94 void DraggedTabControllerGtk::AddNewContents(TabContents* source,
72 TabContents* new_contents, 95 TabContents* new_contents,
73 WindowOpenDisposition disposition, 96 WindowOpenDisposition disposition,
74 const gfx::Rect& initial_pos, 97 const gfx::Rect& initial_pos,
75 bool user_gesture) { 98 bool user_gesture) {
76 DCHECK(disposition != CURRENT_TAB); 99 DCHECK(disposition != CURRENT_TAB);
77 100
78 // Theoretically could be called while dragging if the page tries to 101 // Theoretically could be called while dragging if the page tries to
79 // spawn a window. Route this message back to the browser in most cases. 102 // spawn a window. Route this message back to the browser in most cases.
80 if (original_delegate_) { 103 if (original_delegate_) {
81 original_delegate_->AddNewContents(source, new_contents, disposition, 104 original_delegate_->AddNewContents(source, new_contents, disposition,
82 initial_pos, user_gesture); 105 initial_pos, user_gesture);
83 } 106 }
84 } 107 }
85 108
86 void DraggedTabControllerGtk::ActivateContents(TabContents* contents) { 109 void DraggedTabControllerGtk::ActivateContents(TabContents* contents) {
87 // Ignored. 110 // Ignored.
88 } 111 }
89 112
90 void DraggedTabControllerGtk::LoadingStateChanged(TabContents* source) { 113 void DraggedTabControllerGtk::LoadingStateChanged(TabContents* source) {
114 // TODO(jhawkins): It would be nice to respond to this message by changing the
115 // screen shot in the dragged tab.
116 if (dragged_tab_.get())
117 dragged_tab_->Update();
91 } 118 }
92 119
93 void DraggedTabControllerGtk::CloseContents(TabContents* source) { 120 void DraggedTabControllerGtk::CloseContents(TabContents* source) {
94 // Theoretically could be called by a window. Should be ignored 121 // Theoretically could be called by a window. Should be ignored
95 // because window.close() is ignored (usually, even though this 122 // because window.close() is ignored (usually, even though this
96 // method gets called.) 123 // method gets called.)
97 } 124 }
98 125
99 void DraggedTabControllerGtk::MoveContents(TabContents* source, 126 void DraggedTabControllerGtk::MoveContents(TabContents* source,
100 const gfx::Rect& pos) { 127 const gfx::Rect& pos) {
(...skipping 24 matching lines...) Expand all
125 // DraggedTabControllerGtk, NotificationObserver implementation: 152 // DraggedTabControllerGtk, NotificationObserver implementation:
126 153
127 void DraggedTabControllerGtk::Observe(NotificationType type, 154 void DraggedTabControllerGtk::Observe(NotificationType type,
128 const NotificationSource& source, 155 const NotificationSource& source,
129 const NotificationDetails& details) { 156 const NotificationDetails& details) {
130 DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); 157 DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
131 DCHECK(Source<TabContents>(source).ptr() == dragged_contents_); 158 DCHECK(Source<TabContents>(source).ptr() == dragged_contents_);
132 EndDragImpl(TAB_DESTROYED); 159 EndDragImpl(TAB_DESTROYED);
133 } 160 }
134 161
162 void DraggedTabControllerGtk::InitWindowCreatePoint() {
163 window_create_point_.SetPoint(mouse_offset_.x(), mouse_offset_.y());
164 }
165
135 void DraggedTabControllerGtk::SetDraggedContents(TabContents* new_contents) { 166 void DraggedTabControllerGtk::SetDraggedContents(TabContents* new_contents) {
136 if (dragged_contents_) { 167 if (dragged_contents_) {
137 registrar_.Remove(this, 168 registrar_.Remove(this,
138 NotificationType::TAB_CONTENTS_DESTROYED, 169 NotificationType::TAB_CONTENTS_DESTROYED,
139 Source<TabContents>(dragged_contents_)); 170 Source<TabContents>(dragged_contents_));
140 if (original_delegate_) 171 if (original_delegate_)
141 dragged_contents_->set_delegate(original_delegate_); 172 dragged_contents_->set_delegate(original_delegate_);
142 } 173 }
143 original_delegate_ = NULL; 174 original_delegate_ = NULL;
144 dragged_contents_ = new_contents; 175 dragged_contents_ = new_contents;
145 if (dragged_contents_) { 176 if (dragged_contents_) {
146 registrar_.Add(this, 177 registrar_.Add(this,
147 NotificationType::TAB_CONTENTS_DESTROYED, 178 NotificationType::TAB_CONTENTS_DESTROYED,
148 Source<TabContents>(dragged_contents_)); 179 Source<TabContents>(dragged_contents_));
149 180
150 // We need to be the delegate so we receive messages about stuff, 181 // We need to be the delegate so we receive messages about stuff,
151 // otherwise our dragged_contents() may be replaced and subsequently 182 // otherwise our dragged_contents() may be replaced and subsequently
152 // collected/destroyed while the drag is in process, leading to 183 // collected/destroyed while the drag is in process, leading to
153 // nasty crashes. 184 // nasty crashes.
154 original_delegate_ = dragged_contents_->delegate(); 185 original_delegate_ = dragged_contents_->delegate();
155 dragged_contents_->set_delegate(this); 186 dragged_contents_->set_delegate(this);
156 } 187 }
157 } 188 }
158 189
159 void DraggedTabControllerGtk::ContinueDragging() { 190 void DraggedTabControllerGtk::ContinueDragging() {
191 EnsureDraggedTab();
192
160 // TODO(jhawkins): We don't handle the situation where the last tab is dragged 193 // TODO(jhawkins): We don't handle the situation where the last tab is dragged
161 // out of a window, so we'll just go with the way Windows handles dragging for 194 // out of a window, so we'll just go with the way Windows handles dragging for
162 // now. 195 // now.
163 gfx::Point screen_point = GetCursorScreenPoint(); 196 gfx::Point screen_point = GetCursorScreenPoint();
164 MoveTab(screen_point); 197 MoveTab(screen_point);
165 } 198 }
166 199
167 void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) { 200 void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) {
168 gfx::Point dragged_point = GetDraggedPoint(screen_point); 201 gfx::Point dragged_tab_point = GetDraggedTabPoint(screen_point);
169 202
170 if (attached_tabstrip_) { 203 if (attached_tabstrip_) {
171 // Determine the horizontal move threshold. This is dependent on the width 204 // Determine the horizontal move threshold. This is dependent on the width
172 // of tabs. The smaller the tabs compared to the standard size, the smaller 205 // of tabs. The smaller the tabs compared to the standard size, the smaller
173 // the threshold. 206 // the threshold.
174 double unselected, selected; 207 double unselected, selected;
175 attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected); 208 attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
176 double ratio = unselected / TabGtk::GetStandardSize().width(); 209 double ratio = unselected / TabGtk::GetStandardSize().width();
177 int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); 210 int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold);
178 211
179 // Update the model, moving the TabContents from one index to another. Do 212 // Update the model, moving the TabContents from one index to another. Do
180 // this only if we have moved a minimum distance since the last reorder (to 213 // this only if we have moved a minimum distance since the last reorder (to
181 // prevent jitter). 214 // prevent jitter).
182 if (abs(screen_point.x() - last_move_screen_x_) > threshold) { 215 if (abs(screen_point.x() - last_move_screen_x_) > threshold) {
183 TabStripModel* attached_model = attached_tabstrip_->model(); 216 TabStripModel* attached_model = attached_tabstrip_->model();
184 int from_index = 217 int from_index =
185 attached_model->GetIndexOfTabContents(dragged_contents_); 218 attached_model->GetIndexOfTabContents(dragged_contents_);
186 gfx::Rect bounds = source_tab_->bounds(); 219 gfx::Rect bounds = GetDraggedTabTabStripBounds(dragged_tab_point);
187 int to_index = GetInsertionIndexForDraggedBounds(bounds); 220 int to_index = GetInsertionIndexForDraggedBounds(bounds);
188 to_index = NormalizeIndexToAttachedTabStrip(to_index); 221 to_index = NormalizeIndexToAttachedTabStrip(to_index);
189 if (from_index != to_index) { 222 if (from_index != to_index) {
190 last_move_screen_x_ = screen_point.x(); 223 last_move_screen_x_ = screen_point.x();
191 snap_bounds_ = attached_tabstrip_->GetTabAt(to_index)->bounds();
192 attached_model->MoveTabContentsAt(from_index, to_index, true); 224 attached_model->MoveTabContentsAt(from_index, to_index, true);
193 } 225 }
194 } 226 }
195 } 227 }
196 228
197 // Move the tab. There are no changes to the model if we're detached. 229 // Move the dragged tab. There are no changes to the model if we're detached.
198 gfx::Rect bounds = source_tab_->bounds(); 230 dragged_tab_->MoveTo(dragged_tab_point);
199 bounds.set_x(dragged_point.x());
200 source_tab_->SetBounds(bounds);
201 gtk_fixed_move(GTK_FIXED(source_tabstrip_->tabstrip_.get()),
202 source_tab_->widget(), bounds.x(), bounds.y());
203 } 231 }
204 232
205 TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint( 233 TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint(
206 const gfx::Point& screen_point) { 234 const gfx::Point& screen_point) {
207 // TODO(jhawkins): Actually get the correct tabstrip under |screen_point|. 235 // TODO(jhawkins): Actually get the correct tabstrip under |screen_point|.
208 return source_tabstrip_; 236 return source_tabstrip_;
209 } 237 }
210 238
239 void DraggedTabControllerGtk::Attach(TabStripGtk* attached_tabstrip,
240 const gfx::Point& screen_point) {
241 attached_tabstrip_ = attached_tabstrip;
242 InitWindowCreatePoint();
243 attached_tabstrip_->GenerateIdealBounds();
244
245 TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
246
247 // Update the tab first, so we can ask it for its bounds and determine
248 // where to insert the hidden tab.
249
250 // If this is the first time Attach is called for this drag, we're attaching
251 // to the source tabstrip, and we should assume the tab count already
252 // includes this tab since we haven't been detached yet. If we don't do this,
253 // the dragged representation will be a different size to others in the
254 // tabstrip.
255 int tab_count = attached_tabstrip_->GetTabCount();
256 if (!tab)
257 ++tab_count;
258 double unselected_width = 0, selected_width = 0;
259 attached_tabstrip_->GetDesiredTabWidths(tab_count, &unselected_width,
260 &selected_width);
261 EnsureDraggedTab();
262 dragged_tab_->Attach(static_cast<int>(selected_width));
263
264 if (!tab) {
265 // There is no tab in |attached_tabstrip| that corresponds to the dragged
266 // TabContents. We must now create one.
267
268 // Remove ourselves as the delegate now that the dragged TabContents is
269 // being inserted back into a Browser.
270 dragged_contents_->set_delegate(NULL);
271 original_delegate_ = NULL;
272
273 // Return the TabContents' to normalcy.
274 dragged_contents_->set_capturing_contents(false);
275
276 // We need to ask the tabstrip we're attached to ensure that the ideal
277 // bounds for all its tabs are correctly generated, because the calculation
278 // in GetInsertionIndexForDraggedBounds needs them to be to figure out the
279 // appropriate insertion index.
280 attached_tabstrip_->GenerateIdealBounds();
281
282 // Inserting counts as a move. We don't want the tabs to jitter when the
283 // user moves the tab immediately after attaching it.
284 last_move_screen_x_ = screen_point.x();
285
286 // Figure out where to insert the tab based on the bounds of the dragged
287 // representation and the ideal bounds of the other tabs already in the
288 // strip. ("ideal bounds" are stable even if the tabs' actual bounds are
289 // changing due to animation).
290 gfx::Rect bounds = GetDraggedTabTabStripBounds(screen_point);
291 int index = GetInsertionIndexForDraggedBounds(bounds);
292 index = std::max(std::min(index, attached_tabstrip_->model()->count()), 0);
293 attached_tabstrip_->model()->InsertTabContentsAt(index, dragged_contents_,
294 true, false);
295
296 tab = GetTabMatchingDraggedContents(attached_tabstrip_);
297 }
298 DCHECK(tab); // We should now have a tab.
299 tab->SetVisible(false);
300
301 // TODO(jhawkins): Move the corresponding window to the front.
302 }
303
304 void DraggedTabControllerGtk::Detach() {
305 // TODO(jhawkins): Detach the dragged tab.
306 }
307
308 gfx::Point DraggedTabControllerGtk::ConvertScreenPointToTabStripPoint(
309 TabStripGtk* tabstrip, const gfx::Point& screen_point) {
310 gint x, y;
311 gdk_window_get_origin(tabstrip->tabstrip_.get()->window, &x, &y);
312 return gfx::Point(screen_point.x() - x, screen_point.y() - y);
313 }
314
315 gfx::Rect DraggedTabControllerGtk::GetDraggedTabTabStripBounds(
316 const gfx::Point& screen_point) {
317 gfx::Point client_point =
318 ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point);
319 gfx::Size tab_size = dragged_tab_->attached_tab_size();
320 return gfx::Rect(client_point.x(), client_point.y(),
321 tab_size.width(), tab_size.height());
322 }
323
211 int DraggedTabControllerGtk::GetInsertionIndexForDraggedBounds( 324 int DraggedTabControllerGtk::GetInsertionIndexForDraggedBounds(
212 const gfx::Rect& dragged_bounds) const { 325 const gfx::Rect& dragged_bounds) const {
213 int right_tab_x = 0; 326 int right_tab_x = 0;
214 327
215 // TODO(jhawkins): Handle RTL layout. 328 // TODO(jhawkins): Handle RTL layout.
216 329
217 // Divides each tab into two halves to see if the dragged tab has crossed 330 // Divides each tab into two halves to see if the dragged tab has crossed
218 // the halfway boundary necessary to move past the next tab. 331 // the halfway boundary necessary to move past the next tab.
219 for (int i = 0; i < attached_tabstrip_->GetTabCount(); i++) { 332 for (int i = 0; i < attached_tabstrip_->GetTabCount(); i++) {
220 gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i); 333 gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i);
(...skipping 15 matching lines...) Expand all
236 return i; 349 return i;
237 } 350 }
238 } 351 }
239 352
240 if (dragged_bounds.right() > right_tab_x) 353 if (dragged_bounds.right() > right_tab_x)
241 return attached_tabstrip_->model()->count(); 354 return attached_tabstrip_->model()->count();
242 355
243 return TabStripModel::kNoTab; 356 return TabStripModel::kNoTab;
244 } 357 }
245 358
246 gfx::Point DraggedTabControllerGtk::GetDraggedPoint(const gfx::Point& point) { 359 gfx::Point DraggedTabControllerGtk::GetDraggedTabPoint(
247 int x = point.x() - mouse_offset_.x(); 360 const gfx::Point& screen_point) {
248 int y = point.y() - mouse_offset_.y(); 361 int x = screen_point.x() - mouse_offset_.x();
362 int y = screen_point.y() - mouse_offset_.y();
249 363
250 // Snap the dragged tab to the tab strip. 364 // If we're not attached, we just use x and y from above.
251 if (x < 0) 365 if (attached_tabstrip_) {
252 x = 0; 366 gfx::Rect tabstrip_bounds =
367 gtk_util::GetWidgetScreenBounds(attached_tabstrip_->tabstrip_.get());
368 // Snap the dragged tab to the tabstrip if we are attached, detaching
369 // only when the mouse position (screen_point) exceeds the screen bounds
370 // of the tabstrip.
371 if (x < tabstrip_bounds.x() && screen_point.x() >= tabstrip_bounds.x())
372 x = tabstrip_bounds.x();
253 373
254 // Make sure the tab can't be dragged off the right side of the tab strip. 374 gfx::Size tab_size = dragged_tab_->attached_tab_size();
255 int max_x = attached_tabstrip_->bounds_.right() - source_tab_->width(); 375 int vertical_drag_magnetism = tab_size.height() * 2;
256 if (x > max_x) 376 int vertical_detach_point = tabstrip_bounds.y() - vertical_drag_magnetism;
257 x = max_x; 377 if (y < tabstrip_bounds.y() && screen_point.y() >= vertical_detach_point)
378 y = tabstrip_bounds.y();
258 379
380 // Make sure the tab can't be dragged off the right side of the tabstrip
381 // unless the mouse pointer passes outside the bounds of the strip by
382 // clamping the position of the dragged window to the tabstrip width less
383 // the width of one tab until the mouse pointer (screen_point) exceeds the
384 // screen bounds of the tabstrip.
385 int max_x = tabstrip_bounds.right() - tab_size.width();
386 int max_y = tabstrip_bounds.bottom() - tab_size.height();
387 if (x > max_x && screen_point.x() <= tabstrip_bounds.right())
388 x = max_x;
389 if (y > max_y && screen_point.y() <=
390 (tabstrip_bounds.bottom() + vertical_drag_magnetism)) {
391 y = max_y;
392 }
393 }
259 return gfx::Point(x, y); 394 return gfx::Point(x, y);
260 } 395 }
261 396
262 int DraggedTabControllerGtk::NormalizeIndexToAttachedTabStrip(int index) const { 397 int DraggedTabControllerGtk::NormalizeIndexToAttachedTabStrip(int index) const {
263 if (index >= attached_tabstrip_->model_->count()) 398 if (index >= attached_tabstrip_->model_->count())
264 return attached_tabstrip_->model_->count() - 1; 399 return attached_tabstrip_->model_->count() - 1;
265 if (index == TabStripModel::kNoTab) 400 if (index == TabStripModel::kNoTab)
266 return 0; 401 return 0;
267 return index; 402 return index;
268 } 403 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 446
312 return destroy_now; 447 return destroy_now;
313 } 448 }
314 449
315 void DraggedTabControllerGtk::RevertDrag() { 450 void DraggedTabControllerGtk::RevertDrag() {
316 // We save this here because code below will modify |attached_tabstrip_|. 451 // We save this here because code below will modify |attached_tabstrip_|.
317 if (attached_tabstrip_) { 452 if (attached_tabstrip_) {
318 int index = attached_tabstrip_->model()->GetIndexOfTabContents( 453 int index = attached_tabstrip_->model()->GetIndexOfTabContents(
319 dragged_contents_); 454 dragged_contents_);
320 if (attached_tabstrip_ != source_tabstrip_) { 455 if (attached_tabstrip_ != source_tabstrip_) {
321 // The Tab was inserted into another TabStrip. We need to put it back 456 // The tab was inserted into another tabstrip. We need to put it back
322 // into the original one. 457 // into the original one.
323 attached_tabstrip_->model()->DetachTabContentsAt(index); 458 attached_tabstrip_->model()->DetachTabContentsAt(index);
324 // TODO(beng): (Cleanup) seems like we should use Attach() for this 459 // TODO(beng): (Cleanup) seems like we should use Attach() for this
325 // somehow. 460 // somehow.
326 attached_tabstrip_ = source_tabstrip_; 461 attached_tabstrip_ = source_tabstrip_;
327 source_tabstrip_->model()->InsertTabContentsAt(source_model_index_, 462 source_tabstrip_->model()->InsertTabContentsAt(source_model_index_,
328 dragged_contents_, true, false); 463 dragged_contents_, true, false);
329 } else { 464 } else {
330 // The Tab was moved within the TabStrip where the drag was initiated. 465 // The tab was moved within the tabstrip where the drag was initiated.
331 // Move it back to the starting location. 466 // Move it back to the starting location.
332 source_tabstrip_->model()->MoveTabContentsAt(index, source_model_index_, 467 source_tabstrip_->model()->MoveTabContentsAt(index, source_model_index_,
333 true); 468 true);
334 } 469 }
335 } else { 470 } else {
336 // TODO(beng): (Cleanup) seems like we should use Attach() for this 471 // TODO(beng): (Cleanup) seems like we should use Attach() for this
337 // somehow. 472 // somehow.
338 attached_tabstrip_ = source_tabstrip_; 473 attached_tabstrip_ = source_tabstrip_;
339 // The Tab was detached from the TabStrip where the drag began, and has not 474 // The tab was detached from the tabstrip where the drag began, and has not
340 // been attached to any other TabStrip. We need to put it back into the 475 // been attached to any other tabstrip. We need to put it back into the
341 // source TabStrip. 476 // source tabstrip.
342 source_tabstrip_->model()->InsertTabContentsAt(source_model_index_, 477 source_tabstrip_->model()->InsertTabContentsAt(source_model_index_,
343 dragged_contents_, true, false); 478 dragged_contents_, true, false);
344 } 479 }
480
481 source_tab_->SetVisible(true);
345 } 482 }
346 483
347 bool DraggedTabControllerGtk::CompleteDrag() { 484 bool DraggedTabControllerGtk::CompleteDrag() {
348 // We don't need to do anything other than make the Tab visible again, 485 // We don't need to do anything other than make the tab visible again,
349 // since the dragged tab is going away. 486 // since the dragged tab is going away.
350 gfx::Rect bounds = source_tab_->bounds(); 487 TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
351 bounds.set_x(snap_bounds_.x()); 488 gfx::Rect rect = GetTabScreenBounds(tab);
352 source_tab_->SetBounds(bounds); 489 dragged_tab_->AnimateToBounds(GetTabScreenBounds(tab),
353 gtk_fixed_move(GTK_FIXED(source_tabstrip_->tabstrip_.get()), 490 NewCallback(this, &DraggedTabControllerGtk::OnAnimateToBoundsComplete));
354 source_tab_->widget(), bounds.x(), bounds.y());
355 491
356 return false; 492 return false;
357 } 493 }
358 494
495 void DraggedTabControllerGtk::EnsureDraggedTab() {
496 if (!dragged_tab_.get()) {
497 gfx::Rect rect;
498 dragged_contents_->GetContainerBounds(&rect);
499
500 dragged_tab_.reset(new DraggedTabGtk(dragged_contents_, mouse_offset_,
501 gfx::Size(rect.width(), rect.height())));
502 }
503 }
504
359 gfx::Point DraggedTabControllerGtk::GetCursorScreenPoint() const { 505 gfx::Point DraggedTabControllerGtk::GetCursorScreenPoint() const {
360 // Get default display and screen. 506 // Get default display and screen.
361 GdkDisplay* display = gdk_display_get_default(); 507 GdkDisplay* display = gdk_display_get_default();
362 508
363 // Get cursor position. 509 // Get cursor position.
364 int x, y; 510 int x, y;
365 gdk_display_get_pointer(display, NULL, &x, &y, NULL); 511 gdk_display_get_pointer(display, NULL, &x, &y, NULL);
366 512
367 return gfx::Point(x, y); 513 return gfx::Point(x, y);
368 } 514 }
515
516 // static
517 gfx::Rect DraggedTabControllerGtk::GetTabScreenBounds(TabGtk* tab) {
518 // A hidden widget moved with gtk_fixed_move in a GtkFixed container doesn't
519 // update its allocation until after the widget is shown, so we have to use
520 // the tab bounds we keep track of.
521 int x, y;
522 x = tab->bounds().x();
523 y = tab->bounds().y();
524
525 GtkWidget* widget = tab->widget();
526 GtkWidget* parent = gtk_widget_get_parent(widget);
527 gfx::Point point = gtk_util::GetWidgetScreenPosition(parent);
528 x += point.x();
529 y += point.y();
530
531 return gfx::Rect(x, y, widget->allocation.width, widget->allocation.height);
532 }
533
534 void DraggedTabControllerGtk::OnAnimateToBoundsComplete() {
535 // Sometimes, for some reason, in automation we can be called back on a
536 // detach even though we aren't attached to a tabstrip. Guard against that.
537 if (attached_tabstrip_) {
538 TabGtk* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
539 if (tab) {
540 tab->SetVisible(true);
541 // Paint the tab now, otherwise there may be slight flicker between the
542 // time the dragged tab window is destroyed and we paint.
543 tab->SchedulePaint();
544 }
545 }
546
547 if (!in_destructor_)
548 source_tabstrip_->DestroyDragController();
549 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h ('k') | chrome/browser/gtk/tabs/dragged_tab_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698