Skip to content

Commit 3704759

Browse files
milkey-mousevberger
authored andcommitted
Allow linking to libxkbcommon at compile time
This commit introduces a "dlopen" feature that is enabled by default that preserves the existing behavior of not linking to/requiring libxkbcommon except for trying to dlopen it at runtime. If the feature is disabled, cargo will link to an existing libxkbcommon.so.
1 parent 3026a83 commit 3704759

File tree

3 files changed

+109
-61
lines changed

3 files changed

+109
-61
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ readme = "README.md"
1414
[dependencies]
1515
bitflags = "1.0"
1616
nix = "0.19"
17-
dlib = "0.4"
17+
dlib = "0.5"
1818
lazy_static = "1.0"
1919
memmap2 = "0.2.0"
2020
andrew = { version = "0.3.0", optional = true }
@@ -25,7 +25,8 @@ wayland-cursor = "0.28"
2525
calloop = { version = "0.6.1", optional = true }
2626

2727
[features]
28-
default = ["frames", "calloop"]
28+
default = ["frames", "calloop", "dlopen"]
29+
dlopen = ["wayland-client/dlopen"]
2930
frames = ["andrew"]
3031

3132
[dev-dependencies]

src/seat/keyboard/ffi.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ bitflags::bitflags!(
174174
}
175175
);
176176

