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
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_
6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_
10 #include "base/compiler_specific.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/timer/timer.h"
13 #include "chrome/browser/ui/views/tabs/tab.h"
14 #include "chrome/browser/ui/views/tabs/tab_controller.h"
15 #include "ui/gfx/animation/animation_container.h"
16 #include "ui/gfx/geometry/point.h"
17 #include "ui/gfx/geometry/rect.h"
18 #include "ui/views/animation/bounds_animator.h"
19 #include "ui/views/controls/button/image_button.h"
20 #include "ui/views/mouse_watcher.h"
21 #include "ui/views/view.h"
22 #include "ui/views/view_model.h"
23 #include "ui/views/view_targeter_delegate.h"
26 class StackedTabStripLayout
;
28 class TabDragController
;
29 class TabStripController
;
30 class TabStripObserver
;
33 class ListSelectionModel
;
40 ///////////////////////////////////////////////////////////////////////////////
44 // A View that represents the TabStripModel. The TabStrip has the
45 // following responsibilities:
46 // - It implements the TabStripModelObserver interface, and acts as a
47 // container for Tabs, and is also responsible for creating them.
48 // - It takes part in Tab Drag & Drop with Tab, TabDragHelper and
49 // DraggedTab, focusing on tasks that require reshuffling other tabs
50 // in response to dragged tabs.
52 ///////////////////////////////////////////////////////////////////////////////
53 class TabStrip
: public views::View
,
54 public views::ButtonListener
,
55 public views::MouseWatcherListener
,
56 public views::ViewTargeterDelegate
,
57 public TabController
{
59 static const char kViewClassName
[];
61 // Horizontal offset for the new tab button to bring it closer to the
63 static const int kNewTabButtonHorizontalOffset
;
65 // The vertical offset of the tab strip button. This offset applies only to
67 static const int kNewTabButtonVerticalOffset
;
69 // The size of the new tab button must be hardcoded because we need to be
70 // able to lay it out before we are able to get its image from the
71 // ui::ThemeProvider. It also makes sense to do this, because the size of the
72 // new tab button should not need to be calculated dynamically.
73 static const int kNewTabButtonAssetWidth
;
74 static const int kNewTabButtonAssetHeight
;
76 explicit TabStrip(TabStripController
* controller
);
79 // Add and remove observers to changes within this TabStrip.
80 void AddObserver(TabStripObserver
* observer
);
81 void RemoveObserver(TabStripObserver
* observer
);
83 // If |adjust_layout| is true the stacked layout changes based on whether the
84 // user uses a mouse or a touch device with the tabstrip.
85 void set_adjust_layout(bool adjust_layout
) { adjust_layout_
= adjust_layout
; }
87 // |stacked_layout_| defines what should happen when the tabs won't fit at
88 // their ideal size. When |stacked_layout_| is true the tabs are always sized
89 // to their ideal size and stacked on top of each other so that only a certain
90 // set of tabs are visible. This is used when the user uses a touch device.
91 // When |stacked_layout_| is false the tabs shrink to accommodate the
92 // available space. This is the default.
93 bool stacked_layout() const { return stacked_layout_
; }
95 // Sets |stacked_layout_| and animates if necessary.
96 void SetStackedLayout(bool stacked_layout
);
98 // Returns the bounds of the new tab button.
99 gfx::Rect
GetNewTabButtonBounds();
101 // Returns true if the new tab button should be sized to the top of the tab
103 bool SizeTabButtonToTopOfTabStrip();
105 // Starts highlighting the tab at the specified index.
106 void StartHighlight(int model_index
);
108 // Stops all tab higlighting.
109 void StopAllHighlighting();
111 // Adds a tab at the specified index.
112 void AddTabAt(int model_index
, const TabRendererData
& data
, bool is_active
);
115 void MoveTab(int from_model_index
,
117 const TabRendererData
& data
);
119 // Removes a tab at the specified index.
120 void RemoveTabAt(int model_index
);
122 // Sets the tab data at the specified model index.
123 void SetTabData(int model_index
, const TabRendererData
& data
);
125 // Returns true if the tab is not partly or fully clipped (due to overflow),
126 // and the tab couldn't become partly clipped due to changing the selected tab
127 // (for example, if currently the strip has the last tab selected, and
128 // changing that to the first tab would cause |tab| to be pushed over enough
130 bool ShouldTabBeVisible(const Tab
* tab
) const;
132 // Invoked from the controller when the close initiates from the TabController
133 // (the user clicked the tab close button or middle clicked the tab). This is
134 // invoked from Close. Because of unload handlers Close is not always
135 // immediately followed by RemoveTabAt.
136 void PrepareForCloseAt(int model_index
, CloseTabSource source
);
138 // Invoked when the selection changes from |old_selection| to
140 void SetSelection(const ui::ListSelectionModel
& old_selection
,
141 const ui::ListSelectionModel
& new_selection
);
143 // Invoked when the title of a tab changes and the tab isn't loading.
144 void TabTitleChangedNotLoading(int model_index
);
146 // Retrieves the ideal bounds for the Tab at the specified index.
147 const gfx::Rect
& ideal_bounds(int tab_data_index
) {
148 return tabs_
.ideal_bounds(tab_data_index
);
151 // Returns the Tab at |index|.
152 Tab
* tab_at(int index
) const { return tabs_
.view_at(index
); }
154 // Returns the index of the specified tab in the model coordinate system, or
155 // -1 if tab is closing or not valid.
156 int GetModelIndexOfTab(const Tab
* tab
) const;
158 // Gets the number of Tabs in the tab strip.
159 int tab_count() const { return tabs_
.view_size(); }
161 // Cover method for TabStripController::GetCount.
162 int GetModelCount() const;
164 // Cover method for TabStripController::IsValidIndex.
165 bool IsValidModelIndex(int model_index
) const;
167 TabStripController
* controller() const { return controller_
.get(); }
169 // Returns true if a drag session is currently active.
170 bool IsDragSessionActive() const;
172 // Returns true if a tab is being dragged into this tab strip.
173 bool IsActiveDropTarget() const;
175 // Returns true if the tab strip is editable. Returns false if the tab strip
176 // is being dragged or animated to prevent extensions from messing things up
177 // while that's happening.
178 bool IsTabStripEditable() const;
180 // Returns false when there is a drag operation in progress so that the frame
182 bool IsTabStripCloseable() const;
184 // Updates the loading animations displayed by tabs in the tabstrip to the
186 void UpdateLoadingAnimations();
188 // Returns true if the specified point (in TabStrip coordinates) is in the
189 // window caption area of the browser window.
190 bool IsPositionInWindowCaption(const gfx::Point
& point
);
192 // Returns true if the specified rect (in TabStrip coordinates) intersects
193 // the window caption area of the browser window.
194 bool IsRectInWindowCaption(const gfx::Rect
& rect
);
196 // Set the background offset used by inactive tabs to match the frame image.
197 void SetBackgroundOffset(const gfx::Point
& offset
);
199 // Sets a painting style with miniature "tab indicator" rectangles at the top.
200 void SetImmersiveStyle(bool enable
);
202 // Returns true if Tabs in this TabStrip are currently changing size or
204 bool IsAnimating() const;
206 // Stops any ongoing animations. If |layout| is true and an animation is
207 // ongoing this does a layout.
208 void StopAnimating(bool layout
);
210 // Called to indicate whether the given URL is a supported file.
211 void FileSupported(const GURL
& url
, bool supported
);
213 // TabController overrides:
214 const ui::ListSelectionModel
& GetSelectionModel() override
;
215 bool SupportsMultipleSelection() override
;
216 bool ShouldHideCloseButtonForInactiveTabs() override
;
217 void SelectTab(Tab
* tab
) override
;
218 void ExtendSelectionTo(Tab
* tab
) override
;
219 void ToggleSelected(Tab
* tab
) override
;
220 void AddSelectionFromAnchorTo(Tab
* tab
) override
;
221 void CloseTab(Tab
* tab
, CloseTabSource source
) override
;
222 void ToggleTabAudioMute(Tab
* tab
) override
;
223 void ShowContextMenuForTab(Tab
* tab
,
225 ui::MenuSourceType source_type
) override
;
226 bool IsActiveTab(const Tab
* tab
) const override
;
227 bool IsTabSelected(const Tab
* tab
) const override
;
228 bool IsTabPinned(const Tab
* tab
) const override
;
231 const ui::LocatedEvent
& event
,
232 const ui::ListSelectionModel
& original_selection
) override
;
233 void ContinueDrag(views::View
* view
, const ui::LocatedEvent
& event
) override
;
234 bool EndDrag(EndDragReason reason
) override
;
235 Tab
* GetTabAt(Tab
* tab
, const gfx::Point
& tab_in_tab_coordinates
) override
;
236 void OnMouseEventInTab(views::View
* source
,
237 const ui::MouseEvent
& event
) override
;
238 bool ShouldPaintTab(const Tab
* tab
, gfx::Rect
* clip
) override
;
239 bool IsImmersiveStyle() const override
;
240 void UpdateTabAccessibilityState(const Tab
* tab
,
241 ui::AXViewState
* state
) override
;
243 // MouseWatcherListener overrides:
244 void MouseMovedOutOfHost() override
;
246 // views::View overrides:
247 void Layout() override
;
248 void PaintChildren(const ui::PaintContext
& context
) override
;
249 const char* GetClassName() const override
;
250 gfx::Size
GetPreferredSize() const override
;
251 // NOTE: the drag and drop methods are invoked from FrameView. This is done
252 // to allow for a drop region that extends outside the bounds of the TabStrip.
253 void OnDragEntered(const ui::DropTargetEvent
& event
) override
;
254 int OnDragUpdated(const ui::DropTargetEvent
& event
) override
;
255 void OnDragExited() override
;
256 int OnPerformDrop(const ui::DropTargetEvent
& event
) override
;
257 void GetAccessibleState(ui::AXViewState
* state
) override
;
258 views::View
* GetTooltipHandlerForPoint(const gfx::Point
& point
) override
;
260 // Returns preferred height in immersive style.
261 static int GetImmersiveHeight();
264 typedef std::vector
<Tab
*> Tabs
;
265 typedef std::map
<int, Tabs
> TabsClosingMap
;
266 typedef std::pair
<TabsClosingMap::iterator
,
267 Tabs::iterator
> FindClosingTabResult
;
269 class RemoveTabDelegate
;
271 friend class TabDragController
;
272 friend class TabDragControllerTest
;
273 friend class TabStripTest
;
274 FRIEND_TEST_ALL_PREFIXES(TabDragControllerTest
, GestureEndShouldEndDragTest
);
275 FRIEND_TEST_ALL_PREFIXES(TabStripTest
, TabHitTestMaskWhenStacked
);
276 FRIEND_TEST_ALL_PREFIXES(TabStripTest
, TabCloseButtonVisibilityWhenStacked
);
278 // Used during a drop session of a url. Tracks the position of the drop as
279 // well as a window used to highlight where the drop occurs.
281 DropInfo(int drop_index
,
284 views::Widget
* context
);
287 // Index of the tab to drop on. If drop_before is true, the drop should
288 // occur between the tab at drop_index - 1 and drop_index.
289 // WARNING: if drop_before is true it is possible this will == tab_count,
290 // which indicates the drop should create a new tab at the end of the tabs.
294 // Direction the arrow should point in. If true, the arrow is displayed
295 // above the tab and points down. If false, the arrow is displayed beneath
296 // the tab and points up.
299 // Renders the drop indicator.
300 views::Widget
* arrow_window
;
301 views::ImageView
* arrow_view
;
303 // The URL for the drop event.
306 // Whether the MIME type of the file pointed to by |url| is supported.
310 DISALLOW_COPY_AND_ASSIGN(DropInfo
);
313 // Horizontal gap between pinned and non-pinned tabs.
314 static const int kPinnedToNonPinnedGap
;
318 // Creates and returns a new tab. The caller owners the returned tab.
321 // Invoked from |AddTabAt| after the newly created tab has been inserted.
322 void StartInsertTabAnimation(int model_index
);
324 // Invoked from |MoveTab| after |tab_data_| has been updated to animate the
326 void StartMoveTabAnimation();
328 // Starts the remove tab animation.
329 void StartRemoveTabAnimation(int model_index
);
331 // Schedules the animations and bounds changes necessary for a remove tab
333 void ScheduleRemoveTabAnimation(Tab
* tab
);
335 // Animates all the views to their ideal bounds.
336 // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds
337 // currently set in ideal_bounds.
338 void AnimateToIdealBounds();
340 // Returns whether the highlight button should be highlighted after a remove.
341 bool ShouldHighlightCloseButtonAfterRemove();
343 // Invoked from Layout if the size changes or layout is really needed.
346 // Sets the visibility state of all tabs based on ShouldTabBeVisible().
347 void SetTabVisibility();
349 // Drags the active tab by |delta|. |initial_positions| is the x-coordinates
350 // of the tabs when the drag started.
351 void DragActiveTab(const std::vector
<int>& initial_positions
, int delta
);
353 // Sets the ideal bounds x-coordinates to |positions|.
354 void SetIdealBoundsFromPositions(const std::vector
<int>& positions
);
356 // Stacks the dragged tabs. This is used if the drag operation is
357 // MOVE_VISIBLE_TABS and the tabs don't fill the tabstrip. When this happens
358 // the active tab follows the mouse and the other tabs stack around it.
359 void StackDraggedTabs(int delta
);
361 // Returns true if dragging has resulted in temporarily stacking the tabs.
362 bool IsStackingDraggedTabs() const;
364 // Invoked during drag to layout the tabs being dragged in |tabs| at
365 // |location|. If |initial_drag| is true, this is the initial layout after the
366 // user moved the mouse far enough to trigger a drag.
367 void LayoutDraggedTabsAt(const Tabs
& tabs
,
369 const gfx::Point
& location
,
372 // Calculates the bounds needed for each of the tabs, placing the result in
374 void CalculateBoundsForDraggedTabs(const Tabs
& tabs
,
375 std::vector
<gfx::Rect
>* bounds
);
377 // Returns the size needed for the specified tabs. This is invoked during drag
378 // and drop to calculate offsets and positioning.
379 int GetSizeNeededForTabs(const Tabs
& tabs
);
381 // Returns the number of pinned tabs.
382 int GetPinnedTabCount() const;
384 // Returns the last tab in the strip that's actually visible. This will be
385 // the actual last tab unless the strip is in the overflow state.
386 const Tab
* GetLastVisibleTab() const;
388 // Adds the tab at |index| to |tabs_closing_map_| and removes the tab from
390 void RemoveTabFromViewModel(int index
);
392 // Cleans up the Tab from the TabStrip. This is called from the tab animation
393 // code and is not a general-purpose method.
394 void RemoveAndDeleteTab(Tab
* tab
);
396 // Adjusts the indices of all tabs in |tabs_closing_map_| whose index is
397 // >= |index| to have a new index of |index + delta|.
398 void UpdateTabsClosingMap(int index
, int delta
);
400 // Used by TabDragController when the user starts or stops dragging tabs.
401 void StartedDraggingTabs(const Tabs
& tabs
);
403 // Invoked when TabDragController detaches a set of tabs.
404 void DraggedTabsDetached();
406 // Used by TabDragController when the user stops dragging tabs. |move_only| is
407 // true if the move behavior is TabDragController::MOVE_VISIBILE_TABS.
408 // |completed| is true if the drag operation completed successfully, false if
410 void StoppedDraggingTabs(const Tabs
& tabs
,
411 const std::vector
<int>& initial_positions
,
415 // Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known
416 // |is_first_tab| is set to true.
417 void StoppedDraggingTab(Tab
* tab
, bool* is_first_tab
);
419 // Takes ownership of |controller|.
420 void OwnDragController(TabDragController
* controller
);
422 // Destroys the current TabDragController. This cancel the existing drag
424 void DestroyDragController();
426 // Releases ownership of the current TabDragController.
427 TabDragController
* ReleaseDragController();
429 // Finds |tab| in the |tab_closing_map_| and returns a pair of iterators
430 // indicating precisely where it is.
431 FindClosingTabResult
FindClosingTab(const Tab
* tab
);
433 // Paints all the tabs in |tabs_closing_map_[index]|.
434 void PaintClosingTabs(int index
, const ui::PaintContext
& context
);
436 // Invoked when a mouse event occurs over |source|. Potentially switches the
437 // |stacked_layout_|.
438 void UpdateStackedLayoutFromMouseEvent(views::View
* source
,
439 const ui::MouseEvent
& event
);
441 // -- Tab Resize Layout -----------------------------------------------------
443 // Returns the exact (unrounded) current width of each tab.
444 void GetCurrentTabWidths(double* unselected_width
,
445 double* selected_width
) const;
447 // Returns the exact (unrounded) desired width of each tab, based on the
448 // desired strip width and number of tabs. If
449 // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in
450 // calculating the desired strip width; otherwise we use the current width.
451 // |pinned_tab_count| gives the number of pinned tabs and |tab_count| the
452 // number of pinned and non-pinned tabs.
453 void GetDesiredTabWidths(int tab_count
,
454 int pinned_tab_count
,
455 double* unselected_width
,
456 double* selected_width
) const;
458 // Perform an animated resize-relayout of the TabStrip immediately.
459 void ResizeLayoutTabs();
461 // Invokes ResizeLayoutTabs() as long as we're not in a drag session. If we
462 // are in a drag session this restarts the timer.
463 void ResizeLayoutTabsFromTouch();
465 // Restarts |resize_layout_timer_|.
466 void StartResizeLayoutTabsFromTouchTimer();
468 // Sets the bounds of the tabs to |tab_bounds|.
469 void SetTabBoundsForDrag(const std::vector
<gfx::Rect
>& tab_bounds
);
471 // Ensure that the message loop observer used for event spying is added and
472 // removed appropriately so we can tell when to resize layout the tab strip.
473 void AddMessageLoopObserver();
474 void RemoveMessageLoopObserver();
476 // -- Link Drag & Drop ------------------------------------------------------
478 // Returns the bounds to render the drop at, in screen coordinates. Sets
479 // |is_beneath| to indicate whether the arrow is beneath the tab, or above
481 gfx::Rect
GetDropBounds(int drop_index
, bool drop_before
, bool* is_beneath
);
483 // Updates the location of the drop based on the event.
484 void UpdateDropIndex(const ui::DropTargetEvent
& event
);
486 // Sets the location of the drop, repainting as necessary.
487 void SetDropIndex(int tab_data_index
, bool drop_before
);
489 // Returns the drop effect for dropping a URL on the tab strip. This does
490 // not query the data in anyway, it only looks at the source operations.
491 int GetDropEffect(const ui::DropTargetEvent
& event
);
493 // Returns the image to use for indicating a drop on a tab. If is_down is
494 // true, this returns an arrow pointing down.
495 static gfx::ImageSkia
* GetDropArrowImage(bool is_down
);
497 // -- Animations ------------------------------------------------------------
499 // Invoked prior to starting a new animation.
500 void PrepareForAnimation();
502 // Generates the ideal bounds for each of the tabs as well as the new tab
504 void GenerateIdealBounds();
506 // Generates the ideal bounds for the pinned tabs. Returns the index to
507 // position the first non-pinned tab and sets |first_non_pinned_index| to the
508 // index of the first non-pinned tab.
509 int GenerateIdealBoundsForPinnedTabs(int* first_non_pinned_index
);
511 // Returns the width needed for the new tab button (and padding).
512 static int new_tab_button_width() {
513 return kNewTabButtonAssetWidth
+ kNewTabButtonHorizontalOffset
;
516 // Returns the width of the area that contains tabs. This does not include
517 // the width of the new tab button.
518 int tab_area_width() const { return width() - new_tab_button_width(); }
520 // Starts various types of TabStrip animations.
521 void StartResizeLayoutAnimation();
522 void StartPinnedTabAnimation();
523 void StartMouseInitiatedRemoveTabAnimation(int model_index
);
525 // Returns true if the specified point in TabStrip coords is within the
526 // hit-test region of the specified Tab.
527 bool IsPointInTab(Tab
* tab
, const gfx::Point
& point_in_tabstrip_coords
);
529 // -- Touch Layout ----------------------------------------------------------
531 // Returns the position normal tabs start at.
532 int GetStartXForNormalTabs() const;
534 // Returns the tab to use for event handling. This uses FindTabForEventFrom()
535 // to do the actual searching.
536 Tab
* FindTabForEvent(const gfx::Point
& point
);
538 // Returns the tab to use for event handling starting at index |start| and
539 // iterating by |delta|.
540 Tab
* FindTabForEventFrom(const gfx::Point
& point
, int start
, int delta
);
542 // For a given point, finds a tab that is hit by the point. If the point hits
543 // an area on which two tabs are overlapping, the tab is selected as follows:
544 // - If one of the tabs is active, select it.
545 // - Select the left one.
546 // If no tabs are hit, returns NULL.
547 views::View
* FindTabHitByPoint(const gfx::Point
& point
);
549 // Returns the x-coordinates of the tabs.
550 std::vector
<int> GetTabXCoordinates();
552 // Creates/Destroys |touch_layout_| as necessary.
553 void SwapLayoutIfNecessary();
555 // Returns true if |touch_layout_| is needed.
556 bool NeedsTouchLayout() const;
558 // Sets the value of |reset_to_shrink_on_exit_|. If true |mouse_watcher_| is
559 // used to track when the mouse truly exits the tabstrip and the stacked
561 void SetResetToShrinkOnExit(bool value
);
563 // views::ButtonListener implementation:
564 void ButtonPressed(views::Button
* sender
, const ui::Event
& event
) override
;
567 const views::View
* GetViewByID(int id
) const override
;
568 bool OnMousePressed(const ui::MouseEvent
& event
) override
;
569 bool OnMouseDragged(const ui::MouseEvent
& event
) override
;
570 void OnMouseReleased(const ui::MouseEvent
& event
) override
;
571 void OnMouseCaptureLost() override
;
572 void OnMouseMoved(const ui::MouseEvent
& event
) override
;
573 void OnMouseEntered(const ui::MouseEvent
& event
) override
;
575 // ui::EventHandler overrides.
576 void OnGestureEvent(ui::GestureEvent
* event
) override
;
578 // views::ViewTargeterDelegate:
579 views::View
* TargetForRect(views::View
* root
, const gfx::Rect
& rect
) override
;
581 // -- Member Variables ------------------------------------------------------
583 // There is a one-to-one mapping between each of the tabs in the
584 // TabStripController (TabStripModel) and |tabs_|. Because we animate tab
585 // removal there exists a period of time where a tab is displayed but not in
586 // the model. When this occurs the tab is removed from |tabs_| and placed in
587 // |tabs_closing_map_|. When the animation completes the tab is removed from
588 // |tabs_closing_map_|. The painting code ensures both sets of tabs are
589 // painted, and the event handling code ensures only tabs in |tabs_| are used.
590 views::ViewModelT
<Tab
> tabs_
;
591 TabsClosingMap tabs_closing_map_
;
593 scoped_ptr
<TabStripController
> controller_
;
595 // The "New Tab" button.
596 NewTabButton
* newtab_button_
;
598 // Ideal bounds of the new tab button.
599 gfx::Rect newtab_button_bounds_
;
601 // The current widths of various types of tabs. We save these so that, as
602 // users close tabs while we're holding them at the same size, we can lay out
603 // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving
604 // them all at their existing, rounded widths.
605 double current_unselected_width_
;
606 double current_selected_width_
;
608 // If this value is nonnegative, it is used in GetDesiredTabWidths() to
609 // calculate how much space in the tab strip to use for tabs. Most of the
610 // time this will be -1, but while we're handling closing a tab via the mouse,
611 // we'll set this to the edge of the last tab before closing, so that if we
612 // are closing the last tab and need to resize immediately, we'll resize only
613 // back to this width, thus once again placing the last tab under the mouse
615 int available_width_for_tabs_
;
617 // True if PrepareForCloseAt has been invoked. When true remove animations
618 // preserve current tab bounds.
621 // Valid for the lifetime of a drag over us.
622 scoped_ptr
<DropInfo
> drop_info_
;
624 // To ensure all tabs pulse at the same time they share the same animation
625 // container. This is that animation container.
626 scoped_refptr
<gfx::AnimationContainer
> animation_container_
;
628 // MouseWatcher is used for two things:
629 // . When a tab is closed to reset the layout.
630 // . When a mouse is used and the layout dynamically adjusts and is currently
631 // stacked (|stacked_layout_| is true).
632 scoped_ptr
<views::MouseWatcher
> mouse_watcher_
;
634 // The controller for a drag initiated from a Tab. Valid for the lifetime of
636 scoped_ptr
<TabDragController
> drag_controller_
;
638 views::BoundsAnimator bounds_animator_
;
640 // Size we last layed out at.
641 gfx::Size last_layout_size_
;
643 // See description above stacked_layout().
644 bool stacked_layout_
;
646 // Should the layout dynamically adjust?
649 // Only used while in touch mode.
650 scoped_ptr
<StackedTabStripLayout
> touch_layout_
;
652 // If true the |stacked_layout_| is set to false when the mouse exits the
653 // tabstrip (as determined using MouseWatcher).
654 bool reset_to_shrink_on_exit_
;
656 // Location of the mouse at the time of the last move.
657 gfx::Point last_mouse_move_location_
;
659 // Time of the last mouse move event.
660 base::TimeTicks last_mouse_move_time_
;
662 // Number of mouse moves.
663 int mouse_move_count_
;
665 // Timer used when a tab is closed and we need to relayout. Only used when a
666 // tab close comes from a touch device.
667 base::OneShotTimer
<TabStrip
> resize_layout_timer_
;
669 // True if tabs are painted as rectangular light-bars.
670 bool immersive_style_
;
673 typedef base::ObserverList
<TabStripObserver
> TabStripObservers
;
674 TabStripObservers observers_
;
676 DISALLOW_COPY_AND_ASSIGN(TabStrip
);
679 #endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_H_