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
|
// 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.
#include "ui/gfx/x/event.h"
#include <xcb/xcb.h>
#include <cstring>
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_internal.h"
#include "ui/gfx/x/xproto_types.h"
namespace x11 {
Event::Event() = default;
Event::Event(scoped_refptr<UnsizedRefCountedMemory> event_bytes,
Connection* connection) {
auto* xcb_event =
reinterpret_cast<xcb_generic_event_t*>(event_bytes->bytes());
uint8_t response_type = xcb_event->response_type & ~kSendEventMask;
if (xcb_event->response_type & kSendEventMask) {
send_event_ = true;
}
sequence_ = xcb_event->full_sequence;
// On the wire, events are 32 bytes except for generic events which are
// trailed by additional data. XCB inserts an extended 4-byte sequence
// between the 32-byte event and the additional data, so we need to shift
// the additional data over by 4 bytes so the event is back in its wire
// format, which is what XProto is expecting.
if (response_type == GeGenericEvent::opcode) {
auto* ge = reinterpret_cast<xcb_ge_event_t*>(xcb_event);
const size_t extended_length = ge->length * 4;
UNSAFE_TODO(memmove(&ge->full_sequence, &ge[1], extended_length));
}
connection->GetEventTypeAndOp(event_bytes->bytes(), &type_id_, &opcode_);
if (type_id_) {
raw_event_ = event_bytes;
}
}
Event::Event(Event&& event) {
operator=(std::move(event));
}
Event& Event::operator=(Event&& event) {
send_event_ = event.send_event_;
fabricated_ = event.fabricated_;
type_id_ = event.type_id_;
opcode_ = event.opcode_;
sequence_ = event.sequence_;
raw_event_ = std::move(event.raw_event_);
event_ = std::move(event.event_);
// Clear the old instance, to make sure it's in a valid state.
event.send_event_ = false;
event.fabricated_ = false;
event.type_id_ = 0;
event.opcode_ = 0;
event.sequence_ = 0;
return *this;
}
Event::~Event() = default;
void Event::Parse(void* event, Parser parser, Deleter deleter) {
CHECK(type_id_);
CHECK(!event_);
CHECK(raw_event_);
ReadBuffer read_buffer(raw_event_);
parser(event, &read_buffer);
event_ = {event, deleter};
raw_event_.reset();
}
} // namespace x11
|