-
Notifications
You must be signed in to change notification settings - Fork 15
/
core.hpp
339 lines (284 loc) · 7.89 KB
/
core.hpp
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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#ifndef XPP_CORE_HPP
#define XPP_CORE_HPP
#include <string>
#include <memory>
#include <xcb/xcb.h>
namespace xpp {
class connection_error
: public std::runtime_error
{
public:
connection_error(uint8_t code, const std::string & description)
: std::runtime_error(description + "(" + std::to_string(code) + ")")
, m_code(code)
, m_description(description)
{}
uint8_t
code(void)
{
return m_code;
}
std::string
description(void)
{
return m_description;
}
protected:
uint8_t m_code;
std::string m_description;
};
class core
{
protected:
using shared_generic_event_ptr = std::shared_ptr<xcb_generic_event_t>;
int m_screen = 0;
// reference counting for xcb_connection_t
std::shared_ptr<xcb_connection_t> m_c;
shared_generic_event_ptr
dispatch(const std::string & producer, xcb_generic_event_t * event) const
{
if (event) {
if (event->response_type == 0) {
throw std::shared_ptr<xcb_generic_error_t>(
reinterpret_cast<xcb_generic_error_t *>(event));
}
return shared_generic_event_ptr(event, std::free);
}
check_connection();
throw std::runtime_error(producer + " failed");
}
public:
explicit
core(xcb_connection_t * c)
: m_c(std::shared_ptr<xcb_connection_t>(c, [](...) {}))
{}
template<typename ... ConnectionParameter>
explicit
core(xcb_connection_t * (*Connect)(ConnectionParameter ...),
ConnectionParameter ... connection_parameter)
: m_c(std::shared_ptr<xcb_connection_t>(
Connect(connection_parameter ...),
[&](void *) { disconnect(); }))
{}
// xcb_connect (const char *displayname, int *screenp)
explicit
core(const std::string & displayname = "")
: core(xcb_connect, displayname.c_str(), &m_screen)
{}
// xcb_connect_to_fd (int fd, xcb_auth_info_t *auth_info)
explicit
core(int fd, xcb_auth_info_t * auth_info)
: core(xcb_connect_to_fd, fd, auth_info)
{}
// xcb_connect_to_display_with_auth_info (
// const char *display, xcb_auth_info_t *auth, int *screen)
explicit
core(const std::string & display, xcb_auth_info_t * auth)
: core(xcb_connect_to_display_with_auth_info,
display.c_str(), auth, &m_screen)
{}
virtual
~core(void)
{}
virtual
xcb_connection_t *
operator*(void) const
{
return m_c.get();
}
virtual
operator xcb_connection_t *(void) const
{
return m_c.get();
}
virtual
int
default_screen(void) const
{
return m_screen;
}
virtual
int
flush(void) const
{
return xcb_flush(m_c.get());
}
virtual
uint32_t
get_maximum_request_length(void) const
{
return xcb_get_maximum_request_length(m_c.get());
}
virtual
void
prefetch_maximum_request_length(void) const
{
xcb_prefetch_maximum_request_length(m_c.get());
}
virtual
shared_generic_event_ptr
wait_for_event(void) const
{
return dispatch("wait_for_event", xcb_wait_for_event(m_c.get()));
}
virtual
shared_generic_event_ptr
poll_for_event(void) const
{
return shared_generic_event_ptr(xcb_poll_for_event(m_c.get()));
}
virtual
shared_generic_event_ptr
poll_for_queued_event(void) const
{
return shared_generic_event_ptr(xcb_poll_for_queued_event(m_c.get()));
}
virtual
shared_generic_event_ptr
poll_for_special_event(xcb_special_event_t * se) const
{
return shared_generic_event_ptr(xcb_poll_for_special_event(m_c.get(), se));
}
// virtual
// shared_generic_event_ptr
// poll_for_special_event(const std::shared_ptr<xcb_special_event_t> & se) const
// {
// return poll_for_special_event(se.get());
// }
virtual
shared_generic_event_ptr
wait_for_special_event(xcb_special_event_t * se) const
{
return dispatch("wait_for_special_event",
xcb_wait_for_special_event(m_c.get(), se));
}
// virtual
// shared_generic_event_ptr
// wait_for_special_event(const std::shared_ptr<xcb_special_event_t> & se) const
// {
// return wait_for_special_event(se.get());
// }
// xcb_special_event_t has incomplete type -> no std::shared_ptr
virtual
xcb_special_event_t *
register_for_special_xge(xcb_extension_t * ext,
uint32_t eid,
uint32_t * stamp) const
{
return xcb_register_for_special_xge(m_c.get(), ext, eid, stamp);
}
virtual
void
unregister_for_special_event(xcb_special_event_t * se) const
{
xcb_unregister_for_special_event(m_c.get(), se);
}
virtual
std::shared_ptr<xcb_generic_error_t>
request_check(xcb_void_cookie_t cookie) const
{
return std::shared_ptr<xcb_generic_error_t>(
xcb_request_check(m_c.get(), cookie));
}
virtual
void
discard_reply(unsigned int sequence) const
{
xcb_discard_reply(m_c.get(), sequence);
}
// The result must not be freed.
// This storage is managed by the cache itself.
virtual
const xcb_query_extension_reply_t *
get_extension_data(xcb_extension_t * ext) const
{
return xcb_get_extension_data(m_c.get(), ext);
}
virtual
void
prefetch_extension_data(xcb_extension_t * ext) const
{
xcb_prefetch_extension_data(m_c.get(), ext);
}
virtual
const xcb_setup_t *
get_setup(void) const
{
return xcb_get_setup(m_c.get());
}
virtual
int
get_file_descriptor(void) const
{
return xcb_get_file_descriptor(m_c.get());
}
virtual
int
connection_has_error(void) const
{
return xcb_connection_has_error(m_c.get());
}
virtual
void
disconnect(void) const
{
xcb_disconnect(m_c.get());
}
// hostname, display, screen
virtual
std::tuple<std::string, int, int>
parse_display(const std::string & name) const
{
int screen = 0;
int display = 0;
char * host = NULL;
std::string hostname;
xcb_parse_display(name.c_str(), &host, &display, &screen);
if (host != NULL) {
hostname = std::string(host);
}
return std::make_tuple(hostname, display, screen);
}
virtual
uint32_t
generate_id(void) const
{
return xcb_generate_id(m_c.get());
}
xcb_screen_t *
screen_of_display(int screen)
{
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator(xcb_get_setup(m_c.get()));
for (; iter.rem; --screen, xcb_screen_next(&iter))
if (screen == 0)
return iter.data;
return NULL;
}
void
check_connection(void) const
{
switch (xcb_connection_has_error(m_c.get())) {
case XCB_CONN_ERROR:
throw(connection_error(
XCB_CONN_ERROR, "XCB_CONN_ERROR"));
case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
throw(connection_error(XCB_CONN_CLOSED_EXT_NOTSUPPORTED,
"XCB_CONN_CLOSED_EXT_NOTSUPPORTED"));
case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
throw(connection_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT,
"XCB_CONN_CLOSED_MEM_INSUFFICIENT"));
case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
throw(connection_error(XCB_CONN_CLOSED_REQ_LEN_EXCEED,
"XCB_CONN_CLOSED_REQ_LEN_EXCEED"));
case XCB_CONN_CLOSED_PARSE_ERR:
throw(connection_error(XCB_CONN_CLOSED_PARSE_ERR,
"XCB_CONN_CLOSED_PARSE_ERR"));
case XCB_CONN_CLOSED_INVALID_SCREEN:
throw(connection_error(XCB_CONN_CLOSED_INVALID_SCREEN,
"XCB_CONN_CLOSED_INVALID_SCREEN"));
};
}
}; // class core
}; // namespace xpp
#endif // XPP_CORE_HPP