// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_WM_WINDOW_CYCLE_WINDOW_CYCLE_EVENT_FILTER_H_
#define ASH_WM_WINDOW_CYCLE_WINDOW_CYCLE_EVENT_FILTER_H_
#include <optional>
#include "ash/ash_export.h"
#include "ash/wm/window_cycle/window_cycle_controller.h"
#include "base/memory/raw_ptr.h"
#include "base/timer/timer.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
class GestureEvent;
class KeyEvent;
class MouseEvent;
class ScrollEvent;
} // namespace ui
namespace ash {
// Created by WindowCycleController when cycling through windows. Eats all key
// events and stops cycling when the necessary key sequence is encountered.
// Also allows users to cycle using right/left keys.
class ASH_EXPORT WindowCycleEventFilter : public ui::EventHandler {
public:
// The threshold of performing an action with a touchpad or mouse wheel
// scroll.
static constexpr float kHorizontalThresholdDp = 330.f;
WindowCycleEventFilter();
WindowCycleEventFilter(const WindowCycleEventFilter&) = delete;
WindowCycleEventFilter& operator=(const WindowCycleEventFilter&) = delete;
~WindowCycleEventFilter() override;
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
private:
// A struct containing the relevant data during a scroll session.
struct ScrollData {
int finger_count = 0;
// Values are cumulative (ex. |scroll_x| is the total x distance moved
// since the scroll began.
float scroll_x = 0.f;
float scroll_y = 0.f;
};
class AltReleaseHandler : public ui::EventHandler {
public:
AltReleaseHandler();
AltReleaseHandler(const AltReleaseHandler&) = delete;
AltReleaseHandler& operator=(const AltReleaseHandler&) = delete;
~AltReleaseHandler() override;
// ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
};
// Depending on the values of |event| either repeatedly cycle through windows,
// stop repeatedly cycling through windows, or cycle once.
void HandleTriggerKey(ui::KeyEvent* event);
// Returns whether the window cycle should repeatedly cycle in the
// direction given by |event|.
bool ShouldRepeatKey(ui::KeyEvent* event) const;
// Given |event|, determine if the user has used their mouse, i.e. moved or
// clicked.
void SetHasUserUsedMouse(ui::MouseEvent* event);
// Depending on the properties of |event|, may cycle the window cycle list or
// complete cycling.
void ProcessMouseEvent(ui::MouseEvent* event);
// Depending on the properties of |event|, may continuously scroll the window
// cycle list, move the cycle view's focus ring or complete cycling.
void ProcessGestureEvent(ui::GestureEvent* event);
// Called by ProcessMouseEvent() and OnScrollEvent(). May cycle the window
// cycle list. Returns true if the event has been handled and should not be
// processed further, false otherwise.
bool ProcessEventImpl(int finger_count, float delta_x, float delta_y);
// Based on the given scroll data, determine whether we should cycle the
// window cycle list. Return true if we do cycle the window cycle list,
// otherwise return false.
bool CycleWindowCycleList(int finger_count, float scroll_x, float scroll_y);
// Returns the cycling direction the window cycle should cycle depending on
// the combination of keys being pressed.
WindowCycleController::WindowCyclingDirection GetWindowCyclingDirection(
ui::KeyEvent* event) const;
// Returns the navigation direction to move the focus to.
WindowCycleController::KeyboardNavDirection GetKeyboardNavDirection(
ui::KeyEvent* event) const;
// When the user holds Alt+Tab, this timer is used to send repeated
// cycle commands to WindowCycleController. Note this is not accomplished
// by marking the Alt+Tab accelerator as "repeatable" in the accelerator
// table because we wish to control the repeat interval.
base::RepeatingTimer repeat_timer_;
AltReleaseHandler alt_release_handler_;
// Stores the initial mouse coordinates. Used to determine whether
// |has_user_used_mouse_| when this handles mouse events.
gfx::Point initial_mouse_location_;
// Bool for tracking whether the user has used their mouse. If this is false,
// mouse events should be filtered. This is to prevent the initial mouse
// position from triggering window cycle items' mouse event handlers despite a
// user not moving their mouse. Should be set to true when a user moves their
// mouse enough or clicks/drags/mousewheel scrolls.
// See crbug.com/114375.
bool has_user_used_mouse_ = false;
// Stores the current scroll session data. If it does not exist, there is no
// active scroll session.
std::optional<ScrollData> scroll_data_;
// When a user taps on a preview item it should move the focus ring to it.
// However, the focus ring should not move if the user is scrolling. Store
// |tapped_window_| on tap events and determine whether this is a tap or
// scroll with subsequent events.
raw_ptr<aura::Window> tapped_window_ = nullptr;
// Tracks whether the user is touch scrolling the window cycle list.
bool touch_scrolling_ = false;
};
} // namespace ash
#endif // ASH_WM_WINDOW_CYCLE_WINDOW_CYCLE_EVENT_FILTER_H_