Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef XENOLITH_PLATFORM_LINUX_XLPLATFORMLINUXXCB_H_
24 : #define XENOLITH_PLATFORM_LINUX_XLPLATFORMLINUXXCB_H_
25 :
26 : #include "XLCommon.h"
27 : #include "SPDso.h"
28 :
29 : #if LINUX
30 :
31 : #include <xcb/xcb.h>
32 : #include <xcb/randr.h>
33 : #include <xcb/xcb_keysyms.h>
34 :
35 : #define explicit _explicit;
36 : #include <xcb/xkb.h>
37 : #undef explicit
38 :
39 : #define XL_X11_DEBUG 0
40 :
41 : namespace STAPPLER_VERSIONIZED stappler::xenolith::platform {
42 :
43 : class XcbLibrary : public Ref {
44 : public:
45 : static constexpr int RANDR_MAJOR_VERSION = XCB_RANDR_MAJOR_VERSION;
46 : static constexpr int RANDR_MINOR_VERSION = XCB_RANDR_MINOR_VERSION;
47 :
48 : struct ConnectionData {
49 : int screen_nbr = -1;
50 : xcb_connection_t *connection = nullptr;
51 : const xcb_setup_t *setup = nullptr;
52 : xcb_screen_t *screen = nullptr;
53 : };
54 :
55 : static XcbLibrary *getInstance();
56 :
57 10 : XcbLibrary() { }
58 :
59 : virtual ~XcbLibrary();
60 :
61 : bool init();
62 :
63 : bool open(Dso &handle);
64 : void close();
65 :
66 : bool hasRandr() const;
67 : bool hasKeysyms() const;
68 : bool hasXkb() const;
69 :
70 : xcb_connection_t * (* xcb_connect) (const char *displayname, int *screenp) = nullptr;
71 : const struct xcb_setup_t * (* xcb_get_setup) (xcb_connection_t *c) = nullptr;
72 : xcb_screen_iterator_t (* xcb_setup_roots_iterator) (const xcb_setup_t *R) = nullptr;
73 : void (* xcb_screen_next) (xcb_screen_iterator_t *i) = nullptr;
74 :
75 : int (* xcb_connection_has_error) (xcb_connection_t *c) = nullptr;
76 : int (* xcb_get_file_descriptor) (xcb_connection_t *c) = nullptr;
77 : uint32_t (* xcb_generate_id) (xcb_connection_t *c) = nullptr;
78 : int (*xcb_flush) (xcb_connection_t *c) = nullptr;
79 : void (* xcb_disconnect) (xcb_connection_t *c) = nullptr;
80 : xcb_generic_event_t * (* xcb_poll_for_event) (xcb_connection_t *c) = nullptr;
81 : xcb_void_cookie_t (*xcb_send_event) (xcb_connection_t *c, uint8_t propagate,
82 : xcb_window_t destination, uint32_t event_mask, const char *event) = nullptr;
83 :
84 : const struct xcb_query_extension_reply_t *(* xcb_get_extension_data) (xcb_connection_t *c, xcb_extension_t *ext) = nullptr;
85 :
86 : xcb_void_cookie_t (* xcb_map_window) (xcb_connection_t *c, xcb_window_t window) = nullptr;
87 :
88 : xcb_void_cookie_t (* xcb_create_window) (xcb_connection_t *c, uint8_t depth, xcb_window_t wid,
89 : xcb_window_t parent, int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t border_width,
90 : uint16_t _class, xcb_visualid_t visual, uint32_t value_mask, const void *value_list) = nullptr;
91 :
92 : xcb_void_cookie_t (* xcb_change_property) (xcb_connection_t *c, uint8_t mode, xcb_window_t window,
93 : xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t data_len, const void *data) = nullptr;
94 :
95 : xcb_intern_atom_cookie_t (* xcb_intern_atom) (xcb_connection_t *c, uint8_t only_if_exists,
96 : uint16_t name_len,const char *name) = nullptr;
97 :
98 : xcb_intern_atom_reply_t * (* xcb_intern_atom_reply) (xcb_connection_t *c, xcb_intern_atom_cookie_t cookie,
99 : xcb_generic_error_t **e) = nullptr;
100 :
101 : xcb_get_property_reply_t* (* xcb_get_property_reply) (xcb_connection_t *c, xcb_get_property_cookie_t cookie,
102 : xcb_generic_error_t **e) = nullptr;
103 : xcb_get_property_cookie_t (*xcb_get_property) (xcb_connection_t *c, uint8_t _delete, xcb_window_t window,
104 : xcb_atom_t property, xcb_atom_t type, uint32_t long_offset, uint32_t long_length) = nullptr;
105 : void * (* xcb_get_property_value) (const xcb_get_property_reply_t *R) = nullptr;
106 : int (* xcb_get_property_value_length) (const xcb_get_property_reply_t *R) = nullptr;
107 :
108 : void * (* xcb_wait_for_reply) (xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e) = nullptr;
109 :
110 : xcb_get_modifier_mapping_cookie_t (* xcb_get_modifier_mapping_unchecked) (xcb_connection_t *c) = nullptr;
111 : xcb_get_modifier_mapping_reply_t * (* xcb_get_modifier_mapping_reply) (xcb_connection_t *c,
112 : xcb_get_modifier_mapping_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
113 : xcb_keycode_t * (* xcb_get_modifier_mapping_keycodes) (const xcb_get_modifier_mapping_reply_t *) = nullptr;
114 :
115 : xcb_void_cookie_t (* xcb_convert_selection) (xcb_connection_t *c, xcb_window_t requestor,
116 : xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t time) = nullptr;
117 : xcb_void_cookie_t (* xcb_set_selection_owner) (xcb_connection_t *c, xcb_window_t owner,
118 : xcb_atom_t selection, xcb_timestamp_t time) = nullptr;
119 : xcb_get_selection_owner_cookie_t (* xcb_get_selection_owner) (xcb_connection_t *c,
120 : xcb_atom_t selection) = nullptr;
121 : xcb_get_selection_owner_reply_t* (* xcb_get_selection_owner_reply) (xcb_connection_t *c,
122 : xcb_get_selection_owner_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
123 :
124 : xcb_get_keyboard_mapping_cookie_t (*xcb_get_keyboard_mapping)(xcb_connection_t *c,
125 : xcb_keycode_t first_keycode, uint8_t count) = nullptr;
126 : xcb_get_keyboard_mapping_reply_t * (* xcb_get_keyboard_mapping_reply) (xcb_connection_t *c,
127 : xcb_get_keyboard_mapping_cookie_t cookie /**< */, xcb_generic_error_t **e) = nullptr;
128 :
129 : xcb_extension_t *xcb_randr_id = nullptr;
130 :
131 : xcb_randr_query_version_cookie_t (* xcb_randr_query_version) (xcb_connection_t *c,
132 : uint32_t major_version, uint32_t minor_version) = nullptr;
133 : xcb_randr_query_version_reply_t * (* xcb_randr_query_version_reply) (xcb_connection_t *c,
134 : xcb_randr_query_version_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
135 : xcb_randr_get_screen_info_cookie_t (* xcb_randr_get_screen_info_unchecked) (xcb_connection_t *c,
136 : xcb_window_t window) = nullptr;
137 : xcb_randr_get_screen_info_reply_t * (* xcb_randr_get_screen_info_reply) (xcb_connection_t *c,
138 : xcb_randr_get_screen_info_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
139 :
140 : xcb_randr_screen_size_t * (* xcb_randr_get_screen_info_sizes) (const xcb_randr_get_screen_info_reply_t *) = nullptr;
141 : int (* xcb_randr_get_screen_info_sizes_length) (const xcb_randr_get_screen_info_reply_t *) = nullptr;
142 : xcb_randr_screen_size_iterator_t (* xcb_randr_get_screen_info_sizes_iterator) (const xcb_randr_get_screen_info_reply_t *) = nullptr;
143 :
144 : int (* xcb_randr_get_screen_info_rates_length) (const xcb_randr_get_screen_info_reply_t *) = nullptr;
145 : xcb_randr_refresh_rates_iterator_t (* xcb_randr_get_screen_info_rates_iterator) (const xcb_randr_get_screen_info_reply_t *) = nullptr;
146 : void (* xcb_randr_refresh_rates_next) (xcb_randr_refresh_rates_iterator_t *) = nullptr;
147 : xcb_generic_iterator_t (* xcb_randr_refresh_rates_end) (xcb_randr_refresh_rates_iterator_t) = nullptr;
148 : uint16_t * (* xcb_randr_refresh_rates_rates) (const xcb_randr_refresh_rates_t *) = nullptr;
149 : int (* xcb_randr_refresh_rates_rates_length) (const xcb_randr_refresh_rates_t *) = nullptr;
150 :
151 : xcb_randr_get_screen_resources_cookie_t (* xcb_randr_get_screen_resources) (
152 : xcb_connection_t *c, xcb_window_t window) = nullptr;
153 : xcb_randr_get_screen_resources_cookie_t (* xcb_randr_get_screen_resources_unchecked) (
154 : xcb_connection_t *c, xcb_window_t window) = nullptr;
155 : xcb_randr_get_screen_resources_reply_t * (* xcb_randr_get_screen_resources_reply) (
156 : xcb_connection_t *c, xcb_randr_get_screen_resources_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
157 : xcb_randr_mode_info_t * (* xcb_randr_get_screen_resources_modes) (const xcb_randr_get_screen_resources_reply_t *R) = nullptr;
158 : int (* xcb_randr_get_screen_resources_modes_length) (const xcb_randr_get_screen_resources_reply_t *R) = nullptr;
159 :
160 : xcb_randr_get_screen_resources_current_cookie_t (* xcb_randr_get_screen_resources_current) (
161 : xcb_connection_t *c, xcb_window_t window) = nullptr;
162 : xcb_randr_get_screen_resources_current_cookie_t (* xcb_randr_get_screen_resources_current_unchecked) (
163 : xcb_connection_t *c, xcb_window_t window) = nullptr;
164 : xcb_randr_get_screen_resources_current_reply_t * (* xcb_randr_get_screen_resources_current_reply) (
165 : xcb_connection_t *c, xcb_randr_get_screen_resources_current_cookie_t cookie, xcb_generic_error_t **e) = nullptr;
166 : xcb_randr_output_t* (* xcb_randr_get_screen_resources_current_outputs) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
167 : int (* xcb_randr_get_screen_resources_current_outputs_length) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
168 : xcb_randr_mode_info_t * (* xcb_randr_get_screen_resources_current_modes) (
169 : const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
170 : int (* xcb_randr_get_screen_resources_current_modes_length) (
171 : const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
172 : uint8_t* (* xcb_randr_get_screen_resources_current_names) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
173 : int (* xcb_randr_get_screen_resources_current_names_length) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
174 : xcb_randr_crtc_t* (* xcb_randr_get_screen_resources_current_crtcs) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
175 : int (* xcb_randr_get_screen_resources_current_crtcs_length) (const xcb_randr_get_screen_resources_current_reply_t *) = nullptr;
176 :
177 : xcb_randr_get_output_primary_cookie_t (* xcb_randr_get_output_primary) (xcb_connection_t *, xcb_window_t) = nullptr;
178 : xcb_randr_get_output_primary_cookie_t (* xcb_randr_get_output_primary_unchecked) (xcb_connection_t *, xcb_window_t) = nullptr;
179 : xcb_randr_get_output_primary_reply_t * (* xcb_randr_get_output_primary_reply) (xcb_connection_t *,
180 : xcb_randr_get_output_primary_cookie_t, xcb_generic_error_t **) = nullptr;
181 :
182 : xcb_randr_get_output_info_cookie_t (* xcb_randr_get_output_info) (xcb_connection_t *,
183 : xcb_randr_output_t, xcb_timestamp_t) = nullptr;
184 : xcb_randr_get_output_info_cookie_t (* xcb_randr_get_output_info_unchecked) (xcb_connection_t *,
185 : xcb_randr_output_t, xcb_timestamp_t) = nullptr;
186 : xcb_randr_get_output_info_reply_t* (* xcb_randr_get_output_info_reply) (xcb_connection_t *,
187 : xcb_randr_get_output_info_cookie_t, xcb_generic_error_t **) = nullptr;
188 : xcb_randr_crtc_t * (* xcb_randr_get_output_info_crtcs) (const xcb_randr_get_output_info_reply_t *) = nullptr;
189 : int (* xcb_randr_get_output_info_crtcs_length) (const xcb_randr_get_output_info_reply_t *) = nullptr;
190 : xcb_generic_iterator_t (* xcb_randr_get_output_info_crtcs_end) (const xcb_randr_get_output_info_reply_t *) = nullptr;
191 : xcb_randr_mode_t * (* xcb_randr_get_output_info_modes) (const xcb_randr_get_output_info_reply_t *) = nullptr;
192 : int (* xcb_randr_get_output_info_modes_length) (const xcb_randr_get_output_info_reply_t *) = nullptr;
193 : uint8_t * (* xcb_randr_get_output_info_name) (const xcb_randr_get_output_info_reply_t *) = nullptr;
194 : int (* xcb_randr_get_output_info_name_length) (const xcb_randr_get_output_info_reply_t *) = nullptr;
195 :
196 : xcb_randr_get_crtc_info_cookie_t (* xcb_randr_get_crtc_info) (xcb_connection_t *, xcb_randr_crtc_t, xcb_timestamp_t) = nullptr;
197 : xcb_randr_get_crtc_info_cookie_t (* xcb_randr_get_crtc_info_unchecked) (xcb_connection_t *, xcb_randr_crtc_t, xcb_timestamp_t) = nullptr;
198 : xcb_randr_get_crtc_info_reply_t* (* xcb_randr_get_crtc_info_reply) (xcb_connection_t *,
199 : xcb_randr_get_crtc_info_cookie_t, xcb_generic_error_t **) = nullptr;
200 : xcb_randr_output_t* (* xcb_randr_get_crtc_info_outputs) (const xcb_randr_get_crtc_info_reply_t *) = nullptr;
201 : int (* xcb_randr_get_crtc_info_outputs_length) (const xcb_randr_get_crtc_info_reply_t *) = nullptr;
202 : xcb_randr_output_t* (* xcb_randr_get_crtc_info_possible) (const xcb_randr_get_crtc_info_reply_t *) = nullptr;
203 : int (* xcb_randr_get_crtc_info_possible_length) (const xcb_randr_get_crtc_info_reply_t *) = nullptr;
204 :
205 : xcb_key_symbols_t * (* xcb_key_symbols_alloc) (xcb_connection_t *c) = nullptr;
206 : void (* xcb_key_symbols_free) (xcb_key_symbols_t *syms) = nullptr;
207 :
208 : xcb_keysym_t (* xcb_key_symbols_get_keysym) (xcb_key_symbols_t *syms, xcb_keycode_t keycode, int col) = nullptr;
209 : xcb_keycode_t * (* xcb_key_symbols_get_keycode) (xcb_key_symbols_t *syms, xcb_keysym_t keysym) = nullptr;
210 : xcb_keysym_t (* xcb_key_press_lookup_keysym) (xcb_key_symbols_t *syms, xcb_key_press_event_t *event, int col) = nullptr;
211 : xcb_keysym_t (* xcb_key_release_lookup_keysym) (xcb_key_symbols_t *syms, xcb_key_release_event_t *event, int col) = nullptr;
212 : int (* xcb_refresh_keyboard_mapping) (xcb_key_symbols_t *syms, xcb_mapping_notify_event_t *event) = nullptr;
213 :
214 : int (* xcb_is_keypad_key) (xcb_keysym_t keysym) = nullptr;
215 : int (* xcb_is_private_keypad_key) (xcb_keysym_t keysym) = nullptr;
216 : int (* xcb_is_cursor_key) (xcb_keysym_t keysym) = nullptr;
217 : int (* xcb_is_pf_key) (xcb_keysym_t keysym) = nullptr;
218 : int (* xcb_is_function_key) (xcb_keysym_t keysym) = nullptr;
219 : int (* xcb_is_misc_function_key) (xcb_keysym_t keysym) = nullptr;
220 : int (* xcb_is_modifier_key) (xcb_keysym_t keysym) = nullptr;
221 :
222 : xcb_void_cookie_t (* xcb_xkb_select_events) (xcb_connection_t *c, xcb_xkb_device_spec_t deviceSpec,
223 : uint16_t affectWhich, uint16_t clear, uint16_t selectAll, uint16_t affectMap, uint16_t map, const void *details) = nullptr;
224 :
225 : ConnectionData acquireConnection();
226 : ConnectionData getActiveConnection() const;
227 :
228 : protected:
229 : void openAux();
230 : void openConnection(ConnectionData &data);
231 :
232 : Dso _handle;
233 : Dso _randr;
234 : Dso _keysyms;
235 : Dso _xkb;
236 :
237 : ConnectionData _pending;
238 : ConnectionData _current;
239 : };
240 :
241 : enum class XcbAtomIndex {
242 : WM_PROTOCOLS,
243 : WM_DELETE_WINDOW,
244 : WM_NAME,
245 : WM_ICON_NAME,
246 : SAVE_TARGETS,
247 : CLIPBOARD,
248 : PRIMARY,
249 : TARGETS,
250 : MULTIPLE,
251 : STRING,
252 : XNULL,
253 : XENOLITH_CLIPBOARD
254 : };
255 :
256 : struct XcbAtomRequest {
257 : StringView name;
258 : bool onlyIfExists;
259 : };
260 :
261 : static XcbAtomRequest s_atomRequests[] = {
262 : { "WM_PROTOCOLS", true },
263 : { "WM_DELETE_WINDOW", false },
264 : { "WM_NAME", false },
265 : { "WM_ICON_NAME", false },
266 : { "SAVE_TARGETS", false },
267 : { "CLIPBOARD", false },
268 : { "PRIMARY", false },
269 : { "TARGETS", false },
270 : { "MULTIPLE", false },
271 : { "UTF8_STRING", false },
272 : { "NULL", false },
273 : { "XENOLITH_CLIPBOARD", false },
274 : };
275 :
276 : }
277 :
278 : #endif
279 :
280 : #endif /* XENOLITH_PLATFORM_LINUX_XLPLATFORMLINUXXCB_H_ */
|