177-
dlopen_external_library!(XkbCommon,
177+
external_library!(XkbCommon, "xkbcommon",
178178
functions:
179179
fn xkb_keysym_get_name(xkb_keysym_t, *mut c_char, usize) -> c_int,
180180
fn xkb_keysym_from_name(*const c_char, xkb_keysym_flags) -> xkb_keysym_t,
@@ -253,8 +253,9 @@ functions:
253253
fn xkb_compose_state_get_one_sym(*mut xkb_compose_state) -> xkb_keysym_t,
254254
);
255255

256+
#[cfg(feature = "dlopen")]
256257
lazy_static::lazy_static!(
257-
pub static ref XKBCOMMON_OPTION: Option<XkbCommon> = {
258+
pub static ref XKBCOMMON_OPTION: Option<XkbCommon> = unsafe {
258259
XkbCommon::open("libxkbcommon.so.0")
259260
.or_else(|_| XkbCommon::open("libxkbcommon.so"))
260261
.ok()

src/seat/keyboard/state.rs

Lines changed: 103 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
use memmap2::MmapOptions;
22
use std::{env, ffi::CString, fs::File, os::raw::c_char, os::unix::ffi::OsStringExt, ptr};
33

4-
use super::ffi::{self, xkb_state_component, XKBCOMMON_HANDLE as XKBH};
4+
#[cfg(feature = "dlopen")]
5+
use super::ffi::XKBCOMMON_HANDLE as XKBH;
6+
#[cfg(not(feature = "dlopen"))]
7+
use super::ffi::*;
8+
use super::ffi::{self, xkb_state_component};
59
use super::Error;
610

711
pub(crate) struct KbState {
@@ -65,45 +69,57 @@ impl ModifiersState {
6569

6670
fn update_with(&mut self, state: *mut ffi::xkb_state) {
6771
self.ctrl = unsafe {
68-
(XKBH.xkb_state_mod_name_is_active)(
72+
ffi_dispatch!(
73+
XKBH,
74+
xkb_state_mod_name_is_active,
6975
state,
7076
ffi::XKB_MOD_NAME_CTRL.as_ptr() as *const c_char,
71-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
77+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
7278
) > 0
7379
};
7480
self.alt = unsafe {
75-
(XKBH.xkb_state_mod_name_is_active)(
81+
ffi_dispatch!(
82+
XKBH,
83+
xkb_state_mod_name_is_active,
7684
state,
7785
ffi::XKB_MOD_NAME_ALT.as_ptr() as *const c_char,
78-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
86+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
7987
) > 0
8088
};
8189
self.shift = unsafe {
82-
(XKBH.xkb_state_mod_name_is_active)(
90+
ffi_dispatch!(
91+
XKBH,
92+
xkb_state_mod_name_is_active,
8393
state,
8494
ffi::XKB_MOD_NAME_SHIFT.as_ptr() as *const c_char,
85-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
95+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
8696
) > 0
8797
};
8898
self.caps_lock = unsafe {
89-
(XKBH.xkb_state_mod_name_is_active)(
99+
ffi_dispatch!(
100+
XKBH,
101+
xkb_state_mod_name_is_active,
90102
state,
91103
ffi::XKB_MOD_NAME_CAPS.as_ptr() as *const c_char,
92-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
104+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
93105
) > 0
94106
};
95107
self.logo = unsafe {
96-
(XKBH.xkb_state_mod_name_is_active)(
108+
ffi_dispatch!(
109+
XKBH,
110+
xkb_state_mod_name_is_active,
97111
state,
98112
ffi::XKB_MOD_NAME_LOGO.as_ptr() as *const c_char,
99-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
113+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
100114
) > 0
101115
};
102116
self.num_lock = unsafe {
103-
(XKBH.xkb_state_mod_name_is_active)(
117+
ffi_dispatch!(
118+
XKBH,
119+
xkb_state_mod_name_is_active,
104120
state,
105121
ffi::XKB_MOD_NAME_NUM.as_ptr() as *const c_char,
106-
xkb_state_component::XKB_STATE_MODS_EFFECTIVE,
122+
xkb_state_component::XKB_STATE_MODS_EFFECTIVE
107123
) > 0
108124
};
109125
}
@@ -121,14 +137,16 @@ impl KbState {
121137
return;
122138
}
123139
let mask = unsafe {
124-
(XKBH.xkb_state_update_mask)(
140+
ffi_dispatch!(
141+
XKBH,
142+
xkb_state_update_mask,
125143
self.xkb_state,
126144
mods_depressed,
127145
mods_latched,
128146
mods_locked,
129147
0,
130148
0,
131-
group,
149+
group
132150
)
133151
};
134152
if mask.contains(xkb_state_component::XKB_STATE_MODS_EFFECTIVE) {
@@ -141,27 +159,36 @@ impl KbState {
141159
if !self.ready() {
142160
return 0;
143161
}
144-
unsafe { (XKBH.xkb_state_key_get_one_sym)(self.xkb_state, keycode + 8) }
162+
unsafe { ffi_dispatch!(XKBH, xkb_state_key_get_one_sym, self.xkb_state, keycode + 8) }
145163
}
146164

147165
pub(crate) fn get_utf8_raw(&mut self, keycode: u32) -> Option<String> {
148166
if !self.ready() {
149167
return None;
150168
}
151169
let size = unsafe {
152-
(XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode + 8, ptr::null_mut(), 0)
170+
ffi_dispatch!(
171+
XKBH,
172+
xkb_state_key_get_utf8,
173+
self.xkb_state,
174+
keycode + 8,
175+
ptr::null_mut(),
176+
0
177+
)
153178
} + 1;
154179
if size <= 1 {
155180
return None;
156181
};
157182
let mut buffer = Vec::with_capacity(size as usize);
158183
unsafe {
159184
buffer.set_len(size as usize);
160-
(XKBH.xkb_state_key_get_utf8)(
185+
ffi_dispatch!(
186+
XKBH,
187+
xkb_state_key_get_utf8,
161188
self.xkb_state,
162189
keycode + 8,
163190
buffer.as_mut_ptr() as *mut _,
164-
size as usize,
191+
size as usize
165192
);
166193
};
167194
// remove the final `\0`
@@ -174,33 +201,41 @@ impl KbState {
174201
if !self.ready() || self.xkb_compose_state.is_null() {
175202
return None;
176203
}
177-
Some(unsafe { (XKBH.xkb_compose_state_feed)(self.xkb_compose_state, keysym) })
204+
Some(unsafe { ffi_dispatch!(XKBH, xkb_compose_state_feed, self.xkb_compose_state, keysym) })
178205
}
179206

180207
pub(crate) fn compose_status(&mut self) -> Option<ffi::xkb_compose_status> {
181208
if !self.ready() || self.xkb_compose_state.is_null() {
182209
return None;
183210
}
184-
Some(unsafe { (XKBH.xkb_compose_state_get_status)(self.xkb_compose_state) })
211+
Some(unsafe { ffi_dispatch!(XKBH, xkb_compose_state_get_status, self.xkb_compose_state) })
185212
}
186213

187214
pub(crate) fn compose_get_utf8(&mut self) -> Option<String> {
188215
if !self.ready() || self.xkb_compose_state.is_null() {
189216
return None;
190217
}
191218
let size = unsafe {
192-
(XKBH.xkb_compose_state_get_utf8)(self.xkb_compose_state, ptr::null_mut(), 0)
219+
ffi_dispatch!(
220+
XKBH,
221+
xkb_compose_state_get_utf8,
222+
self.xkb_compose_state,
223+
ptr::null_mut(),
224+
0
225+
)
193226
} + 1;
194227
if size <= 1 {
195228
return None;
196229
};
197230
let mut buffer = Vec::with_capacity(size as usize);
198231
unsafe {
199232
buffer.set_len(size as usize);
200-
(XKBH.xkb_compose_state_get_utf8)(
233+
ffi_dispatch!(
234+
XKBH,
235+
xkb_compose_state_get_utf8,
201236
self.xkb_compose_state,
202237
buffer.as_mut_ptr() as *mut _,
203-
size as usize,
238+
size as usize
204239
);
205240
};
206241
// remove the final `\0`
@@ -210,18 +245,21 @@ impl KbState {
210245
}
211246

212247
pub(crate) fn new() -> Result<KbState, Error> {
213-
let xkbh = match ffi::XKBCOMMON_OPTION.as_ref() {
214-
Some(h) => h,
215-
None => return Err(Error::XKBNotFound),
248+
#[cfg(feature = "dlopen")]
249+
{
250+
if ffi::XKBCOMMON_OPTION.as_ref().is_none() {
251+
return Err(Error::XKBNotFound);
252+
}
253+
}
254+
let context = unsafe {
255+
ffi_dispatch!(XKBH, xkb_context_new, ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS)
216256
};
217-
let xkb_context =
218-
unsafe { (xkbh.xkb_context_new)(ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS) };
219-
if xkb_context.is_null() {
257+
if context.is_null() {
220258
return Err(Error::XKBNotFound);
221259
}
222260

223261
let mut me = KbState {
224-
xkb_context,
262+
xkb_context: context,
225263
xkb_keymap: ptr::null_mut(),
226264
xkb_state: ptr::null_mut(),
227265
xkb_compose_table: ptr::null_mut(),
@@ -276,84 +314,92 @@ impl KbState {
276314
.unwrap_or_else(|| "C".into());
277315
let locale = CString::new(locale.into_vec()).unwrap();
278316

279-
let compose_table = (XKBH.xkb_compose_table_new_from_locale)(
317+
let compose_table = ffi_dispatch!(
318+
XKBH,
319+
xkb_compose_table_new_from_locale,
280320
self.xkb_context,
281321
locale.as_ptr(),
282-
ffi::xkb_compose_compile_flags::XKB_COMPOSE_COMPILE_NO_FLAGS,
322+
ffi::xkb_compose_compile_flags::XKB_COMPOSE_COMPILE_NO_FLAGS
283323
);
284324

285325
if compose_table.is_null() {
286326
// init of compose table failed, continue without compose
287327
return;
288328
}
289329

290-
let compose_state = (XKBH.xkb_compose_state_new)(
330+
let compose_state = ffi_dispatch!(
331+
XKBH,
332+
xkb_compose_state_new,
291333
compose_table,
292-
ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS,
334+
ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS
293335
);
294336

295337
if compose_state.is_null() {
296338
// init of compose state failed, continue without compose
297-
(XKBH.xkb_compose_table_unref)(compose_table);
339+
ffi_dispatch!(XKBH, xkb_compose_table_unref, compose_table);
298340
return;
299341
}
300342

301343
self.xkb_compose_table = compose_table;
302344
self.xkb_compose_state = compose_state;
303345
}
304346

305-
pub(crate) unsafe fn post_init(&mut self, xkb_keymap: *mut ffi::xkb_keymap) {
306-
let xkb_state = (XKBH.xkb_state_new)(xkb_keymap);
307-
self.xkb_keymap = xkb_keymap;
308-
self.xkb_state = xkb_state;
309-
self.mods_state.update_with(xkb_state);
347+
pub(crate) unsafe fn post_init(&mut self, keymap: *mut ffi::xkb_keymap) {
348+
let state = ffi_dispatch!(XKBH, xkb_state_new, keymap);
349+
self.xkb_keymap = keymap;
350+
self.xkb_state = state;
351+
self.mods_state.update_with(state);
310352
}
311353

312354
pub(crate) unsafe fn de_init(&mut self) {
313-
(XKBH.xkb_state_unref)(self.xkb_state);
355+
ffi_dispatch!(XKBH, xkb_state_unref, self.xkb_state);
314356
self.xkb_state = ptr::null_mut();
315-
(XKBH.xkb_keymap_unref)(self.xkb_keymap);
357+
ffi_dispatch!(XKBH, xkb_keymap_unref, self.xkb_keymap);
316358
self.xkb_keymap = ptr::null_mut();
317359
}
318360

319361
pub(crate) unsafe fn init_with_fd(&mut self, fd: File, size: usize) {
320362
let map = MmapOptions::new().len(size).map(&fd).unwrap();
321363

322-
let xkb_keymap = (XKBH.xkb_keymap_new_from_string)(
364+
let keymap = ffi_dispatch!(
365+
XKBH,
366+
xkb_keymap_new_from_string,
323367
self.xkb_context,
324368
map.as_ptr() as *const _,
325369
ffi::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
326-
ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
370+
ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS
327371
);
328372

329-
if xkb_keymap.is_null() {
373+
if keymap.is_null() {
330374
panic!("Received invalid keymap from compositor.");
331375
}
332376

333-
self.post_init(xkb_keymap);
377+
self.post_init(keymap);
334378
}
335379

336380
pub(crate) unsafe fn init_with_rmlvo(
337381
&mut self,
338382
names: ffi::xkb_rule_names,
339383
) -> Result<(), Error> {
340-
let xkb_keymap = (XKBH.xkb_keymap_new_from_names)(
384+
let keymap = ffi_dispatch!(
385+
XKBH,
386+
xkb_keymap_new_from_names,
341387
self.xkb_context,
342388
&names,
343-
ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
389+
ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS
344390
);
345391

346-
if xkb_keymap.is_null() {
392+
if keymap.is_null() {
347393
return Err(Error::BadNames);
348394
}
349395

350-
self.post_init(xkb_keymap);
396+
self.post_init(keymap);
351397

352398
Ok(())
353399
}
354400

355401
pub(crate) unsafe fn key_repeats(&mut self, xkb_keycode_t: ffi::xkb_keycode_t) -> bool {
356-
(XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, xkb_keycode_t) == 1
402+
ffi_dispatch!(XKBH, xkb_keymap_key_repeats, self.xkb_keymap, xkb_keycode_t) == 1
357403
}
358404

359405
#[inline]
@@ -375,11 +421,11 @@ impl KbState {
375421
impl Drop for KbState {
376422
fn drop(&mut self) {
377423
unsafe {
378-
(XKBH.xkb_compose_state_unref)(self.xkb_compose_state);
379-
(XKBH.xkb_compose_table_unref)(self.xkb_compose_table);
380-
(XKBH.xkb_state_unref)(self.xkb_state);
381-
(XKBH.xkb_keymap_unref)(self.xkb_keymap);
382-
(XKBH.xkb_context_unref)(self.xkb_context);
424+
ffi_dispatch!(XKBH, xkb_compose_state_unref, self.xkb_compose_state);
425+
ffi_dispatch!(XKBH, xkb_compose_table_unref, self.xkb_compose_table);
426+
ffi_dispatch!(XKBH, xkb_state_unref, self.xkb_state);
427+
ffi_dispatch!(XKBH, xkb_keymap_unref, self.xkb_keymap);
428+
ffi_dispatch!(XKBH, xkb_context_unref, self.xkb_context);
383429
}
384430
}
385431
}

0 commit comments

Comments
 (0)