1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
// MIT/Apache2 License

//! This module provides the events used to drive the `breadx` event system.

#[cfg(feature = "input")]
pub mod input;

use crate::auto::{
    xproto::{
        ButtonPressEvent, ButtonReleaseEvent, CirculateNotifyEvent, CirculateRequestEvent,
        ClientMessageEvent, ConfigureNotifyEvent, ConfigureRequestEvent, CreateNotifyEvent,
        DestroyNotifyEvent, EnterNotifyEvent, ExposeEvent, FocusInEvent, FocusOutEvent,
        GraphicsExposureEvent, GravityNotifyEvent, KeyPressEvent, KeyReleaseEvent,
        KeymapNotifyEvent, LeaveNotifyEvent, MapNotifyEvent, MapRequestEvent, MappingNotifyEvent,
        NoExposureEvent, PropertyNotifyEvent, ReparentNotifyEvent, ResizeRequestEvent,
        SelectionClearEvent, SelectionNotifyEvent, SelectionRequestEvent, UnmapNotifyEvent,
        VisibilityNotifyEvent,
    },
    AsByteSequence, Event as AutoEvent,
};
use tinyvec::TinyVec;

const OPCODE_MASK: u8 = !0x80;

#[derive(Debug)]
pub enum Event {
    ConfigureNotify(ConfigureNotifyEvent),
    ClientMessage(ClientMessageEvent),
    Expose(ExposeEvent),
    ButtonPress(ButtonPressEvent),
    ButtonRelease(ButtonReleaseEvent),
    CirculateNotify(CirculateNotifyEvent),
    CirculateRequest(CirculateRequestEvent),
    ConfigureRequest(ConfigureRequestEvent),
    CreateNotify(CreateNotifyEvent),
    DestroyNotify(DestroyNotifyEvent),
    EnterNotify(EnterNotifyEvent),
    FocusIn(FocusInEvent),
    FocusOut(FocusOutEvent),
    GraphicsExposure(GraphicsExposureEvent),
    GravityNotify(GravityNotifyEvent),
    KeyPress(KeyPressEvent),
    KeyRelease(KeyReleaseEvent),
    KeymapNotify(KeymapNotifyEvent),
    LeaveNotify(LeaveNotifyEvent),
    MapNotify(MapNotifyEvent),
    MapRequest(MapRequestEvent),
    MappingNotify(MappingNotifyEvent),
    NoExposure(NoExposureEvent),
    PropertyNotify(PropertyNotifyEvent),
    ReparentNotify(ReparentNotifyEvent),
    ResizeRequest(ResizeRequestEvent),
    SelectionClear(SelectionClearEvent),
    SelectionNotify(SelectionNotifyEvent),
    SelectionRequest(SelectionRequestEvent),
    UnmapNotify(UnmapNotifyEvent),
    VisibilityNotify(VisibilityNotifyEvent),
    NoneOfTheAbove {
        opcode: u8,
        bytes: TinyVec<[u8; 32]>,
    },
}

impl Event {
    #[inline]
    pub(crate) fn from_bytes(bytes: TinyVec<[u8; 32]>) -> crate::Result<Self> {
        let mut e = Event::NoneOfTheAbove {
            opcode: bytes[0] & OPCODE_MASK,
            bytes,
        };
        e.differentiate()?;
        Ok(e)
    }

    #[inline]
    pub(crate) fn as_bytes(&self, bytes: &mut [u8]) {
        match self {
            Self::ConfigureNotify(cne) => cne.as_bytes(bytes),
            Self::ClientMessage(cne) => cne.as_bytes(bytes),
            Self::Expose(ee) => ee.as_bytes(bytes),
            Self::ButtonPress(bpe) => bpe.as_bytes(bytes),
            Self::ButtonRelease(bre) => bre.as_bytes(bytes),
            Self::CirculateNotify(cne) => cne.as_bytes(bytes),
            Self::CirculateRequest(cre) => cre.as_bytes(bytes),
            Self::ConfigureRequest(cre) => cre.as_bytes(bytes),
            Self::CreateNotify(cne) => cne.as_bytes(bytes),
            Self::DestroyNotify(dne) => dne.as_bytes(bytes),
            Self::EnterNotify(ene) => ene.as_bytes(bytes),
            Self::FocusIn(fie) => fie.as_bytes(bytes),
            Self::FocusOut(foe) => foe.as_bytes(bytes),
            Self::GraphicsExposure(gee) => gee.as_bytes(bytes),
            Self::GravityNotify(gne) => gne.as_bytes(bytes),
            Self::KeyPress(kpe) => kpe.as_bytes(bytes),
            Self::KeyRelease(kre) => kre.as_bytes(bytes),
            Self::KeymapNotify(kne) => kne.as_bytes(bytes),
            Self::LeaveNotify(lne) => lne.as_bytes(bytes),
            Self::MapNotify(mne) => mne.as_bytes(bytes),
            Self::MapRequest(mre) => mre.as_bytes(bytes),
            Self::MappingNotify(mne) => mne.as_bytes(bytes),
            Self::NoExposure(nee) => nee.as_bytes(bytes),
            Self::PropertyNotify(pne) => pne.as_bytes(bytes),
            Self::ReparentNotify(rne) => rne.as_bytes(bytes),
            Self::ResizeRequest(rre) => rre.as_bytes(bytes),
            Self::SelectionClear(sce) => sce.as_bytes(bytes),
            Self::SelectionNotify(sne) => sne.as_bytes(bytes),
            Self::SelectionRequest(sre) => sre.as_bytes(bytes),
            Self::UnmapNotify(une) => une.as_bytes(bytes),
            Self::VisibilityNotify(vne) => vne.as_bytes(bytes),
            Self::NoneOfTheAbove { bytes: b, .. } => {
                (&mut bytes[0..b.len()]).copy_from_slice(b);
                0
            }
        };
    }

