| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/ui/views/tabs/tab_strip.h" | 5 #include "chrome/browser/ui/views/tabs/tab_strip.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windowsx.h> | 8 #include <windowsx.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 virtual void AnimationCanceled(const ui::Animation* animation) { | 260 virtual void AnimationCanceled(const ui::Animation* animation) { |
| 261 tab_->set_dragging(false); | 261 tab_->set_dragging(false); |
| 262 } | 262 } |
| 263 | 263 |
| 264 private: | 264 private: |
| 265 BaseTab* tab_; | 265 BaseTab* tab_; |
| 266 | 266 |
| 267 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); | 267 DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); |
| 268 }; | 268 }; |
| 269 | 269 |
| 270 // If |dest| contains the point |point_in_source| the event handler from |dest| | 270 // If |dest| contains the rect |rect_in_source| the event handler from |dest| |
| 271 // is returned. Otherwise NULL is returned. | 271 // is returned. Otherwise NULL is returned. |
| 272 views::View* ConvertPointToViewAndGetEventHandler( | 272 views::View* ConvertRectToViewAndGetEventHandler( |
| 273 views::View* source, | 273 views::View* source, |
| 274 views::View* dest, | 274 views::View* dest, |
| 275 const gfx::Point& point_in_source) { | 275 const gfx::Rect& rect_in_source, |
| 276 gfx::Point dest_point(point_in_source); | 276 views::View::EventType type) { |
| 277 views::View::ConvertPointToTarget(source, dest, &dest_point); | 277 gfx::Rect dest_rect(rect_in_source); |
| 278 return dest->HitTestPoint(dest_point) ? | 278 views::View::ConvertRectToTarget(source, dest, &dest_rect); |
| 279 dest->GetEventHandlerForPoint(dest_point) : NULL; | 279 return dest->HitTestRect(dest_rect) ? |
| 280 dest->GetEventHandler(dest_rect, type) : NULL; |
| 280 } | 281 } |
| 281 | 282 |
| 282 } // namespace | 283 } // namespace |
| 283 | 284 |
| 284 /////////////////////////////////////////////////////////////////////////////// | 285 /////////////////////////////////////////////////////////////////////////////// |
| 285 // NewTabButton | 286 // NewTabButton |
| 286 // | 287 // |
| 287 // A subclass of button that hit-tests to the shape of the new tab button and | 288 // A subclass of button that hit-tests to the shape of the new tab button and |
| 288 // does custom drawing. | 289 // does custom drawing. |
| 289 | 290 |
| 290 class NewTabButton : public views::ImageButton { | 291 class NewTabButton : public views::ImageButton { |
| 291 public: | 292 public: |
| 292 NewTabButton(TabStrip* tab_strip, views::ButtonListener* listener); | 293 NewTabButton(TabStrip* tab_strip, views::ButtonListener* listener); |
| 293 virtual ~NewTabButton(); | 294 virtual ~NewTabButton(); |
| 294 | 295 |
| 295 // Set the background offset used to match the background image to the frame | 296 // Set the background offset used to match the background image to the frame |
| 296 // image. | 297 // image. |
| 297 void set_background_offset(const gfx::Point& offset) { | 298 void set_background_offset(const gfx::Point& offset) { |
| 298 background_offset_ = offset; | 299 background_offset_ = offset; |
| 299 } | 300 } |
| 300 | 301 |
| 302 View* GetEventHandler(const gfx::Rect& rect, EventType type) OVERRIDE { |
| 303 return View::GetEventHandler(rect, type); |
| 304 } |
| 305 |
| 301 protected: | 306 protected: |
| 302 // Overridden from views::View: | 307 // Overridden from views::View: |
| 303 virtual bool HasHitTestMask() const OVERRIDE; | 308 virtual bool HasHitTestMask() const OVERRIDE; |
| 304 virtual void GetHitTestMask(gfx::Path* path) const OVERRIDE; | 309 virtual void GetHitTestMask(gfx::Path* path) const OVERRIDE; |
| 305 #if defined(OS_WIN) && !defined(USE_AURA) | 310 #if defined(OS_WIN) && !defined(USE_AURA) |
| 306 void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; | 311 void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; |
| 307 #endif | 312 #endif |
| 308 virtual ui::EventResult OnGestureEvent( | 313 virtual ui::EventResult OnGestureEvent( |
| 309 const ui::GestureEvent& event) OVERRIDE; | 314 const ui::GestureEvent& event) OVERRIDE; |
| 310 void OnPaint(gfx::Canvas* canvas) OVERRIDE; | 315 void OnPaint(gfx::Canvas* canvas) OVERRIDE; |
| (...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 | 1340 |
| 1336 controller()->PerformDrop(drop_before, drop_index, url); | 1341 controller()->PerformDrop(drop_before, drop_index, url); |
| 1337 | 1342 |
| 1338 return GetDropEffect(event); | 1343 return GetDropEffect(event); |
| 1339 } | 1344 } |
| 1340 | 1345 |
| 1341 void TabStrip::GetAccessibleState(ui::AccessibleViewState* state) { | 1346 void TabStrip::GetAccessibleState(ui::AccessibleViewState* state) { |
| 1342 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST; | 1347 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST; |
| 1343 } | 1348 } |
| 1344 | 1349 |
| 1345 views::View* TabStrip::GetEventHandlerForPoint(const gfx::Point& point) { | 1350 double CoverageProportion(const gfx::Rect& rect_one, |
| 1351 const gfx::Rect& rect_two) { |
| 1352 gfx::Rect intersection = rect_one.Intersect(rect_two); |
| 1353 double rect_one_area = rect_one.size().GetArea(); |
| 1354 double rect_two_area = rect_two.size().GetArea(); |
| 1355 double intersection_area = intersection.size().GetArea(); |
| 1356 if ((rect_one_area <= 0) || (rect_two_area <= 0)) |
| 1357 return 0.0; |
| 1358 if (rect_one_area > rect_two_area) |
| 1359 return intersection_area / rect_two_area; |
| 1360 else |
| 1361 return intersection_area / rect_one_area; |
| 1362 } |
| 1363 |
| 1364 views::View* TabStrip::GetEventHandler(const gfx::Rect& rect, |
| 1365 EventType type) { |
| 1366 #if defined(OS_WIN) |
| 1367 if (ui::IsMouseEventFromTouch(WM_MOUSEMOVE) && |
| 1368 (type == EVENT_HANDLER_TYPE_MOUSE)) { |
| 1369 // This MOUSE event was actually generated from a touch. |
| 1370 // Views doesn't currently enable Windows OS touch. |
| 1371 int touch_size = 24; |
| 1372 return GetEventHandler(gfx::Rect(rect.x()-touch_size, rect.y()-touch_size, |
| 1373 touch_size*2, touch_size*2), |
| 1374 EVENT_HANDLER_TYPE_TOUCH); |
| 1375 } |
| 1376 #endif |
| 1377 |
| 1378 View* closest_view = NULL; |
| 1379 View* closest_untouched_view = NULL; |
| 1380 double max_proportion = 0; |
| 1381 int closest_distance = INT_MAX; |
| 1382 |
| 1346 if (!touch_layout_.get()) { | 1383 if (!touch_layout_.get()) { |
| 1347 // Return any view that isn't a Tab or this TabStrip immediately. We don't | 1384 // Return any view that isn't a Tab or this TabStrip immediately. We don't |
| 1348 // want to interfere. | 1385 // want to interfere. |
| 1349 views::View* v = View::GetEventHandlerForPoint(point); | 1386 views::View* v = View::GetEventHandler(rect, type); |
| 1350 if (v && v != this && v->GetClassName() != Tab::kViewClassName) | 1387 if (v && v != this && v->GetClassName() != Tab::kViewClassName) |
| 1351 return v; | 1388 return v; |
| 1352 | 1389 |
| 1353 // The display order doesn't necessarily match the child list order, so we | 1390 // The display order doesn't necessarily match the child list order, so we |
| 1354 // walk the display list hit-testing Tabs. Since the active tab always | 1391 // walk the display list hit-testing Tabs. Since the active tab always |
| 1355 // renders on top of adjacent tabs, it needs to be hit-tested before any | 1392 // renders on top of adjacent tabs, it needs to be hit-tested before any |
| 1356 // left-adjacent Tab, so we look ahead for it as we walk. | 1393 // left-adjacent Tab, so we look ahead for it as we walk. |
| 1357 for (int i = 0; i < tab_count(); ++i) { | 1394 for (int i = 0; i < tab_count(); ++i) { |
| 1358 Tab* next_tab = i < (tab_count() - 1) ? tab_at(i + 1) : NULL; | 1395 Tab* next_tab = i < (tab_count() - 1) ? tab_at(i + 1) : NULL; |
| 1359 if (next_tab && next_tab->IsActive() && IsPointInTab(next_tab, point)) | 1396 if (next_tab && next_tab->IsActive() && IsRectInTab(next_tab, rect)) |
| 1360 return next_tab; | 1397 return next_tab; |
| 1361 if (IsPointInTab(tab_at(i), point)) | 1398 if (IsRectInTab(tab_at(i), rect)) |
| 1362 return tab_at(i); | 1399 return tab_at(i); |
| 1363 } | 1400 } |
| 1364 } else { | 1401 } else { |
| 1402 // Test for new tab button.... |
| 1365 if (newtab_button_->visible()) { | 1403 if (newtab_button_->visible()) { |
| 1366 views::View* view = | 1404 views::View* view = |
| 1367 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); | 1405 ConvertRectToViewAndGetEventHandler( |
| 1406 this, newtab_button_, rect, type); |
| 1368 if (view) | 1407 if (view) |
| 1369 return view; | 1408 return view; |
| 1370 } | 1409 } |
| 1371 Tab* tab = FindTabForEvent(point); | 1410 // Otherwise, check for other tabs.... |
| 1411 Tab* tab = FindTabForEvent(rect); |
| 1372 if (tab) | 1412 if (tab) |
| 1373 return ConvertPointToViewAndGetEventHandler(this, tab, point); | 1413 return ConvertRectToViewAndGetEventHandler(this, tab, rect, type); |
| 1374 } | 1414 } |
| 1375 return this; | 1415 return this; |
| 1376 } | 1416 } |
| 1377 | 1417 |
| 1378 int TabStrip::GetMiniTabCount() const { | 1418 int TabStrip::GetMiniTabCount() const { |
| 1379 int mini_count = 0; | 1419 int mini_count = 0; |
| 1380 while (mini_count < tab_count() && tab_at(mini_count)->data().mini) | 1420 while (mini_count < tab_count() && tab_at(mini_count)->data().mini) |
| 1381 mini_count++; | 1421 mini_count++; |
| 1382 return mini_count; | 1422 return mini_count; |
| 1383 } | 1423 } |
| (...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2445 true); | 2485 true); |
| 2446 } | 2486 } |
| 2447 | 2487 |
| 2448 bool TabStrip::IsPointInTab(Tab* tab, | 2488 bool TabStrip::IsPointInTab(Tab* tab, |
| 2449 const gfx::Point& point_in_tabstrip_coords) { | 2489 const gfx::Point& point_in_tabstrip_coords) { |
| 2450 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); | 2490 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); |
| 2451 View::ConvertPointToTarget(this, tab, &point_in_tab_coords); | 2491 View::ConvertPointToTarget(this, tab, &point_in_tab_coords); |
| 2452 return tab->HitTestPoint(point_in_tab_coords); | 2492 return tab->HitTestPoint(point_in_tab_coords); |
| 2453 } | 2493 } |
| 2454 | 2494 |
| 2495 bool TabStrip::IsRectInTab(Tab* tab, |
| 2496 const gfx::Rect& rect_in_tabstrip_coords) { |
| 2497 gfx::Rect rect_in_tab_coords(rect_in_tabstrip_coords); |
| 2498 View::ConvertRectToTarget(this, tab, &rect_in_tab_coords); |
| 2499 return tab->HitTestRect(rect_in_tab_coords); |
| 2500 } |
| 2501 |
| 2455 int TabStrip::GetStartXForNormalTabs() const { | 2502 int TabStrip::GetStartXForNormalTabs() const { |
| 2456 int mini_tab_count = GetMiniTabCount(); | 2503 int mini_tab_count = GetMiniTabCount(); |
| 2457 if (mini_tab_count == 0) | 2504 if (mini_tab_count == 0) |
| 2458 return 0; | 2505 return 0; |
| 2459 return mini_tab_count * (Tab::GetMiniWidth() + tab_h_offset()) + | 2506 return mini_tab_count * (Tab::GetMiniWidth() + tab_h_offset()) + |
| 2460 kMiniToNonMiniGap; | 2507 kMiniToNonMiniGap; |
| 2461 } | 2508 } |
| 2462 | 2509 |
| 2510 Tab* TabStrip::FindTabForEvent(const gfx::Rect& rect) { |
| 2511 DCHECK(touch_layout_.get()); |
| 2512 int active_tab_index = touch_layout_->active_index(); |
| 2513 Tab* tab = NULL; |
| 2514 if (active_tab_index != -1) { |
| 2515 tab = FindTabForEventFrom(rect, active_tab_index, -1); |
| 2516 if (!tab) |
| 2517 tab = FindTabForEventFrom(rect, active_tab_index + 1, 1); |
| 2518 } else if (tab_count()) { |
| 2519 tab = FindTabForEventFrom(rect, 0, 1); |
| 2520 } |
| 2521 return tab; |
| 2522 } |
| 2523 |
| 2463 Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { | 2524 Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { |
| 2464 DCHECK(touch_layout_.get()); | 2525 DCHECK(touch_layout_.get()); |
| 2465 int active_tab_index = touch_layout_->active_index(); | 2526 int active_tab_index = touch_layout_->active_index(); |
| 2466 Tab* tab = NULL; | 2527 Tab* tab = NULL; |
| 2467 if (active_tab_index != -1) { | 2528 if (active_tab_index != -1) { |
| 2468 tab = FindTabForEventFrom(point, active_tab_index, -1); | 2529 tab = FindTabForEventFrom(point, active_tab_index, -1); |
| 2469 if (!tab) | 2530 if (!tab) |
| 2470 tab = FindTabForEventFrom(point, active_tab_index + 1, 1); | 2531 tab = FindTabForEventFrom(point, active_tab_index + 1, 1); |
| 2471 } else if (tab_count()) { | 2532 } else if (tab_count()) { |
| 2472 tab = FindTabForEventFrom(point, 0, 1); | 2533 tab = FindTabForEventFrom(point, 0, 1); |
| 2473 } | 2534 } |
| 2474 return tab; | 2535 return tab; |
| 2475 } | 2536 } |
| 2476 | 2537 |
| 2538 Tab* TabStrip::FindTabForEventFrom(const gfx::Rect& rect, |
| 2539 int start, |
| 2540 int delta) { |
| 2541 // |start| equals tab_count() when there are only pinned tabs. |
| 2542 if (start == tab_count()) |
| 2543 start += delta; |
| 2544 for (int i = start; i >= 0 && i < tab_count(); i += delta) { |
| 2545 if (IsRectInTab(tab_at(i), rect)) |
| 2546 return tab_at(i); |
| 2547 } |
| 2548 return NULL; |
| 2549 } |
| 2550 |
| 2477 Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point, | 2551 Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point, |
| 2478 int start, | 2552 int start, |
| 2479 int delta) { | 2553 int delta) { |
| 2480 // |start| equals tab_count() when there are only pinned tabs. | 2554 // |start| equals tab_count() when there are only pinned tabs. |
| 2481 if (start == tab_count()) | 2555 if (start == tab_count()) |
| 2482 start += delta; | 2556 start += delta; |
| 2483 for (int i = start; i >= 0 && i < tab_count(); i += delta) { | 2557 for (int i = start; i >= 0 && i < tab_count(); i += delta) { |
| 2484 if (IsPointInTab(tab_at(i), point)) | 2558 if (IsPointInTab(tab_at(i), point)) |
| 2485 return tab_at(i); | 2559 return tab_at(i); |
| 2486 } | 2560 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2561 if (!adjust_layout_) | 2635 if (!adjust_layout_) |
| 2562 return false; | 2636 return false; |
| 2563 | 2637 |
| 2564 #if !defined(OS_CHROMEOS) | 2638 #if !defined(OS_CHROMEOS) |
| 2565 if (ui::GetDisplayLayout() != ui::LAYOUT_TOUCH) | 2639 if (ui::GetDisplayLayout() != ui::LAYOUT_TOUCH) |
| 2566 return false; | 2640 return false; |
| 2567 #endif | 2641 #endif |
| 2568 | 2642 |
| 2569 return true; | 2643 return true; |
| 2570 } | 2644 } |
| OLD | NEW |