1 | /* |
2 | * Copyright © 2013 Ran Benita |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 | * DEALINGS IN THE SOFTWARE. |
22 | */ |
23 | |
24 | #ifndef _XKBCOMMON_X11_H |
25 | #define _XKBCOMMON_X11_H |
26 | |
27 | #include <xcb/xcb.h> |
28 | #include <xkbcommon/xkbcommon.h> |
29 | |
30 | #ifdef __cplusplus |
31 | extern "C" { |
32 | #endif |
33 | |
34 | /** |
35 | * @file |
36 | * libxkbcommon-x11 API - Additional X11 support for xkbcommon. |
37 | */ |
38 | |
39 | /** |
40 | * @defgroup x11 X11 support |
41 | * Additional X11 support for xkbcommon. |
42 | * @since 0.4.0 |
43 | * |
44 | * @{ |
45 | */ |
46 | |
47 | /** |
48 | * @page x11-overview Overview |
49 | * @parblock |
50 | * |
51 | * The xkbcommon-x11 module provides a means for creating an xkb_keymap |
52 | * corresponding to the currently active keymap on the X server. To do |
53 | * so, it queries the XKB X11 extension using the xcb-xkb library. It |
54 | * can be used as a replacement for Xlib's keyboard handling. |
55 | * |
56 | * Following is an example workflow using xkbcommon-x11. A complete |
57 | * example may be found in the tools/interactive-x11.c file in the |
58 | * xkbcommon source repository. On startup: |
59 | * |
60 | * 1. Connect to the X server using xcb_connect(). |
61 | * 2. Setup the XKB X11 extension. You can do this either by using the |
62 | * xcb_xkb_use_extension() request directly, or by using the |
63 | * xkb_x11_setup_xkb_extension() helper function. |
64 | * |
65 | * The XKB extension supports using separate keymaps and states for |
66 | * different keyboard devices. The devices are identified by an integer |
67 | * device ID and are managed by another X11 extension, XInput. The |
68 | * original X11 protocol only had one keyboard device, called the "core |
69 | * keyboard", which is still supported as a "virtual device". |
70 | * |
71 | * 3. We will use the core keyboard as an example. To get its device ID, |
72 | * use either the xcb_xkb_get_device_info() request directly, or the |
73 | * xkb_x11_get_core_keyboard_device_id() helper function. |
74 | * 4. Create an initial xkb_keymap for this device, using the |
75 | * xkb_x11_keymap_new_from_device() function. |
76 | * 5. Create an initial xkb_state for this device, using the |
77 | * xkb_x11_state_new_from_device() function. |
78 | * |
79 | * @note At this point, you may consider setting various XKB controls and |
80 | * XKB per-client flags. For example, enabling detectable autorepeat: \n |
81 | * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat |
82 | * |
83 | * Next, you need to react to state changes (e.g. a modifier was pressed, |
84 | * the layout was changed) and to keymap changes (e.g. a tool like xkbcomp, |
85 | * setxkbmap or xmodmap was used): |
86 | * |
87 | * 6. Select to listen to at least the following XKB events: |
88 | * NewKeyboardNotify, MapNotify, StateNotify; using the |
89 | * xcb_xkb_select_events_aux() request. |
90 | * 7. When NewKeyboardNotify or MapNotify are received, recreate the |
91 | * xkb_keymap and xkb_state as described above. |
92 | * 8. When StateNotify is received, update the xkb_state accordingly |
93 | * using the xkb_state_update_mask() function. |
94 | * |
95 | * @note It is also possible to use the KeyPress/KeyRelease @p state |
96 | * field to find the effective modifier and layout state, instead of |
97 | * using XkbStateNotify: \n |
98 | * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State |
99 | * \n However, XkbStateNotify is more accurate. |
100 | * |
101 | * @note There is no need to call xkb_state_update_key(); the state is |
102 | * already synchronized. |
103 | * |
104 | * Finally, when a key event is received, you can use ordinary xkbcommon |
105 | * functions, like xkb_state_key_get_one_sym() and xkb_state_key_get_utf8(), |
106 | * as you normally would. |
107 | * |
108 | * @endparblock |
109 | */ |
110 | |
111 | /** |
112 | * The minimal compatible major version of the XKB X11 extension which |
113 | * this library can use. |
114 | */ |
115 | #define XKB_X11_MIN_MAJOR_XKB_VERSION 1 |
116 | /** |
117 | * The minimal compatible minor version of the XKB X11 extension which |
118 | * this library can use (for the minimal major version). |
119 | */ |
120 | #define XKB_X11_MIN_MINOR_XKB_VERSION 0 |
121 | |
122 | /** Flags for the xkb_x11_setup_xkb_extension() function. */ |
123 | enum xkb_x11_setup_xkb_extension_flags { |
124 | /** Do not apply any flags. */ |
125 | XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0 |
126 | }; |
127 | |
128 | /** |
129 | * Setup the XKB X11 extension for this X client. |
130 | * |
131 | * The xkbcommon-x11 library uses various XKB requests. Before doing so, |
132 | * an X client must notify the server that it will be using the extension. |
133 | * This function (or an XCB equivalent) must be called before any other |
134 | * function in this library is used. |
135 | * |
136 | * Some X servers may not support or disable the XKB extension. If you |
137 | * want to support such servers, you need to use a different fallback. |
138 | * |
139 | * You may call this function several times; it is idempotent. |
140 | * |
141 | * @param connection |
142 | * An XCB connection to the X server. |
143 | * @param major_xkb_version |
144 | * See @p minor_xkb_version. |
145 | * @param minor_xkb_version |
146 | * The XKB extension version to request. To operate correctly, you |
147 | * must have (major_xkb_version, minor_xkb_version) >= |
148 | * (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION), |
149 | * though this is not enforced. |
150 | * @param flags |
151 | * Optional flags, or 0. |
152 | * @param[out] major_xkb_version_out |
153 | * See @p minor_xkb_version_out. |
154 | * @param[out] minor_xkb_version_out |
155 | * Backfilled with the compatible XKB extension version numbers picked |
156 | * by the server. Can be NULL. |
157 | * @param[out] base_event_out |
158 | * Backfilled with the XKB base (also known as first) event code, needed |
159 | * to distinguish XKB events. Can be NULL. |
160 | * @param[out] base_error_out |
161 | * Backfilled with the XKB base (also known as first) error code, needed |
162 | * to distinguish XKB errors. Can be NULL. |
163 | * |
164 | * @returns 1 on success, or 0 on failure. |
165 | */ |
166 | int |
167 | xkb_x11_setup_xkb_extension(xcb_connection_t *connection, |
168 | uint16_t major_xkb_version, |
169 | uint16_t minor_xkb_version, |
170 | enum xkb_x11_setup_xkb_extension_flags flags, |
171 | uint16_t *major_xkb_version_out, |
172 | uint16_t *minor_xkb_version_out, |
173 | uint8_t *base_event_out, |
174 | uint8_t *base_error_out); |
175 | |
176 | /** |
177 | * Get the keyboard device ID of the core X11 keyboard. |
178 | * |
179 | * @param connection An XCB connection to the X server. |
180 | * |
181 | * @returns A device ID which may be used with other xkb_x11_* functions, |
182 | * or -1 on failure. |
183 | */ |
184 | int32_t |
185 | xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection); |
186 | |
187 | /** |
188 | * Create a keymap from an X11 keyboard device. |
189 | * |
190 | * This function queries the X server with various requests, fetches the |
191 | * details of the active keymap on a keyboard device, and creates an |
192 | * xkb_keymap from these details. |
193 | * |
194 | * @param context |
195 | * The context in which to create the keymap. |
196 | * @param connection |
197 | * An XCB connection to the X server. |
198 | * @param device_id |
199 | * An XInput device ID (in the range 0-127) with input class KEY. |
200 | * Passing values outside of this range is an error (the XKB protocol |
201 | * predates the XInput2 protocol, which first allowed IDs > 127). |
202 | * @param flags |
203 | * Optional flags for the keymap, or 0. |
204 | * |
205 | * @returns A keymap retrieved from the X server, or NULL on failure. |
206 | * |
207 | * @memberof xkb_keymap |
208 | */ |
209 | struct xkb_keymap * |
210 | xkb_x11_keymap_new_from_device(struct xkb_context *context, |
211 | xcb_connection_t *connection, |
212 | int32_t device_id, |
213 | enum xkb_keymap_compile_flags flags); |
214 | |
215 | /** |
216 | * Create a new keyboard state object from an X11 keyboard device. |
217 | * |
218 | * This function is the same as xkb_state_new(), only pre-initialized |
219 | * with the state of the device at the time this function is called. |
220 | * |
221 | * @param keymap |
222 | * The keymap for which to create the state. |
223 | * @param connection |
224 | * An XCB connection to the X server. |
225 | * @param device_id |
226 | * An XInput 1 device ID (in the range 0-255) with input class KEY. |
227 | * Passing values outside of this range is an error. |
228 | * |
229 | * @returns A new keyboard state object, or NULL on failure. |
230 | * |
231 | * @memberof xkb_state |
232 | */ |
233 | struct xkb_state * |
234 | xkb_x11_state_new_from_device(struct xkb_keymap *keymap, |
235 | xcb_connection_t *connection, |
236 | int32_t device_id); |
237 | |
238 | /** @} */ |
239 | |
240 | #ifdef __cplusplus |
241 | } /* extern "C" */ |
242 | #endif |
243 | |
244 | #endif /* _XKBCOMMON_X11_H */ |
245 | |