OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/views/tabs/dragged_tab_controller.h" | 5 #include "chrome/browser/views/tabs/dragged_tab_controller.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "app/animation.h" | 10 #include "app/animation.h" |
11 #include "app/gfx/canvas.h" | 11 #include "app/gfx/canvas.h" |
| 12 #include "app/l10n_util.h" |
12 #include "app/resource_bundle.h" | 13 #include "app/resource_bundle.h" |
13 #include "chrome/browser/browser_window.h" | 14 #include "chrome/browser/browser_window.h" |
14 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 15 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
15 #include "chrome/browser/tab_contents/tab_contents.h" | 16 #include "chrome/browser/tab_contents/tab_contents.h" |
16 #include "chrome/browser/metrics/user_metrics.h" | 17 #include "chrome/browser/metrics/user_metrics.h" |
17 #include "chrome/browser/views/frame/browser_view.h" | 18 #include "chrome/browser/views/frame/browser_view.h" |
18 #include "chrome/browser/views/tabs/dragged_tab_view.h" | 19 #include "chrome/browser/views/tabs/dragged_tab_view.h" |
19 #include "chrome/browser/views/tabs/native_view_photobooth.h" | 20 #include "chrome/browser/views/tabs/native_view_photobooth.h" |
20 #include "chrome/browser/views/tabs/tab.h" | 21 #include "chrome/browser/views/tabs/tab.h" |
21 #include "chrome/browser/views/tabs/tab_strip.h" | 22 #include "chrome/browser/views/tabs/tab_strip.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 paint.setColor(SkColorSetRGB(108, 108, 108)); | 64 paint.setColor(SkColorSetRGB(108, 108, 108)); |
64 paint.setStyle(SkPaint::kFill_Style); | 65 paint.setStyle(SkPaint::kFill_Style); |
65 canvas->drawRoundRect(outer_rect, SkIntToScalar(kRoundedRectRadius), | 66 canvas->drawRoundRect(outer_rect, SkIntToScalar(kRoundedRectRadius), |
66 SkIntToScalar(kRoundedRectRadius), paint); | 67 SkIntToScalar(kRoundedRectRadius), paint); |
67 | 68 |
68 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 69 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
69 | 70 |
70 SkBitmap* high_icon = rb.GetBitmapNamed(IDR_DOCK_HIGH); | 71 SkBitmap* high_icon = rb.GetBitmapNamed(IDR_DOCK_HIGH); |
71 SkBitmap* wide_icon = rb.GetBitmapNamed(IDR_DOCK_WIDE); | 72 SkBitmap* wide_icon = rb.GetBitmapNamed(IDR_DOCK_WIDE); |
72 | 73 |
| 74 bool rtl_ui = l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT; |
| 75 if (rtl_ui) { |
| 76 // Flip canvas to draw the mirrored tab images for RTL UI. |
| 77 canvas->save(); |
| 78 canvas->TranslateInt(width(), 0); |
| 79 canvas->ScaleInt(-1, 1); |
| 80 } |
| 81 int x_of_active_tab = -1; |
| 82 int x_of_inactive_tab = -1; |
73 switch (type_) { | 83 switch (type_) { |
74 case DockInfo::LEFT_OF_WINDOW: | 84 case DockInfo::LEFT_OF_WINDOW: |
75 case DockInfo::LEFT_HALF: | 85 case DockInfo::LEFT_HALF: |
76 canvas->DrawBitmapInt(*high_icon, | 86 if (!rtl_ui) { |
77 width() / 2 - high_icon->width() - kTabSpacing / 2, | 87 x_of_active_tab = width() / 2 - high_icon->width() - kTabSpacing / 2; |
78 (height() - high_icon->height()) / 2); | 88 x_of_inactive_tab = width() / 2 + kTabSpacing / 2; |
| 89 } else { |
| 90 // Adjust x axis for RTL UI after flippping canvas. |
| 91 x_of_active_tab = width() / 2 + kTabSpacing / 2; |
| 92 x_of_inactive_tab = width() / 2 - high_icon->width() - |
| 93 kTabSpacing / 2; |
| 94 } |
| 95 canvas->DrawBitmapInt(*high_icon, x_of_active_tab, |
| 96 (height() - high_icon->height()) / 2); |
79 if (type_ == DockInfo::LEFT_OF_WINDOW) { | 97 if (type_ == DockInfo::LEFT_OF_WINDOW) { |
80 DrawBitmapWithAlpha(canvas, *high_icon, width() / 2 + kTabSpacing / 2, | 98 DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, |
81 (height() - high_icon->height()) / 2); | 99 (height() - high_icon->height()) / 2); |
82 } | 100 } |
83 break; | 101 break; |
84 | 102 |
85 | 103 |
86 case DockInfo::RIGHT_OF_WINDOW: | 104 case DockInfo::RIGHT_OF_WINDOW: |
87 case DockInfo::RIGHT_HALF: | 105 case DockInfo::RIGHT_HALF: |
88 canvas->DrawBitmapInt(*high_icon, width() / 2 + kTabSpacing / 2, | 106 if (!rtl_ui) { |
| 107 x_of_active_tab = width() / 2 + kTabSpacing / 2; |
| 108 x_of_inactive_tab = width() / 2 - high_icon->width() - |
| 109 kTabSpacing / 2; |
| 110 } else { |
| 111 // Adjust x axis for RTL UI after flippping canvas. |
| 112 x_of_active_tab = width() / 2 - high_icon->width() - kTabSpacing / 2; |
| 113 x_of_inactive_tab = width() / 2 + kTabSpacing / 2; |
| 114 } |
| 115 canvas->DrawBitmapInt(*high_icon, x_of_active_tab, |
89 (height() - high_icon->height()) / 2); | 116 (height() - high_icon->height()) / 2); |
90 if (type_ == DockInfo::RIGHT_OF_WINDOW) { | 117 if (type_ == DockInfo::RIGHT_OF_WINDOW) { |
91 DrawBitmapWithAlpha(canvas, *high_icon, | 118 DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, |
92 width() / 2 - high_icon->width() - kTabSpacing / 2, | 119 (height() - high_icon->height()) / 2); |
93 (height() - high_icon->height()) / 2); | |
94 } | 120 } |
95 break; | 121 break; |
96 | 122 |
97 case DockInfo::TOP_OF_WINDOW: | 123 case DockInfo::TOP_OF_WINDOW: |
98 canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, | 124 canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, |
99 height() / 2 - high_icon->height()); | 125 height() / 2 - high_icon->height()); |
100 break; | 126 break; |
101 | 127 |
102 case DockInfo::MAXIMIZE: { | 128 case DockInfo::MAXIMIZE: { |
103 SkBitmap* max_icon = rb.GetBitmapNamed(IDR_DOCK_MAX); | 129 SkBitmap* max_icon = rb.GetBitmapNamed(IDR_DOCK_MAX); |
(...skipping 10 matching lines...) Expand all Loading... |
114 DrawBitmapWithAlpha(canvas, *wide_icon, | 140 DrawBitmapWithAlpha(canvas, *wide_icon, |
115 (width() - wide_icon->width()) / 2, | 141 (width() - wide_icon->width()) / 2, |
116 height() / 2 - kTabSpacing / 2 - wide_icon->height()); | 142 height() / 2 - kTabSpacing / 2 - wide_icon->height()); |
117 } | 143 } |
118 break; | 144 break; |
119 | 145 |
120 default: | 146 default: |
121 NOTREACHED(); | 147 NOTREACHED(); |
122 break; | 148 break; |
123 } | 149 } |
| 150 if (rtl_ui) |
| 151 canvas->restore(); |
124 } | 152 } |
125 | 153 |
126 private: | 154 private: |
127 void DrawBitmapWithAlpha(gfx::Canvas* canvas, const SkBitmap& image, | 155 void DrawBitmapWithAlpha(gfx::Canvas* canvas, const SkBitmap& image, |
128 int x, int y) { | 156 int x, int y) { |
129 SkPaint paint; | 157 SkPaint paint; |
130 paint.setAlpha(128); | 158 paint.setAlpha(128); |
131 canvas->DrawBitmapInt(image, x, y, paint); | 159 canvas->DrawBitmapInt(image, x, y, paint); |
132 } | 160 } |
133 | 161 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 // contents to NULL, otherwise if the view is animating to its destination | 322 // contents to NULL, otherwise if the view is animating to its destination |
295 // bounds, it won't be able to clean up properly since its cleanup routine | 323 // bounds, it won't be able to clean up properly since its cleanup routine |
296 // uses GetIndexForDraggedContents, which will be invalid. | 324 // uses GetIndexForDraggedContents, which will be invalid. |
297 view_.reset(NULL); | 325 view_.reset(NULL); |
298 SetDraggedContents(NULL); // This removes our observer. | 326 SetDraggedContents(NULL); // This removes our observer. |
299 } | 327 } |
300 | 328 |
301 void DraggedTabController::CaptureDragInfo(const gfx::Point& mouse_offset) { | 329 void DraggedTabController::CaptureDragInfo(const gfx::Point& mouse_offset) { |
302 start_screen_point_ = GetCursorScreenPoint(); | 330 start_screen_point_ = GetCursorScreenPoint(); |
303 mouse_offset_ = mouse_offset; | 331 mouse_offset_ = mouse_offset; |
| 332 InitWindowCreatePoint(); |
304 } | 333 } |
305 | 334 |
306 void DraggedTabController::Drag() { | 335 void DraggedTabController::Drag() { |
307 bring_to_front_timer_.Stop(); | 336 bring_to_front_timer_.Stop(); |
308 | 337 |
309 // Before we get to dragging anywhere, ensure that we consider ourselves | 338 // Before we get to dragging anywhere, ensure that we consider ourselves |
310 // attached to the source tabstrip. | 339 // attached to the source tabstrip. |
311 if (source_tab_->IsVisible() && CanStartDrag()) | 340 if (source_tab_->IsVisible() && CanStartDrag()) |
312 Attach(source_tabstrip_, gfx::Point()); | 341 Attach(source_tabstrip_, gfx::Point()); |
313 | 342 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 void DraggedTabController::DidProcessEvent(GdkEvent* event) { | 483 void DraggedTabController::DidProcessEvent(GdkEvent* event) { |
455 NOTIMPLEMENTED(); | 484 NOTIMPLEMENTED(); |
456 } | 485 } |
457 #endif | 486 #endif |
458 | 487 |
459 /////////////////////////////////////////////////////////////////////////////// | 488 /////////////////////////////////////////////////////////////////////////////// |
460 // DraggedTabController, private: | 489 // DraggedTabController, private: |
461 | 490 |
462 void DraggedTabController::InitWindowCreatePoint() { | 491 void DraggedTabController::InitWindowCreatePoint() { |
463 window_create_point_.SetPoint(mouse_offset_.x(), mouse_offset_.y()); | 492 window_create_point_.SetPoint(mouse_offset_.x(), mouse_offset_.y()); |
464 Tab* first_tab = attached_tabstrip_->GetTabAt(0); | 493 // window_create_point_ is only used in CompleteDrag() (through |
| 494 // GetWindowCreatePoint() to get the start point of the docked window) when |
| 495 // the attached_tabstrip_ is NULL and all the window's related bound |
| 496 // information are obtained from source_tabstrip_. So, we need to get the |
| 497 // first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise, |
| 498 // the window_create_point_ is not in the correct coordinate system. Please |
| 499 // refer to http://crbug.com/6223 comment #15 for detailed information. |
| 500 Tab* first_tab = source_tabstrip_->GetTabAt(0); |
465 views::View::ConvertPointToWidget(first_tab, &window_create_point_); | 501 views::View::ConvertPointToWidget(first_tab, &window_create_point_); |
466 } | 502 } |
467 | 503 |
468 gfx::Point DraggedTabController::GetWindowCreatePoint() const { | 504 gfx::Point DraggedTabController::GetWindowCreatePoint() const { |
469 gfx::Point cursor_point = GetCursorScreenPoint(); | 505 gfx::Point cursor_point = GetCursorScreenPoint(); |
470 if (dock_info_.type() != DockInfo::NONE) { | 506 if (dock_info_.type() != DockInfo::NONE) { |
471 // If we're going to dock, we need to return the exact coordinate, | 507 // If we're going to dock, we need to return the exact coordinate, |
472 // otherwise we may attempt to maximize on the wrong monitor. | 508 // otherwise we may attempt to maximize on the wrong monitor. |
473 return cursor_point; | 509 return cursor_point; |
474 } | 510 } |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 screen_point.y() <= upper_threshold) { | 717 screen_point.y() <= upper_threshold) { |
682 return tabstrip; | 718 return tabstrip; |
683 } | 719 } |
684 } | 720 } |
685 return NULL; | 721 return NULL; |
686 } | 722 } |
687 | 723 |
688 void DraggedTabController::Attach(TabStrip* attached_tabstrip, | 724 void DraggedTabController::Attach(TabStrip* attached_tabstrip, |
689 const gfx::Point& screen_point) { | 725 const gfx::Point& screen_point) { |
690 attached_tabstrip_ = attached_tabstrip; | 726 attached_tabstrip_ = attached_tabstrip; |
691 InitWindowCreatePoint(); | |
692 attached_tabstrip_->GenerateIdealBounds(); | 727 attached_tabstrip_->GenerateIdealBounds(); |
693 | 728 |
694 // We don't need the photo-booth while we're attached. | 729 // We don't need the photo-booth while we're attached. |
695 photobooth_.reset(NULL); | 730 photobooth_.reset(NULL); |
696 | 731 |
697 Tab* tab = GetTabMatchingDraggedContents(attached_tabstrip_); | 732 Tab* tab = GetTabMatchingDraggedContents(attached_tabstrip_); |
698 | 733 |
699 // Update the View first, so we can ask it for its bounds and determine | 734 // Update the View first, so we can ask it for its bounds and determine |
700 // where to insert the hidden Tab. | 735 // where to insert the hidden Tab. |
701 | 736 |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 default: | 1079 default: |
1045 NOTREACHED(); | 1080 NOTREACHED(); |
1046 break; | 1081 break; |
1047 } | 1082 } |
1048 } | 1083 } |
1049 // Compel the model to construct a new window for the detached TabContents. | 1084 // Compel the model to construct a new window for the detached TabContents. |
1050 gfx::Rect browser_rect = source_tabstrip_->GetWindow()->GetBounds(); | 1085 gfx::Rect browser_rect = source_tabstrip_->GetWindow()->GetBounds(); |
1051 gfx::Rect window_bounds( | 1086 gfx::Rect window_bounds( |
1052 GetWindowCreatePoint(), | 1087 GetWindowCreatePoint(), |
1053 gfx::Size(browser_rect.width(), browser_rect.height())); | 1088 gfx::Size(browser_rect.width(), browser_rect.height())); |
| 1089 // When modifying the following if statement, please make sure not to |
| 1090 // introduce issue listed in http://crbug.com/6223 comment #11. |
| 1091 bool rtl_ui = (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT); |
| 1092 bool has_dock_position = (dock_info_.type() != DockInfo::NONE); |
| 1093 if (rtl_ui && has_dock_position) { |
| 1094 // Mirror X axis so the docked tab is aligned using the mouse click as |
| 1095 // the top-right corner. |
| 1096 window_bounds.set_x(window_bounds.x() - window_bounds.width()); |
| 1097 } |
1054 Browser* new_browser = | 1098 Browser* new_browser = |
1055 source_tabstrip_->model()->delegate()->CreateNewStripWithContents( | 1099 source_tabstrip_->model()->delegate()->CreateNewStripWithContents( |
1056 dragged_contents_, window_bounds, dock_info_); | 1100 dragged_contents_, window_bounds, dock_info_); |
1057 new_browser->window()->Show(); | 1101 new_browser->window()->Show(); |
1058 CleanUpHiddenFrame(); | 1102 CleanUpHiddenFrame(); |
1059 } | 1103 } |
1060 | 1104 |
1061 return destroy_immediately; | 1105 return destroy_immediately; |
1062 } | 1106 } |
1063 | 1107 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 | 1233 |
1190 // The previous call made the window appear on top of the dragged window, | 1234 // The previous call made the window appear on top of the dragged window, |
1191 // move the dragged window to the front. | 1235 // move the dragged window to the front. |
1192 SetWindowPos(view_->GetWidget()->GetNativeView(), HWND_TOP, 0, 0, 0, 0, | 1236 SetWindowPos(view_->GetWidget()->GetNativeView(), HWND_TOP, 0, 0, 0, 0, |
1193 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); | 1237 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); |
1194 #else | 1238 #else |
1195 NOTIMPLEMENTED(); | 1239 NOTIMPLEMENTED(); |
1196 #endif | 1240 #endif |
1197 } | 1241 } |
1198 } | 1242 } |
OLD | NEW |