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
31extern "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. */
123enum 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 */
166int
167xkb_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 */
184int32_t
185xkb_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 */
209struct xkb_keymap *
210xkb_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 */
233struct xkb_state *
234xkb_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

source code of include/xkbcommon/xkbcommon-x11.h