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 : #include "XLPlatformLinuxXkb.h" 24 : 25 : #if XL_LINK 26 : extern "C" { 27 : struct xkb_context * xkb_context_new(enum xkb_context_flags flags); 28 : struct xkb_context * xkb_context_ref(struct xkb_context *context); 29 : void xkb_context_unref (struct xkb_context *context); 30 : void xkb_keymap_unref(struct xkb_keymap *keymap); 31 : void xkb_state_unref(struct xkb_state *state); 32 : struct xkb_keymap* xkb_keymap_new_from_string(struct xkb_context *context, const char *string, 33 : enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); 34 : struct xkb_state * xkb_state_new(struct xkb_keymap *keymap); 35 : enum xkb_state_component xkb_state_update_mask(struct xkb_state *, xkb_mod_mask_t depressed_mods, 36 : xkb_mod_mask_t latched_mods, xkb_mod_mask_t locked_mods, xkb_layout_index_t depressed_layout, 37 : xkb_layout_index_t latched_layout, xkb_layout_index_t locked_layout); 38 : int xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t key, char *buffer, size_t size); 39 : uint32_t xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t key); 40 : xkb_keysym_t xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t key); 41 : int xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx, enum xkb_state_component type); 42 : int xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key, const xkb_keysym_t **syms_out); 43 : struct xkb_keymap * xkb_state_get_keymap(struct xkb_state *state); 44 : void xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter, void *data); 45 : const char * xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t key); 46 : xkb_mod_index_t xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name); 47 : int xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t key); 48 : uint32_t xkb_keysym_to_utf32(xkb_keysym_t keysym); 49 : 50 : struct xkb_compose_table * xkb_compose_table_new_from_locale(struct xkb_context *context, 51 : const char *locale, enum xkb_compose_compile_flags flags); 52 : void xkb_compose_table_unref(struct xkb_compose_table *table); 53 : struct xkb_compose_state* xkb_compose_state_new(struct xkb_compose_table *table, enum xkb_compose_state_flags flags); 54 : enum xkb_compose_feed_result xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym); 55 : void xkb_compose_state_reset(struct xkb_compose_state *state); 56 : enum xkb_compose_status xkb_compose_state_get_status(struct xkb_compose_state *state); 57 : xkb_keysym_t xkb_compose_state_get_one_sym(struct xkb_compose_state *state); 58 : void xkb_compose_state_unref(struct xkb_compose_state *state); 59 : 60 : int xkb_x11_setup_xkb_extension(xcb_connection_t *connection, uint16_t major_xkb_version, uint16_t minor_xkb_version, 61 : enum xkb_x11_setup_xkb_extension_flags flags, uint16_t *major_xkb_version_out, uint16_t *minor_xkb_version_out, 62 : uint8_t *base_event_out, uint8_t *base_error_out); 63 : int32_t xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection); 64 : struct xkb_keymap * xkb_x11_keymap_new_from_device(struct xkb_context *context, 65 : xcb_connection_t *connection, int32_t device_id, enum xkb_keymap_compile_flags flags); 66 : struct xkb_state * xkb_x11_state_new_from_device(struct xkb_keymap *keymap, 67 : xcb_connection_t *connection, int32_t device_id); 68 : } 69 : #endif 70 : 71 : namespace STAPPLER_VERSIONIZED stappler::xenolith::platform { 72 : 73 25 : XkbLibrary *XkbLibrary::getInstance() { 74 : static Mutex s_mutex; 75 25 : static Rc<XkbLibrary> s_lib; 76 : 77 25 : std::unique_lock<Mutex> lock(s_mutex); 78 25 : if (!s_lib) { 79 25 : s_lib = Rc<XkbLibrary>::create(); 80 : } 81 : 82 50 : return s_lib; 83 25 : } 84 : 85 50 : XkbLibrary::~XkbLibrary() { 86 25 : close(); 87 50 : } 88 : 89 25 : bool XkbLibrary::init() { 90 : #ifndef XL_LINK 91 25 : _handle = Dso("libxkbcommon.so"); 92 25 : if (!_handle) { 93 0 : log::error("XkbLibrary", "Fail to open libxkbcommon.so"); 94 0 : return false; 95 : } 96 : #endif 97 : 98 25 : if (open(_handle)) { 99 25 : _context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 100 25 : return true; 101 : } else { 102 0 : _handle = Dso(); 103 : } 104 0 : return false; 105 : } 106 : 107 25 : void XkbLibrary::close() { 108 25 : if (_context) { 109 25 : xkb_context_unref(_context); 110 25 : _context = nullptr; 111 : } 112 25 : } 113 : 114 25 : bool XkbLibrary::open(Dso &handle) { 115 : #if XL_LINK 116 : this->xkb_context_new = &::xkb_context_new; 117 : this->xkb_context_ref = &::xkb_context_ref; 118 : this->xkb_context_unref = &::xkb_context_unref; 119 : this->xkb_keymap_unref = &::xkb_keymap_unref; 120 : this->xkb_state_unref = &::xkb_state_unref; 121 : this->xkb_keymap_new_from_string = &::xkb_keymap_new_from_string; 122 : this->xkb_state_new = &::xkb_state_new; 123 : this->xkb_state_update_mask = &::xkb_state_update_mask; 124 : this->xkb_state_key_get_utf8 = &::xkb_state_key_get_utf8; 125 : this->xkb_state_key_get_utf32 = &::xkb_state_key_get_utf32; 126 : this->xkb_state_key_get_one_sym = &::xkb_state_key_get_one_sym; 127 : this->xkb_state_mod_index_is_active = &::xkb_state_mod_index_is_active; 128 : this->xkb_state_key_get_syms = &::xkb_state_key_get_syms; 129 : this->xkb_state_get_keymap = &::xkb_state_get_keymap; 130 : this->xkb_keymap_key_for_each = &::xkb_keymap_key_for_each; 131 : this->xkb_keymap_key_get_name = &::xkb_keymap_key_get_name; 132 : this->xkb_keymap_mod_get_index = &::xkb_keymap_mod_get_index; 133 : this->xkb_keymap_key_repeats = &::xkb_keymap_key_repeats; 134 : this->xkb_keysym_to_utf32 = &::xkb_keysym_to_utf32; 135 : this->xkb_compose_table_new_from_locale = &::xkb_compose_table_new_from_locale; 136 : this->xkb_compose_table_unref = &::xkb_compose_table_unref; 137 : this->xkb_compose_state_new = &::xkb_compose_state_new; 138 : this->xkb_compose_state_feed = &::xkb_compose_state_feed; 139 : this->xkb_compose_state_reset = &::xkb_compose_state_reset; 140 : this->xkb_compose_state_get_status = &::xkb_compose_state_get_status; 141 : this->xkb_compose_state_get_one_sym = &::xkb_compose_state_get_one_sym; 142 : this->xkb_compose_state_unref = &::xkb_compose_state_unref; 143 : #else 144 25 : xkb_context_new = handle.sym<decltype(xkb_context_new)>("xkb_context_new"); 145 25 : xkb_context_ref = handle.sym<decltype(xkb_context_ref)>("xkb_context_ref"); 146 25 : xkb_context_unref = handle.sym<decltype(xkb_context_unref)>("xkb_context_unref"); 147 25 : xkb_keymap_unref = handle.sym<decltype(xkb_keymap_unref)>("xkb_keymap_unref"); 148 25 : xkb_state_unref = handle.sym<decltype(xkb_state_unref)>("xkb_state_unref"); 149 25 : xkb_keymap_new_from_string = handle.sym<decltype(xkb_keymap_new_from_string)>("xkb_keymap_new_from_string"); 150 25 : xkb_state_new = handle.sym<decltype(xkb_state_new)>("xkb_state_new"); 151 25 : xkb_state_update_mask = handle.sym<decltype(xkb_state_update_mask)>("xkb_state_update_mask"); 152 25 : xkb_state_key_get_utf8 = handle.sym<decltype(xkb_state_key_get_utf8)>("xkb_state_key_get_utf8"); 153 25 : xkb_state_key_get_utf32 = handle.sym<decltype(xkb_state_key_get_utf32)>("xkb_state_key_get_utf32"); 154 25 : xkb_state_key_get_one_sym = handle.sym<decltype(xkb_state_key_get_one_sym)>("xkb_state_key_get_one_sym"); 155 25 : xkb_state_mod_index_is_active = handle.sym<decltype(xkb_state_mod_index_is_active)>("xkb_state_mod_index_is_active"); 156 25 : xkb_state_key_get_syms = handle.sym<decltype(xkb_state_key_get_syms)>("xkb_state_key_get_syms"); 157 25 : xkb_state_get_keymap = handle.sym<decltype(xkb_state_get_keymap)>("xkb_state_get_keymap"); 158 25 : xkb_keymap_key_for_each = handle.sym<decltype(xkb_keymap_key_for_each)>("xkb_keymap_key_for_each"); 159 25 : xkb_keymap_key_get_name = handle.sym<decltype(xkb_keymap_key_get_name)>("xkb_keymap_key_get_name"); 160 25 : xkb_keymap_mod_get_index = handle.sym<decltype(xkb_keymap_mod_get_index)>("xkb_keymap_mod_get_index"); 161 25 : xkb_keymap_key_repeats = handle.sym<decltype(xkb_keymap_key_repeats)>("xkb_keymap_key_repeats"); 162 25 : xkb_keysym_to_utf32 = handle.sym<decltype(xkb_keysym_to_utf32)>("xkb_keysym_to_utf32"); 163 25 : xkb_compose_table_new_from_locale = handle.sym<decltype(xkb_compose_table_new_from_locale)>("xkb_compose_table_new_from_locale"); 164 25 : xkb_compose_table_unref = handle.sym<decltype(xkb_compose_table_unref)>("xkb_compose_table_unref"); 165 25 : xkb_compose_state_new = handle.sym<decltype(xkb_compose_state_new)>("xkb_compose_state_new"); 166 25 : xkb_compose_state_feed = handle.sym<decltype(xkb_compose_state_feed)>("xkb_compose_state_feed"); 167 25 : xkb_compose_state_reset = handle.sym<decltype(xkb_compose_state_reset)>("xkb_compose_state_reset"); 168 25 : xkb_compose_state_get_status = handle.sym<decltype(xkb_compose_state_get_status)>("xkb_compose_state_get_status"); 169 25 : xkb_compose_state_get_one_sym = handle.sym<decltype(xkb_compose_state_get_one_sym)>("xkb_compose_state_get_one_sym"); 170 25 : xkb_compose_state_unref = handle.sym<decltype(xkb_compose_state_unref)>("xkb_compose_state_unref"); 171 : #endif 172 : 173 25 : if (this->xkb_context_new 174 25 : && this->xkb_context_ref 175 25 : && this->xkb_context_unref 176 25 : && this->xkb_keymap_unref 177 25 : && this->xkb_state_unref 178 25 : && this->xkb_keymap_new_from_string 179 25 : && this->xkb_state_new 180 25 : && this->xkb_state_update_mask 181 25 : && this->xkb_state_key_get_utf8 182 25 : && this->xkb_state_key_get_utf32 183 25 : && this->xkb_state_key_get_one_sym 184 25 : && this->xkb_state_mod_index_is_active 185 25 : && this->xkb_state_key_get_syms 186 25 : && this->xkb_state_get_keymap 187 25 : && this->xkb_keymap_key_for_each 188 25 : && this->xkb_keymap_key_get_name 189 25 : && this->xkb_keymap_mod_get_index 190 25 : && this->xkb_keymap_key_repeats 191 25 : && this->xkb_keysym_to_utf32 192 25 : && this->xkb_compose_table_new_from_locale 193 25 : && this->xkb_compose_table_unref 194 25 : && this->xkb_compose_state_new 195 25 : && this->xkb_compose_state_feed 196 25 : && this->xkb_compose_state_reset 197 25 : && this->xkb_compose_state_get_status 198 25 : && this->xkb_compose_state_get_one_sym 199 25 : && this->xkb_compose_state_unref) { 200 25 : openAux(); 201 25 : return true; 202 : } 203 0 : return false; 204 : } 205 : 206 25 : void XkbLibrary::openAux() { 207 : #if XL_LINK 208 : this->xkb_x11_setup_xkb_extension = &::xkb_x11_setup_xkb_extension; 209 : this->xkb_x11_get_core_keyboard_device_id = &::xkb_x11_get_core_keyboard_device_id; 210 : this->xkb_x11_keymap_new_from_device = &::xkb_x11_keymap_new_from_device; 211 : this->xkb_x11_state_new_from_device = &::xkb_x11_state_new_from_device; 212 : #else 213 25 : if (auto handle = Dso("libxkbcommon-x11.so")) { 214 25 : this->xkb_x11_setup_xkb_extension = 215 25 : handle.sym<decltype(this->xkb_x11_setup_xkb_extension)>("xkb_x11_setup_xkb_extension"); 216 25 : this->xkb_x11_get_core_keyboard_device_id = 217 25 : handle.sym<decltype(this->xkb_x11_get_core_keyboard_device_id)>("xkb_x11_get_core_keyboard_device_id"); 218 25 : this->xkb_x11_keymap_new_from_device = 219 25 : handle.sym<decltype(this->xkb_x11_keymap_new_from_device)>("xkb_x11_keymap_new_from_device"); 220 25 : this->xkb_x11_state_new_from_device = 221 25 : handle.sym<decltype(this->xkb_x11_state_new_from_device)>("xkb_x11_state_new_from_device"); 222 : 223 25 : if (this->xkb_x11_setup_xkb_extension 224 25 : && xkb_x11_get_core_keyboard_device_id 225 25 : && xkb_x11_keymap_new_from_device 226 25 : && xkb_x11_state_new_from_device) { 227 25 : _x11 = move(handle); 228 : } else { 229 0 : this->xkb_x11_setup_xkb_extension = nullptr; 230 0 : this->xkb_x11_get_core_keyboard_device_id = nullptr; 231 0 : this->xkb_x11_keymap_new_from_device = nullptr; 232 0 : this->xkb_x11_state_new_from_device = nullptr; 233 : } 234 25 : } 235 : #endif 236 25 : } 237 : 238 : }