#ifndef ASH_SHELF_DRAG_HANDLE_H_
#define ASH_SHELF_DRAG_HANDLE_H_
#include "ash/ash_export.h"
#include "ash/controls/contextual_nudge.h"
#include "ash/controls/contextual_tooltip.h"
#include "ash/shelf/shelf.h"
#include "ash/shell_observer.h"
#include "ash/wm/overview/overview_observer.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_observer.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/view_targeter_delegate.h"
namespace ash {
class OverviewController;
class Shell;
class ASH_EXPORT DragHandle : public views::Button,
public views::ViewTargeterDelegate,
public AccessibilityObserver,
public OverviewObserver,
public ShellObserver,
public ui::ImplicitAnimationObserver,
public SplitViewObserver,
public ShelfObserver {
METADATA_HEADER(DragHandle, views::Button)
public:
DragHandle(float drag_handle_corner_radius, Shelf* shelf);
DragHandle(const DragHandle&) = delete;
~DragHandle() override;
DragHandle& operator=(const DragHandle&) = delete;
bool DoesIntersectRect(const views::View* target,
const gfx::Rect& rect) const override;
bool MaybeShowDragHandleNudge();
void ShowDragHandleNudge();
void ScheduleShowDragHandleNudge();
void HideDragHandleNudge(contextual_tooltip::DismissNudgeReason reason,
bool animate);
void SetWindowDragFromShelfInProgress(bool gesture_in_progress);
void OnGestureEvent(ui::GestureEvent* event) override;
gfx::Rect GetAnchorBoundsInScreen() const override;
void OnOverviewModeStarting() override;
void OnShellDestroying() override;
void OnSplitViewStateChanged(SplitViewController::State previous_state,
SplitViewController::State state) override;
void OnHotseatStateChanged(HotseatState old_state,
HotseatState new_state) override;
ContextualNudge* drag_handle_nudge() { return drag_handle_nudge_; }
bool gesture_nudge_target_visibility() const {
return gesture_nudge_target_visibility_;
}
bool show_nudge_animation_in_progress() const {
return show_nudge_animation_in_progress_;
}
bool has_show_drag_handle_timer_for_testing() {
return show_drag_handle_nudge_timer_.IsRunning();
}
void fire_show_drag_handle_timer_for_testing() {
show_drag_handle_nudge_timer_.FireNow();
}
bool has_hide_drag_handle_timer_for_testing() {
return hide_drag_handle_nudge_timer_.IsRunning();
}
void fire_hide_drag_handle_timer_for_testing() {
hide_drag_handle_nudge_timer_.FireNow();
}
private:
void OnAccessibilityStatusChanged() override;
void ButtonPressed();
void OnImplicitAnimationsCompleted() override;
void ShowDragHandleTooltip();
void HideDragHandleNudgeHelper(bool hidden_by_tap, bool animate);
void AnimateDragHandleShow();
void ScheduleDragHandleTranslationAnimation(
int vertical_offset,
base::TimeDelta animation_time,
gfx::Tween::Type tween_type,
ui::LayerAnimator::PreemptionStrategy strategy);
void HandleTapOnNudge();
void StopDragHandleNudgeShowTimer();
void UpdateExpandedCollapsedAccessibleState();
void UpdateAccessibleName();
void UpdateAccessiblePreviousAndNextFocus();
const raw_ptr<Shelf> shelf_;
base::OneShotTimer hide_drag_handle_nudge_timer_;
base::OneShotTimer show_drag_handle_nudge_timer_;
bool gesture_nudge_target_visibility_ = false;
bool show_nudge_animation_in_progress_ = false;
bool window_drag_from_shelf_in_progress_ = false;
raw_ptr<ContextualNudge> drag_handle_nudge_ = nullptr;
std::unique_ptr<Shelf::ScopedAutoHideLock> auto_hide_lock_;
base::ScopedClosureRunner force_show_hotseat_resetter_;
base::ScopedObservation<SplitViewController, SplitViewObserver>
split_view_observation_{this};
base::ScopedObservation<OverviewController, OverviewObserver>
overview_observation_{this};
base::ScopedObservation<Shell, ShellObserver> shell_observation_{this};
base::WeakPtrFactory<DragHandle> weak_factory_{this};
};
}
#endif