chromium/chrome/browser/ui/views/tabs/tab_scrubber_chromeos.h

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_SCRUBBER_CHROMEOS_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_SCRUBBER_CHROMEOS_H_

#include <memory>

#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
#include "ui/events/event_handler.h"

class Browser;
class BrowserView;
class ImmersiveRevealedLock;
class Tab;
class TabStrip;

namespace gfx {
class Point;
}

// Class to enable quick tab switching via horizontal X finger swipes (see
// kFingerCount definition).
class TabScrubberChromeOS : public ui::EventHandler,
                            public BrowserListObserver,
                            public TabStripObserver {
 public:
  static constexpr int kFingerCount = 3;

  enum Direction { LEFT, RIGHT };

  TabScrubberChromeOS(const TabScrubberChromeOS&) = delete;
  TabScrubberChromeOS& operator=(const TabScrubberChromeOS&) = delete;

  // Returns a the single instance of a TabScrubberChromeOS.
  static TabScrubberChromeOS* GetInstance();

  // Returns the starting position (in tabstrip coordinates) of a swipe starting
  // in the tab at |index| and traveling in |direction|.
  static gfx::Point GetStartPoint(TabStrip* tab_strip,
                                  int index,
                                  TabScrubberChromeOS::Direction direction);

  int highlighted_tab() const { return highlighted_tab_; }
  bool IsActivationPending();

  void SetEnabled(bool enabled);

  // Synthesize an ScrollEvent given a x offset (in DIPs).
  // `is_fling_scroll_event` is set to true when the scroll event should be
  // fling scroll event.
  void SynthesizedScrollEvent(float x_offset, bool is_fling_scroll_event);

 private:
  friend class TabScrubberChromeOSTest;

  TabScrubberChromeOS();
  ~TabScrubberChromeOS() override;

  // ui::EventHandler overrides:
  void OnScrollEvent(ui::ScrollEvent* event) override;

  // BrowserListObserver overrides:
  void OnBrowserRemoved(Browser* browser) override;

  // TabStripObserver overrides.
  void OnTabAdded(int index) override;
  void OnTabMoved(int from_index, int to_index) override;
  void OnTabRemoved(int index) override;

  Browser* GetActiveBrowser();

  void BeginScrub(BrowserView* browser_view, float x_offset);
  // Returns true if it does finish the ongoing scrubbing.
  bool FinishScrub(bool activate);

  void ScheduleFinishScrubIfNeeded();

  // Updates the direction and the starting point of the swipe.
  void ScrubDirectionChanged(Direction direction);

  // Updates the X co-ordinate of the swipe taking into account RTL layouts if
  // any.
  void UpdateSwipeX(float x_offset);

  void UpdateHighlightedTab(Tab* new_tab, int new_index);

  bool GetEnabledForTesting() const { return enabled_; }

#if BUILDFLAG(IS_CHROMEOS_ASH)
  static bool MaybeDelegateHandlingToLacros(ui::ScrollEvent* event);
#endif

  // Are we currently scrubbing?.
  bool scrubbing_ = false;
  // The last browser we used for scrubbing, NULL if |scrubbing_| is false and
  // there is no pending work.
  raw_ptr<Browser> browser_ = nullptr;
  // The TabStrip of the active browser we're scrubbing.
  raw_ptr<TabStrip> tab_strip_ = nullptr;
  // The current accumulated x and y positions of a swipe, in the coordinates
  // of the TabStrip of |browser_|.
  float swipe_x_ = -1;
  int swipe_y_ = -1;
  // The direction the current swipe is headed.
  Direction swipe_direction_ = LEFT;
  // The index of the tab that is currently highlighted.
  int highlighted_tab_ = -1;
  // Timer to control a delayed activation of the |highlighted_tab_|.
  base::RetainingOneShotTimer activate_timer_;
  // True if the default activation delay should be used with |activate_timer_|.
  // A value of false means the |activate_timer_| gets a really long delay.
  bool use_default_activation_delay_ = true;
  // Forces the tabs to be revealed if we are in immersive fullscreen.
  std::unique_ptr<ImmersiveRevealedLock> immersive_reveal_lock_;
  // The time at which scrubbing started. Needed for UMA reporting of scrubbing
  // duration.
  base::TimeTicks scrubbing_start_time_;
  // If |enabled_|, tab scrubber takes events and determines whether tabs should
  // scrub. If not |enabled_|, tab scrubber ignores events. Should be disabled
  // when clashing interactions can occur, like window cycle list scrolling
  // gesture.
  bool enabled_ = true;
};

#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_SCRUBBER_CHROMEOS_H_