1use minicbor::decode::{self, Decoder};
8use minicbor::encode::{self, Encoder, Write};
9use minicbor::{Decode, Encode};
10
11use crate::cbor::{self, Elements};
12use crate::message::{Rotation, kind};
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct Event {
17 pub seq: u64,
21 pub time_us: u64,
23 pub payload: EventPayload,
24}
25
26impl Event {
27 pub fn stream(&self) -> Stream {
28 self.payload.stream()
29 }
30}
31
32#[derive(Clone, Debug, PartialEq, Eq)]
34pub enum EventPayload {
35 Tree(TreeChange),
36 Window(WindowChange),
37 Frame(FrameAvailable),
38 Lifecycle(Lifecycle),
39 Unknown(Stream),
42}
43
44impl EventPayload {
45 pub fn stream(&self) -> Stream {
46 match self {
47 EventPayload::Tree(_) => Stream::TREE,
48 EventPayload::Window(_) => Stream::WINDOW,
49 EventPayload::Frame(_) => Stream::FRAME,
50 EventPayload::Lifecycle(_) => Stream::LIFECYCLE,
51 EventPayload::Unknown(stream) => *stream,
52 }
53 }
54}
55
56wire_enum! {
57 pub struct Stream(u8);
59 TREE = 0, "tree";
61 WINDOW = 1, "window";
63 FRAME = 2, "frame";
65 LIFECYCLE = 3, "lifecycle";
67}
68
69impl Stream {
70 pub fn is_lossy(self) -> bool {
74 self == Stream::FRAME
75 }
76}
77
78#[derive(Clone, Debug, PartialEq, Eq)]
80pub struct TreeChange {
81 pub change: TreeChangeKind,
82 pub window: u32,
83 pub path: Vec<u32>,
85}
86
87wire_enum! {
88 pub struct TreeChangeKind(u8);
90 CONTENT = 0, "content";
92 TEXT = 1, "text";
93 SCROLL = 2, "scroll";
94 FOCUS = 3, "focus";
95 SELECTION = 4, "selection";
96}
97
98#[derive(Clone, Debug, PartialEq, Eq)]
100pub struct WindowChange {
101 pub change: WindowChangeKind,
102 pub window: u32,
103}
104
105wire_enum! {
106 pub struct WindowChangeKind(u8);
108 STATE = 0, "state";
110 ADDED = 1, "added";
111 REMOVED = 2, "removed";
112 FOCUS = 3, "focus";
114 BOUNDS = 4, "bounds";
115}
116
117#[derive(Clone, Debug, PartialEq, Eq)]
119pub struct FrameAvailable {
120 pub width: u32,
121 pub height: u32,
122 pub rotation: Rotation,
123}
124
125#[derive(Clone, Debug, PartialEq, Eq)]
127pub struct Lifecycle {
128 pub change: LifecycleKind,
129 pub message: String,
130}
131
132wire_enum! {
133 pub struct LifecycleKind(u8);
135 READY = 0, "ready";
137 OWNERSHIP_LOST = 1, "ownership_lost";
139 SHUTTING_DOWN = 2, "shutting_down";
141 WARNING = 3, "warning";
143}
144
145impl<C> Encode<C> for Event {
146 fn encode<W: Write>(
147 &self,
148 e: &mut Encoder<W>,
149 ctx: &mut C,
150 ) -> Result<(), encode::Error<W::Error>> {
151 let extra: u64 = match &self.payload {
152 EventPayload::Tree(_) | EventPayload::Frame(_) => 3,
153 EventPayload::Window(_) | EventPayload::Lifecycle(_) => 2,
154 EventPayload::Unknown(_) => 0,
155 };
156 e.array(4 + extra)?
157 .u8(kind::EVENT)?
158 .u8(self.stream().0)?
159 .u64(self.seq)?
160 .u64(self.time_us)?;
161 match &self.payload {
162 EventPayload::Tree(t) => {
163 e.u8(t.change.0)?.u32(t.window)?.encode_with(&t.path, ctx)?;
164 }
165 EventPayload::Window(w) => {
166 e.u8(w.change.0)?.u32(w.window)?;
167 }
168 EventPayload::Frame(f) => {
169 e.u32(f.width)?.u32(f.height)?.u8(f.rotation.0)?;
170 }
171 EventPayload::Lifecycle(l) => {
172 e.u8(l.change.0)?.str(&l.message)?;
173 }
174 EventPayload::Unknown(_) => {}
175 }
176 Ok(())
177 }
178}
179
180impl<'b, C> Decode<'b, C> for Event {
181 fn decode(d: &mut Decoder<'b>, ctx: &mut C) -> Result<Event, decode::Error> {
182 let at = d.position();
183 let mut items = Elements::begin(d)?;
184 let k = items.require(d, 0, "kind", |d| d.u8())?;
185 cbor::expect_kind(Some(k), kind::EVENT, at)?;
186 let stream = Stream(items.require(d, 1, "stream", |d| d.u8())?);
187 let seq = items.require(d, 2, "seq", |d| d.u64())?;
188 let time_us = items.require(d, 3, "time_us", |d| d.u64())?;
189 let payload = match stream {
190 Stream::TREE => EventPayload::Tree(TreeChange {
191 change: TreeChangeKind(items.require(d, 4, "change", |d| d.u8())?),
192 window: items.require(d, 5, "window", |d| d.u32())?,
193 path: items.require(d, 6, "path", |d| cbor::decode_vec(d, &mut *ctx))?,
194 }),
195 Stream::WINDOW => EventPayload::Window(WindowChange {
196 change: WindowChangeKind(items.require(d, 4, "change", |d| d.u8())?),
197 window: items.require(d, 5, "window", |d| d.u32())?,
198 }),
199 Stream::FRAME => EventPayload::Frame(FrameAvailable {
200 width: items.require(d, 4, "width", |d| d.u32())?,
201 height: items.require(d, 5, "height", |d| d.u32())?,
202 rotation: Rotation(items.require(d, 6, "rotation", |d| d.u8())?),
203 }),
204 Stream::LIFECYCLE => EventPayload::Lifecycle(Lifecycle {
205 change: LifecycleKind(items.require(d, 4, "change", |d| d.u8())?),
206 message: items.require(d, 5, "message", |d| d.str().map(str::to_owned))?,
207 }),
208 other => EventPayload::Unknown(other),
209 };
210 items.skip_rest(d)?;
211 Ok(Event {
212 seq,
213 time_us,
214 payload,
215 })
216 }
217}