ttx 0.1.0
Loading...
Searching...
No Matches
mouse.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/reflect/enumerator.h"
4#include "di/reflect/reflect.h"
5#include "di/util/bitwise_enum.h"
6#include "dius/tty.h"
7
8// Mouse reference: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
9namespace ttx {
27
28DI_DEFINE_ENUM_BITWISE_OPERATIONS(MouseButton)
29
30constexpr auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MouseButton>) {
31 using enum MouseButton;
32 return di::make_enumerators<"MouseButton">(
33 di::enumerator<"None", None>, di::enumerator<"Left", Left>, di::enumerator<"Middle", Middle>,
34 di::enumerator<"Right", Right>, di::enumerator<"ScrollUp", ScrollUp>, di::enumerator<"ScrollDown", ScrollDown>,
35 di::enumerator<"ScrollLeft", ScrollLeft>, di::enumerator<"ScrollRight", ScrollRight>, di::enumerator<"8", _8>,
36 di::enumerator<"9", _9>, di::enumerator<"10", _10>, di::enumerator<"11", _11>);
37}
38
40public:
41 MouseCoordinate() = default;
42 constexpr MouseCoordinate(u32 x, u32 y) : m_x(x), m_y(y) {}
43
44 constexpr auto x() const -> u32 { return m_x; }
45 constexpr auto y() const -> u32 { return m_y; }
46
47 auto operator==(MouseCoordinate const&) const -> bool = default;
48
49private:
50 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MouseCoordinate>) {
51 return di::make_fields<"MouseCoordinate">(di::field<"x", &MouseCoordinate::m_x>,
52 di::field<"y", &MouseCoordinate::m_y>);
53 }
54
55 u32 m_x { 0 };
56 u32 m_y { 0 };
57};
58
60public:
61 constexpr static auto from_pixels(MouseCoordinate pixels, dius::tty::WindowSize const& size) -> MousePosition {
62 if (size.rows == 0 || size.cols == 0) {
63 return MousePosition({}, pixels);
64 }
65
66 // Determine the cell from pixel coordinates.
67 auto in_cells =
68 MouseCoordinate(pixels.x() * size.cols / size.pixel_width, pixels.y() * size.rows / size.pixel_height);
69 return MousePosition(in_cells, pixels);
70 }
71
72 MousePosition() = default;
73 constexpr explicit MousePosition(MouseCoordinate cells, di::Optional<MouseCoordinate> pixels = {})
74 : m_cells(cells), m_pixels(pixels) {}
75
76 constexpr auto in_cells() const -> MouseCoordinate { return m_cells; }
77 constexpr auto in_pixels() const -> di::Optional<MouseCoordinate> { return m_pixels; }
78
79 constexpr auto in_pixels_with_fallback(dius::tty::WindowSize const& size) const -> MouseCoordinate {
80 if (m_pixels.has_value()) {
81 return m_pixels.value();
82 }
83
84 if (size.rows == 0 || size.cols == 0) {
85 return {};
86 }
87
88 // Infer the pixel coordinates to be in the middle of the cell.
89 auto x = (in_cells().x() * size.pixel_width + size.pixel_width / 2) / size.cols;
90 auto y = (in_cells().y() * size.pixel_height + size.pixel_height / 2) / size.rows;
91 return { x, y };
92 }
93
94 constexpr auto translate(MouseCoordinate offset_in_cells, dius::tty::WindowSize const& size) const
95 -> MousePosition {
96 auto new_cells = MouseCoordinate {
97 in_cells().x() + offset_in_cells.x(),
98 in_cells().y() + offset_in_cells.y(),
99 };
100 auto new_pixels = in_pixels().transform([&](MouseCoordinate pixels) {
101 return MouseCoordinate {
102 pixels.x() + size.pixel_width / size.cols,
103 pixels.y() + size.pixel_height / size.rows,
104 };
105 });
106
107 return MousePosition(new_cells, new_pixels);
108 }
109
110 auto operator==(MousePosition const&) const -> bool = default;
111
112private:
113 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MousePosition>) {
114 return di::make_fields<"MousePosition">(di::field<"cells", &MousePosition::m_cells>,
115 di::field<"pixels", &MousePosition::m_pixels>);
116 }
117
118 MouseCoordinate m_cells;
119 di::Optional<MouseCoordinate> m_pixels;
120};
121}
Definition mouse.h:39
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< MouseCoordinate >)
Definition mouse.h:50
MouseCoordinate()=default
auto operator==(MouseCoordinate const &) const -> bool=default
constexpr auto y() const -> u32
Definition mouse.h:45
constexpr MouseCoordinate(u32 x, u32 y)
Definition mouse.h:42
constexpr auto x() const -> u32
Definition mouse.h:44
constexpr auto translate(MouseCoordinate offset_in_cells, dius::tty::WindowSize const &size) const -> MousePosition
Definition mouse.h:94
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< MousePosition >)
Definition mouse.h:113
auto operator==(MousePosition const &) const -> bool=default
constexpr auto in_pixels() const -> di::Optional< MouseCoordinate >
Definition mouse.h:77
constexpr MousePosition(MouseCoordinate cells, di::Optional< MouseCoordinate > pixels={})
Definition mouse.h:73
static constexpr auto from_pixels(MouseCoordinate pixels, dius::tty::WindowSize const &size) -> MousePosition
Definition mouse.h:61
constexpr auto in_pixels_with_fallback(dius::tty::WindowSize const &size) const -> MouseCoordinate
Definition mouse.h:79
MousePosition()=default
constexpr auto in_cells() const -> MouseCoordinate
Definition mouse.h:76
Definition cursor_style.h:5
MouseButton
Definition mouse.h:10
@ ScrollLeft
Definition mouse.h:17
@ HorizontalScrollButtons
Definition mouse.h:23
@ VerticalScrollButtons
Definition mouse.h:24
@ _11
Definition mouse.h:22
@ ScrollUp
Definition mouse.h:15
@ ScrollDown
Definition mouse.h:16
@ Middle
Definition mouse.h:13
@ ScrollButtons
Definition mouse.h:25
@ ScrollRight
Definition mouse.h:18
@ _10
Definition mouse.h:21
@ None
Definition direction.h:8
@ Right
Definition key.h:70
@ Left
Definition key.h:69
@ _9
Definition key.h:46
@ _8
Definition key.h:45
constexpr auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< CursorStyle >)
Definition cursor_style.h:16