1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gfx/x/event.h"
6
7 #include <xcb/xcb.h>
8
9 #include <cstring>
10
11 #include "base/check_op.h"
12 #include "base/memory/scoped_refptr.h"
13 #include "ui/gfx/x/connection.h"
14 #include "ui/gfx/x/xproto.h"
15 #include "ui/gfx/x/xproto_internal.h"
16 #include "ui/gfx/x/xproto_types.h"
17
18 namespace x11 {
19
20 Event::Event() = default;
21
Event(scoped_refptr<base::RefCountedMemory> event_bytes,x11::Connection * connection,bool sequence_valid)22 Event::Event(scoped_refptr<base::RefCountedMemory> event_bytes,
23 x11::Connection* connection,
24 bool sequence_valid) {
25 auto* xcb_event = reinterpret_cast<xcb_generic_event_t*>(
26 const_cast<uint8_t*>(event_bytes->data()));
27 sequence_valid_ = sequence_valid;
28 sequence_ = xcb_event->full_sequence;
29 // KeymapNotify events are the only events that don't have a sequence.
30 if ((xcb_event->response_type & ~kSendEventMask) !=
31 x11::KeymapNotifyEvent::opcode) {
32 // On the wire, events are 32 bytes except for generic events which are
33 // trailed by additional data. XCB inserts an extended 4-byte sequence
34 // between the 32-byte event and the additional data, so we need to shift
35 // the additional data over by 4 bytes so the event is back in its wire
36 // format, which is what Xlib and XProto are expecting.
37 if ((xcb_event->response_type & ~kSendEventMask) ==
38 x11::GeGenericEvent::opcode) {
39 auto* ge = reinterpret_cast<xcb_ge_event_t*>(xcb_event);
40 constexpr size_t ge_length = sizeof(xcb_raw_generic_event_t);
41 constexpr size_t offset = sizeof(ge->full_sequence);
42 size_t extended_length = ge->length * 4;
43 if (extended_length < ge_length) {
44 // If the additional data is smaller than the fixed size event, shift
45 // the additional data to the left.
46 memmove(&ge->full_sequence, &ge[1], extended_length);
47 } else {
48 // Otherwise shift the fixed size event to the right.
49 char* addr = reinterpret_cast<char*>(xcb_event);
50 memmove(addr + offset, addr, ge_length);
51 event_bytes = base::MakeRefCounted<OffsetRefCountedMemory>(
52 event_bytes, offset, ge_length + extended_length);
53 xcb_event = reinterpret_cast<xcb_generic_event_t*>(addr + offset);
54 }
55 }
56 }
57
58 // Xlib sometimes modifies |xcb_event|, so let it handle the event after
59 // we parse it with ReadEvent().
60 ReadBuffer buf(event_bytes);
61 ReadEvent(this, connection, &buf);
62 }
63
Event(Event && event)64 Event::Event(Event&& event) {
65 memcpy(this, &event, sizeof(Event));
66 memset(&event, 0, sizeof(Event));
67 }
68
operator =(Event && event)69 Event& Event::operator=(Event&& event) {
70 Dealloc();
71 memcpy(this, &event, sizeof(Event));
72 memset(&event, 0, sizeof(Event));
73 return *this;
74 }
75
~Event()76 Event::~Event() {
77 Dealloc();
78 }
79
Dealloc()80 void Event::Dealloc() {
81 if (deleter_)
82 deleter_(event_);
83 }
84
85 } // namespace x11
86