    #[allow(clippy::too_many_lines)]
    #[inline]
    pub(crate) fn differentiate(&mut self) -> crate::Result {
        if let Event::NoneOfTheAbove { opcode, ref bytes } = self {
            log::debug!("Differentiating event bytes: {}", bytes);

            let opcode = *opcode;
            if opcode == ConfigureNotifyEvent::OPCODE {
                let cne = ConfigureNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("ConfigureNotifyEvent")),
                )?;
                *self = Self::ConfigureNotify(cne.0);
            } else if opcode == ClientMessageEvent::OPCODE {
                let cme = ClientMessageEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("ClientMessageEvent")))?;
                *self = Self::ClientMessage(cme.0);
            } else if opcode == ExposeEvent::OPCODE {
                let ee = ExposeEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("ExposeEvent")))?;
                *self = Self::Expose(ee.0);
            } else if opcode == ButtonPressEvent::OPCODE {
                let e = ButtonPressEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("ButtonPressEvent")))?;
                *self = Self::ButtonPress(e.0);
            } else if opcode == ButtonReleaseEvent::OPCODE {
                let e = ButtonReleaseEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("ButtonReleaseEvent")))?;
                *self = Self::ButtonRelease(e.0);
            } else if opcode == CirculateNotifyEvent::OPCODE {
                let e = CirculateNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("CirculateNotifyEvent")),
                )?;
                *self = Self::CirculateNotify(e.0);
            } else if opcode == CirculateRequestEvent::OPCODE {
                let e = CirculateRequestEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("CirculateRequestEvent")),
                )?;
                *self = Self::CirculateRequest(e.0);
            } else if opcode == ConfigureRequestEvent::OPCODE {
                let e = ConfigureRequestEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("ConfigureRequestEvent")),
                )?;
                *self = Self::ConfigureRequest(e.0);
            } else if opcode == CreateNotifyEvent::OPCODE {
                let e = CreateNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("CreateNotifyEvent")))?;
                *self = Self::CreateNotify(e.0);
            } else if opcode == DestroyNotifyEvent::OPCODE {
                let e = DestroyNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("DestroyNotifyEvent")))?;
                *self = Self::DestroyNotify(e.0);
            } else if opcode == EnterNotifyEvent::OPCODE {
                let e = EnterNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("EnterNotifyEvent")))?;
                *self = Self::EnterNotify(e.0);
            } else if opcode == FocusInEvent::OPCODE {
                let e = FocusInEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("FocusInEvent")))?;
                *self = Self::FocusIn(e.0);
            } else if opcode == FocusOutEvent::OPCODE {
                let e = FocusOutEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("FocusOutEvent")))?;
                *self = Self::FocusOut(e.0);
            } else if opcode == GraphicsExposureEvent::OPCODE {
                let e = GraphicsExposureEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("GraphicsExposureEvent")),
                )?;
                *self = Self::GraphicsExposure(e.0);
            } else if opcode == GravityNotifyEvent::OPCODE {
                let e = GravityNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("GravityNotifyEvent")))?;
                *self = Self::GravityNotify(e.0);
            } else if opcode == KeyPressEvent::OPCODE {
                let e = KeyPressEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("KeyPressEvent")))?;
                *self = Self::KeyPress(e.0);
            } else if opcode == KeyReleaseEvent::OPCODE {
                let e = KeyReleaseEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("KeyReleaseEvent")))?;
                *self = Self::KeyRelease(e.0);
            } else if opcode == KeymapNotifyEvent::OPCODE {
                let e = KeymapNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("KeymapNotifyEvent")))?;
                *self = Self::KeymapNotify(e.0);
            } else if opcode == LeaveNotifyEvent::OPCODE {
                let e = LeaveNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("LeaveNotifyEvent")))?;
                *self = Self::LeaveNotify(e.0);
            } else if opcode == MapNotifyEvent::OPCODE {
                let e = MapNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("MapNotifyEvent")))?;
                *self = Self::MapNotify(e.0);
            } else if opcode == MapRequestEvent::OPCODE {
                let e = MapRequestEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("MapRequestEvent")))?;
                *self = Self::MapRequest(e.0);
            } else if opcode == MappingNotifyEvent::OPCODE {
                let e = MappingNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("MappingNotifyEvent")))?;
                *self = Self::MappingNotify(e.0);
            } else if opcode == NoExposureEvent::OPCODE {
                let e = NoExposureEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("NoExposureEvent")))?;
                *self = Self::NoExposure(e.0);
            } else if opcode == PropertyNotifyEvent::OPCODE {
                let e = PropertyNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("PropertyNotifyEvent")),
                )?;
                *self = Self::PropertyNotify(e.0);
            } else if opcode == ReparentNotifyEvent::OPCODE {
                let e = ReparentNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("ReparentNotifyEvent")),
                )?;
                *self = Self::ReparentNotify(e.0);
            } else if opcode == ResizeRequestEvent::OPCODE {
                let e = ResizeRequestEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("ResizeRequestEvent")))?;
                *self = Self::ResizeRequest(e.0);
            } else if opcode == SelectionClearEvent::OPCODE {
                let e = SelectionClearEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("SelectionClearEvent")),
                )?;
                *self = Self::SelectionClear(e.0);
            } else if opcode == SelectionNotifyEvent::OPCODE {
                let e = SelectionNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("SelectionNotifyEvent")),
                )?;
                *self = Self::SelectionNotify(e.0);
            } else if opcode == SelectionRequestEvent::OPCODE {
                let e = SelectionRequestEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("SelectionRequestEvent")),
                )?;
                *self = Self::SelectionRequest(e.0);
            } else if opcode == UnmapNotifyEvent::OPCODE {
                let e = UnmapNotifyEvent::from_bytes(bytes)
                    .ok_or(crate::BreadError::BadObjectRead(Some("UnmapNotifyEvent")))?;
                *self = Self::UnmapNotify(e.0);
            } else if opcode == VisibilityNotifyEvent::OPCODE {
                let e = VisibilityNotifyEvent::from_bytes(bytes).ok_or(
                    crate::BreadError::BadObjectRead(Some("VisibilityNotifyEvent")),
                )?;
                *self = Self::VisibilityNotify(e.0);
            }
        }

        Ok(())
    }

    /// Get the opcode of this event.
    #[inline]
    #[must_use]
    pub fn opcode(&self) -> u8 {
        match self {
            Self::ConfigureNotify(_) => ConfigureNotifyEvent::OPCODE,
            Self::ClientMessage(_) => ClientMessageEvent::OPCODE,
            Self::Expose(_) => ExposeEvent::OPCODE,
            Self::ButtonPress(_) => ButtonPressEvent::OPCODE,
            Self::ButtonRelease(_) => ButtonReleaseEvent::OPCODE,
            Self::CirculateNotify(_) => CirculateNotifyEvent::OPCODE,
            Self::CirculateRequest(_) => CirculateRequestEvent::OPCODE,
            Self::ConfigureRequest(_) => ConfigureRequestEvent::OPCODE,
            Self::CreateNotify(_) => CreateNotifyEvent::OPCODE,
            Self::DestroyNotify(_) => DestroyNotifyEvent::OPCODE,
            Self::EnterNotify(_) => EnterNotifyEvent::OPCODE,
            Self::FocusIn(_) => FocusInEvent::OPCODE,
            Self::FocusOut(_) => FocusOutEvent::OPCODE,
            Self::GraphicsExposure(_) => GraphicsExposureEvent::OPCODE,
            Self::GravityNotify(_) => GravityNotifyEvent::OPCODE,
            Self::KeyPress(_) => KeyPressEvent::OPCODE,
            Self::KeyRelease(_) => KeyReleaseEvent::OPCODE,
            Self::KeymapNotify(_) => KeymapNotifyEvent::OPCODE,
            Self::LeaveNotify(_) => LeaveNotifyEvent::OPCODE,
            Self::MapNotify(_) => MapNotifyEvent::OPCODE,
            Self::MapRequest(_) => MapRequestEvent::OPCODE,
            Self::MappingNotify(_) => MappingNotifyEvent::OPCODE,
            Self::NoExposure(_) => NoExposureEvent::OPCODE,
            Self::PropertyNotify(_) => PropertyNotifyEvent::OPCODE,
            Self::ReparentNotify(_) => ReparentNotifyEvent::OPCODE,
            Self::ResizeRequest(_) => ResizeRequestEvent::OPCODE,
            Self::SelectionClear(_) => SelectionClearEvent::OPCODE,
            Self::SelectionNotify(_) => SelectionNotifyEvent::OPCODE,
            Self::SelectionRequest(_) => SelectionRequestEvent::OPCODE,
            Self::UnmapNotify(_) => UnmapNotifyEvent::OPCODE,
            Self::VisibilityNotify(_) => VisibilityNotifyEvent::OPCODE,
            Self::NoneOfTheAbove { opcode, .. } => *opcode,
        }
    }
}