#ifndef ASH_DISPLAY_CURSOR_WINDOW_CONTROLLER_H_
#define ASH_DISPLAY_CURSOR_WINDOW_CONTROLLER_H_
#include <memory>
#include <optional>
#include "ash/ash_export.h"
#include "ash/constants/ash_constants.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_size.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/display/display.h"
#include "ui/views/widget/unique_widget_ptr.h"
namespace gfx {
class ImageSkia;
}
namespace ash {
class CursorWindowControllerTest;
class CursorWindowDelegate;
class ASH_EXPORT CursorWindowController : public aura::WindowObserver {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnCursorCompositingStateChanged(bool enabled) = 0;
protected:
~Observer() override = default;
};
CursorWindowController();
CursorWindowController(const CursorWindowController&) = delete;
CursorWindowController& operator=(const CursorWindowController&) = delete;
~CursorWindowController() override;
bool is_cursor_compositing_enabled() const {
return is_cursor_compositing_enabled_;
}
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void SetLargeCursorSizeInDip(int large_cursor_size_in_dip);
void SetCursorColor(SkColor cursor_color);
bool ShouldEnableCursorCompositing();
void SetCursorCompositingEnabled(bool enabled);
void UpdateContainer();
void SetDisplay(const display::Display& display);
void OnDockedMagnifierResizingStateChanged(bool is_active);
void OnFullscreenMagnifierEnabled(bool enabled);
void UpdateLocation(bool throttle = false);
void SetCursor(gfx::NativeCursor cursor);
void SetCursorSize(ui::CursorSize cursor_size);
void SetVisibility(bool visible);
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowDestroying(aura::Window* window) override;
const aura::Window* GetContainerForTest() const;
SkColor GetCursorColorForTest() const;
gfx::Rect GetCursorBoundsInScreenForTest() const;
const aura::Window* GetCursorHostWindowForTest() const;
float max_update_rate_ms() const { return max_update_rate_ms_; }
private:
friend class CursorWindowControllerTest;
friend class MirrorWindowTestApi;
void SetContainer(aura::Window* container);
void SetBoundsInScreenAndRotation(const gfx::Rect& bounds,
display::Display::Rotation rotation);
void UpdateCursorImage();
void UpdateCursorVisibility();
void UpdateCursorView();
void UpdateCursorWindow();
const gfx::ImageSkia& GetCursorImageForTest() const;
bool ShouldUseFastInk() const;
void UpdateCursorMode();
base::ObserverList<Observer> observers_;
raw_ptr<aura::Window, DanglingUntriaged> container_ = nullptr;
bool is_cursor_compositing_enabled_ = false;
gfx::Rect bounds_in_screen_;
display::Display::Rotation rotation_ = display::Display::ROTATE_0;
gfx::NativeCursor cursor_ = ui::mojom::CursorType::kNone;
bool visible_ = true;
ui::CursorSize cursor_size_ = ui::CursorSize::kNormal;
gfx::Point hot_point_;
int large_cursor_size_in_dip_ = kDefaultLargeCursorSize;
SkColor cursor_color_ = ui::kDefaultCursorColor;
display::Display display_;
std::unique_ptr<aura::Window> cursor_window_;
std::unique_ptr<CursorWindowDelegate> delegate_;
views::UniqueWidgetPtr cursor_view_widget_;
std::optional<base::TimeTicks> last_updated_;
float max_update_rate_ms_ = 0;
base::ScopedObservation<aura::Window, aura::WindowObserver>
scoped_container_observer_{this};
};
}
#endif