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
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_X_EVENT_H_
#define UI_GFX_X_EVENT_H_
#include <cstdint>
#include <type_traits>
#include <utility>
#include "base/check_op.h"
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
#include "ui/gfx/x/xproto.h"
namespace x11 {
class Connection;
class Event;
struct ReadBuffer;
template <typename T>
void ReadEvent(T* event, ReadBuffer* buf);
class COMPONENT_EXPORT(X11) Event {
public:
template <typename T>
Event(bool send_event, T&& xproto_event) {
using DecayT = std::decay_t<T>;
fabricated_ = true;
send_event_ = send_event;
type_id_ = DecayT::type_id;
auto* event = new DecayT(std::forward<T>(xproto_event));
event_ = {event, [](void* e) {
if (e) {
delete reinterpret_cast<DecayT*>(e);
}
}};
}
Event();
// |event_bytes| is modified and will not be valid after this call.
// A copy is necessary if the original data is still needed.
Event(scoped_refptr<UnsizedRefCountedMemory> event_bytes,
Connection* connection);
Event(const Event&) = delete;
Event& operator=(const Event&) = delete;
Event(Event&& event);
Event& operator=(Event&& event);
~Event();
template <typename T>
T* As() {
if (type_id_ != T::type_id) {
return nullptr;
}
if (!event_) {
T* event = new T;
Parse(
event,
[](void* e, ReadBuffer* r) { ReadEvent<T>(static_cast<T*>(e), r); },
[](void* e) { delete static_cast<T*>(e); });
if constexpr (std::is_member_pointer<decltype(&T::opcode)>()) {
event->opcode = static_cast<decltype(event->opcode)>(opcode_);
}
}
return static_cast<T*>(event_.get());
}
template <typename T>
const T* As() const {
return const_cast<Event*>(this)->As<T>();
}
bool send_event() const { return send_event_; }
uint32_t sequence() const {
CHECK(!fabricated_);
return sequence_;
}
bool Initialized() const { return type_id_; }
private:
using Parser = void (*)(void*, ReadBuffer*);
using Deleter = void (*)(void*);
void Parse(void* event, Parser parser, Deleter deleter);
// Indicates this event was sent from another client instead of the server.
bool send_event_ = false;
// Indicates this event was created, not sent by the server or a client.
bool fabricated_ = false;
// The value of the underlying event's `T::type_id`.
uint8_t type_id_ = 0;
// The value of the underlying event's `t->opcode`.
uint8_t opcode_ = 0;
// The (extended) event sequence provided by XCB.
uint32_t sequence_ = 0;
// The unparsed event, or nullptr if it's already parsed.
scoped_refptr<UnsizedRefCountedMemory> raw_event_;
// The type-erased parsed event, or nullptr if it hasn't been parsed yet.
std::unique_ptr<void, Deleter> event_ = {nullptr, nullptr};
};
} // namespace x11
#endif // UI_GFX_X_EVENT_H_
|