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 #ifndef UI_GFX_X_CONNECTION_H_
6 #define UI_GFX_X_CONNECTION_H_
7
8 #include <queue>
9
10 #include "base/component_export.h"
11 #include "base/containers/circular_deque.h"
12 #include "base/sequence_checker.h"
13 #include "ui/events/platform/platform_event_source.h"
14 #include "ui/gfx/x/event.h"
15 #include "ui/gfx/x/extension_manager.h"
16 #include "ui/gfx/x/xlib_support.h"
17 #include "ui/gfx/x/xproto.h"
18
19 typedef struct xcb_connection_t xcb_connection_t;
20
21 namespace x11 {
22
23 class KeyboardState;
24
25 // Represents a socket to the X11 server.
COMPONENT_EXPORT(X11)26 class COMPONENT_EXPORT(X11) Connection : public XProto,
27 public ExtensionManager {
28 public:
29 using ErrorHandler = base::RepeatingCallback<void(const Error*, const char*)>;
30 using IOErrorHandler = base::OnceClosure;
31
32 class Delegate {
33 public:
34 virtual bool ShouldContinueStream() const = 0;
35 virtual void DispatchXEvent(x11::Event* event) = 0;
36
37 protected:
38 virtual ~Delegate() = default;
39 };
40
41 struct VisualInfo {
42 const Format* format;
43 const VisualType* visual_type;
44 };
45
46 // Gets or creates the thread local connection instance.
47 static Connection* Get();
48
49 // Sets the thread local connection instance.
50 static void Set(std::unique_ptr<x11::Connection> connection);
51
52 explicit Connection(const std::string& address = "");
53 ~Connection();
54
55 Connection(const Connection&) = delete;
56 Connection(Connection&&) = delete;
57
58 xcb_connection_t* XcbConnection();
59
60 // Obtain an Xlib display that's connected to the same server as |this|. This
61 // is meant to be used only for compatibility with components like GLX,
62 // Vulkan, and VAAPI. The underlying socket is not shared, so synchronization
63 // with |this| may be necessary. The |type| parameter can be used to achieve
64 // synchronization. The returned wrapper should not be saved.
65 XlibDisplayWrapper GetXlibDisplay(
66 XlibDisplayType type = XlibDisplayType::kNormal);
67
68 uint32_t extended_max_request_length() const {
69 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
70 return extended_max_request_length_;
71 }
72
73 const Setup& setup() const {
74 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
75 return setup_;
76 }
77 const Screen& default_screen() const {
78 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
79 return *default_screen_;
80 }
81 x11::Window default_root() const {
82 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
83 return default_screen().root;
84 }
85 const Depth& default_root_depth() const {
86 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
87 return *default_root_depth_;
88 }
89 const VisualType& default_root_visual() const {
90 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
91 return *default_root_visual_;
92 }
93
94 // Returns the underlying socket's FD if the connection is valid, or -1
95 // otherwise.
96 int GetFd();
97
98 const std::string& DisplayString() const;
99
100 std::string GetConnectionHostname() const;
101
102 int DefaultScreenId() const;
103
104 template <typename T>
105 T GenerateId() {
106 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
107 return static_cast<T>(GenerateIdImpl());
108 }
109
110 // Is the connection up and error-free?
111 bool Ready() const;
112
113 // Write all requests to the socket.
114 void Flush();
115
116 // Flush and block until the server has responded to all requests.
117 void Sync();
118
119 // If |synchronous| is true, this makes all requests Sync().
120 void SynchronizeForTest(bool synchronous);
121
122 bool synchronous() const { return synchronous_; }
123
124 // Read all responses from the socket without blocking.
125 void ReadResponses();
126
127 Event WaitForNextEvent();
128
129 // Are there any events, errors, or replies already buffered?
130 bool HasPendingResponses();
131
132 // Dispatch any buffered events, errors, or replies.
133 void Dispatch(Delegate* delegate);
134
135 // Returns the old error handler.
136 ErrorHandler SetErrorHandler(ErrorHandler new_handler);
137
138 void SetIOErrorHandler(IOErrorHandler new_handler);
139
140 // Returns the visual data for |id|, or nullptr if the visual with that ID
141 // doesn't exist or only exists on a non-default screen.
142 const VisualInfo* GetVisualInfoFromId(VisualId id) const;
143
144 KeyCode KeysymToKeycode(uint32_t keysym) const;
145
146 uint32_t KeycodeToKeysym(KeyCode keycode, uint32_t modifiers) const;
147
148 // Access the event buffer. Clients may modify the queue, including
149 // "deleting" events by setting events[i] = x11::Event(), which will
150 // guarantee all calls to x11::Event::As() will return nullptr.
151 base::circular_deque<Event>& events() {
152 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
153 return events_;
154 }
155
156 std::unique_ptr<Connection> Clone() const;
157
158 // Releases ownership of this connection to a different thread.
159 void DetachFromSequence();
160
161 // The viz compositor thread hangs a PlatformEventSource off the connection so
162 // that it gets destroyed at the appropriate time.
163 // TODO(thomasanderson): This is a layering violation and this should be moved
164 // somewhere else.
165 std::unique_ptr<ui::PlatformEventSource> platform_event_source;
166
167 private:
168 friend class FutureBase;
169
170 struct Request {
171 Request(unsigned int sequence, FutureBase::ResponseCallback callback);
172 Request(Request&& other);
173 ~Request();
174
175 const unsigned int sequence;
176 FutureBase::ResponseCallback callback;
177 bool have_response = false;
178 FutureBase::RawReply reply;
179 FutureBase::RawError error;
180 };
181
182 void InitRootDepthAndVisual();
183
184 void AddRequest(unsigned int sequence, FutureBase::ResponseCallback callback);
185
186 bool HasNextResponse();
187
188 bool HasNextEvent();
189
190 void PreDispatchEvent(const Event& event);
191
192 int ScreenIndexFromRootWindow(x11::Window root) const;
193
194 // This function is implemented in the generated read_error.cc.
195 void InitErrorParsers();
196
197 std::unique_ptr<Error> ParseError(FutureBase::RawError error_bytes);
198
199 uint32_t GenerateIdImpl();
200
201 xcb_connection_t* connection_ = nullptr;
202 std::unique_ptr<XlibDisplay> xlib_display_;
203
204 bool synchronous_ = false;
205 bool syncing_ = false;
206
207 uint32_t extended_max_request_length_ = 0;
208
209 std::string display_string_;
210 int default_screen_id_ = 0;
211 Setup setup_;
212 Screen* default_screen_ = nullptr;
213 Depth* default_root_depth_ = nullptr;
214 VisualType* default_root_visual_ = nullptr;
215
216 std::unordered_map<VisualId, VisualInfo> default_screen_visuals_;
217
218 std::unique_ptr<KeyboardState> keyboard_state_;
219
220 base::circular_deque<Event> events_;
221
222 std::queue<Request> requests_;
223
224 using ErrorParser =
225 std::unique_ptr<Error> (*)(FutureBase::RawError error_bytes);
226 std::array<ErrorParser, 256> error_parsers_{};
227
228 ErrorHandler error_handler_;
229 IOErrorHandler io_error_handler_;
230
231 SEQUENCE_CHECKER(sequence_checker_);
232 };
233
234 } // namespace x11
235
236 #endif // UI_GFX_X_CONNECTION_H_
237