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#include "ttx/size.h"
8
9// Mouse reference: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
10namespace ttx {
28
29DI_DEFINE_ENUM_BITWISE_OPERATIONS(MouseButton)
30
31constexpr auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MouseButton>) {
32 using enum MouseButton;
33 return di::make_enumerators<"MouseButton">(
34 di::enumerator<"None", None>, di::enumerator<"Left", Left>, di::enumerator<"Middle", Middle>,
35 di::enumerator<"Right", Right>, di::enumerator<"ScrollUp", ScrollUp>, di::enumerator<"ScrollDown", ScrollDown>,
36 di::enumerator<"ScrollLeft", ScrollLeft>, di::enumerator<"ScrollRight", ScrollRight>, di::enumerator<"8", _8>,
37 di::enumerator<"9", _9>, di::enumerator<"10", _10>, di::enumerator<"11", _11>);
38}
39
41public:
42 MouseCoordinate() = default;
43 constexpr MouseCoordinate(u32 x, u32 y) : m_x(x), m_y(y) {}
44
45 constexpr auto x() const -> u32 { return m_x; }
46 constexpr auto y() const -> u32 { return m_y; }
47
48 auto operator==(MouseCoordinate const&) const -> bool = default;
49
50private:
51 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MouseCoordinate>) {
52 return di::make_fields<"MouseCoordinate">(di::field<"x", &MouseCoordinate::m_x>,
53 di::field<"y", &MouseCoordinate::m_y>);
54 }
55
56 u32 m_x { 0 };
57 u32 m_y { 0 };
58};
59
61public:
62 constexpr static auto from_pixels(MouseCoordinate pixels, Size const& size) -> MousePosition {
63 if (size.rows == 0 || size.cols == 0) {
64 return MousePosition({}, pixels);
65 }
66
67 // Determine the cell from pixel coordinates.
68 auto in_cells = MouseCoordinate(pixels.x() * size.cols / size.xpixels, pixels.y() * size.rows / size.ypixels);
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(Size 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.xpixels + size.xpixels / 2) / size.cols;
90 auto y = (in_cells().y() * size.ypixels + size.ypixels / 2) / size.rows;
91 return { x, y };
92 }
93
94 constexpr auto translate(MouseCoordinate offset_in_cells, Size const& size) const -> MousePosition {
95 auto new_cells = MouseCoordinate {
96 in_cells().x() + offset_in_cells.x(),
97 in_cells().y() + offset_in_cells.y(),
98 };
99 auto new_pixels = in_pixels().transform([&](MouseCoordinate pixels) {
100 return MouseCoordinate {
101 pixels.x() + size.xpixels / size.cols,
102 pixels.y() + size.ypixels / size.rows,
103 };
104 });
105
106 return MousePosition(new_cells, new_pixels);
107 }
108
109 auto operator==(MousePosition const&) const -> bool = default;
110
111private:
112 constexpr friend auto tag_invoke(di::Tag<di::reflect>, di::InPlaceType<MousePosition>) {
113 return di::make_fields<"MousePosition">(di::field<"cells", &MousePosition::m_cells>,
114 di::field<"pixels", &MousePosition::m_pixels>);
115 }
116
117 MouseCoordinate m_cells;
118 di::Optional<MouseCoordinate> m_pixels;
119};
120}
Definition mouse.h:40
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< MouseCoordinate >)
Definition mouse.h:51
MouseCoordinate()=default
auto operator==(MouseCoordinate const &) const -> bool=default
constexpr auto y() const -> u32
Definition mouse.h:46
constexpr MouseCoordinate(u32 x, u32 y)
Definition mouse.h:43
constexpr auto x() const -> u32
Definition mouse.h:45
constexpr friend auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< MousePosition >)
Definition mouse.h:112
constexpr auto in_pixels_with_fallback(Size const &size) const -> MouseCoordinate
Definition mouse.h:79
auto operator==(MousePosition const &) const -> bool=default
constexpr auto translate(MouseCoordinate offset_in_cells, Size const &size) const -> MousePosition
Definition mouse.h:94
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, Size const &size) -> MousePosition
Definition mouse.h:62
MousePosition()=default
constexpr auto in_cells() const -> MouseCoordinate
Definition mouse.h:76
Definition clipboard.h:10
MouseButton
Definition mouse.h:11
@ ScrollLeft
Definition mouse.h:18
@ HorizontalScrollButtons
Definition mouse.h:24
@ VerticalScrollButtons
Definition mouse.h:25
@ _11
Definition mouse.h:23
@ ScrollUp
Definition mouse.h:16
@ ScrollDown
Definition mouse.h:17
@ Middle
Definition mouse.h:14
@ ScrollButtons
Definition mouse.h:26
@ ScrollRight
Definition mouse.h:19
@ _10
Definition mouse.h:22
@ None
Definition direction.h:8
constexpr auto tag_invoke(di::Tag< di::reflect >, di::InPlaceType< ClipboardMode >)
Definition clipboard.h:21
@ Right
Definition key.h:70
@ Left
Definition key.h:69
@ _9
Definition key.h:46
@ _8
Definition key.h:45
Definition size.h:7