diff --git a/.builds/build.yml b/.builds/build.yml index 17a1ad96..cf866ed5 100644 --- a/.builds/build.yml +++ b/.builds/build.yml @@ -8,5 +8,4 @@ tasks: rustup toolchain install stable - build: | cd jay - export RUSTC_BOOTSTRAP=1 cargo build diff --git a/.builds/test.yml b/.builds/test.yml index 4f15cbe1..446d1f25 100644 --- a/.builds/test.yml +++ b/.builds/test.yml @@ -12,7 +12,6 @@ tasks: sudo chmod o+rw /dev/dri/card* - build: | cd jay - export RUSTC_BOOTSTRAP=1 cargo build --features it - test: | cd jay diff --git a/.builds/unit-tests.yml b/.builds/unit-tests.yml index e9a98dc4..140ecddb 100644 --- a/.builds/unit-tests.yml +++ b/.builds/unit-tests.yml @@ -8,5 +8,4 @@ tasks: rustup toolchain install stable - test: | cd jay - export RUSTC_BOOTSTRAP=1 cargo test diff --git a/Cargo.lock b/Cargo.lock index c7af9f99..e81a6f12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,12 +196,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" [[package]] name = "cfg-if" @@ -501,6 +498,7 @@ dependencies = [ "bincode", "bstr", "byteorder", + "cc", "chrono", "clap", "clap_complete", diff --git a/Cargo.toml b/Cargo.toml index 3e9b10b7..0f21b60f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ repc = "0.1.1" anyhow = "1.0.79" bstr = { version = "1.9.0", default-features = false, features = ["std"] } shaderc = "0.8.3" +cc = "1.0.86" #[profile.dev.build-override] #opt-level = 3 diff --git a/README.md b/README.md index 87a1eb33..63f5958d 100644 --- a/README.md +++ b/README.md @@ -88,13 +88,13 @@ only the latest stable version is supported. You can now build Jay using this command: ```sh -RUSTC_BOOTSTRAP=1 cargo build --release +cargo build --release ``` The resulting binary will be located at `./target/release/jay`. Alternatively, cargo can also install the binary for you: ```sh -RUSTC_BOOTSTRAP=1 cargo install --path . +cargo install --path . ``` This will install the binary at `$HOME/.cargo/bin/jay`. If you have not already done so, you can add `$HOME/.cargo/bin` to your path. diff --git a/build/build.rs b/build/build.rs index 85580ae8..8c86deb9 100644 --- a/build/build.rs +++ b/build/build.rs @@ -24,6 +24,7 @@ use std::{ mod egl; mod enums; +mod logging; mod tokens; mod vulkan; mod wire; @@ -49,6 +50,7 @@ fn main() -> anyhow::Result<()> { enums::main()?; egl::main()?; vulkan::main()?; + logging::main()?; println!("cargo:rerun-if-changed=build/build.rs"); Ok(()) diff --git a/build/logging.rs b/build/logging.rs new file mode 100644 index 00000000..4b228d1e --- /dev/null +++ b/build/logging.rs @@ -0,0 +1,5 @@ +pub fn main() -> anyhow::Result<()> { + println!("cargo:rerun-if-changed=src/bridge.c"); + cc::Build::new().file("src/bridge.c").compile("bridge"); + Ok(()) +} diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index a4223e62..96e9244d 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -61,7 +61,7 @@ impl Drop for Client { } thread_local! { - pub(crate) static CLIENT: std::cell::Cell<*const Client> = const { std::cell::Cell::new(ptr::null()) }; + pub(crate) static CLIENT: Cell<*const Client> = const { Cell::new(ptr::null()) }; } unsafe fn with_client T>(data: *const u8, f: F) -> T { diff --git a/src/bridge.c b/src/bridge.c new file mode 100644 index 00000000..15390afc --- /dev/null +++ b/src/bridge.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE + +#include +#include +#include + +static char *fmt(const char *format, va_list args) { + char *line; + int ret = vasprintf(&line, format, args); + if (ret < 0) { + return 0; + } else { + return line; + } +} + +void jay_libinput_log_handler( + void *libinput, + int priority, + const char *line +); + +void jay_libinput_log_handler_bridge( + void *libinput, + int priority, + const char *format, + va_list args +) { + char *line = fmt(format, args); + jay_libinput_log_handler(libinput, priority, line); + free(line); +} + +void jay_xkbcommon_log_handler( + void *ctx, + int xkb_log_level, + const char *line +); + +void jay_xkbcommon_log_handler_bridge( + void *ctx, + int xkb_log_level, + const char *format, + va_list args +) { + char *line = fmt(format, args); + jay_xkbcommon_log_handler(ctx, xkb_log_level, line); + free(line); +} diff --git a/src/clientmem.rs b/src/clientmem.rs index 993b0eed..685b67ae 100644 --- a/src/clientmem.rs +++ b/src/clientmem.rs @@ -88,12 +88,12 @@ impl ClientMemOffset { } let mref = MemRef { mem: &*self.mem, - outer: MEM, + outer: MEM.get(), }; - MEM = &mref; + MEM.set(&mref); compiler_fence(Ordering::SeqCst); let res = f(&*self.data); - MEM = mref.outer; + MEM.set(mref.outer); compiler_fence(Ordering::SeqCst); match self.mem.failed.get() { true => Err(ClientMemError::Sigbus), @@ -116,8 +116,9 @@ struct MemRef { outer: *const MemRef, } -#[thread_local] -static mut MEM: *const MemRef = ptr::null(); +thread_local! { + static MEM: Cell<*const MemRef> = const { Cell::new(ptr::null()) }; +} unsafe fn kill() -> ! { c::signal(c::SIGBUS, c::SIG_DFL); @@ -127,7 +128,7 @@ unsafe fn kill() -> ! { unsafe extern "C" fn sigbus(sig: i32, info: &c::siginfo_t, _ucontext: *mut c::c_void) { assert_eq!(sig, c::SIGBUS); - let mut memr_ptr = MEM; + let mut memr_ptr = MEM.get(); while !memr_ptr.is_null() { let memr = &*memr_ptr; let mem = &*memr.mem; diff --git a/src/gfx_apis/gl/egl/context.rs b/src/gfx_apis/gl/egl/context.rs index 094308a2..c72ea95f 100644 --- a/src/gfx_apis/gl/egl/context.rs +++ b/src/gfx_apis/gl/egl/context.rs @@ -15,7 +15,7 @@ use { }, }, ahash::AHashMap, - std::rc::Rc, + std::{cell::Cell, rc::Rc}, }; #[derive(Debug, Clone)] @@ -36,8 +36,9 @@ impl Drop for EglContext { } } -#[thread_local] -static mut CURRENT: EGLContext = EGLContext::none(); +thread_local! { + static CURRENT: Cell = const { Cell::new(EGLContext::none()) }; +} impl EglContext { pub fn reset_status(&self) -> Option { @@ -63,7 +64,7 @@ impl EglContext { f: F, ) -> Result { unsafe { - if CURRENT == self.ctx { + if CURRENT.get() == self.ctx { return f(); } self.with_current_slow(f) @@ -84,15 +85,15 @@ impl EglContext { { return Err(RenderError::MakeCurrent); } - let prev = CURRENT; - CURRENT = self.ctx; + let prev = CURRENT.get(); + CURRENT.set(self.ctx); let res = f(); if (self.dpy.egl.eglMakeCurrent)(self.dpy.dpy, EGLSurface::none(), EGLSurface::none(), prev) == EGL_FALSE { panic!("Could not restore EGLContext"); } - CURRENT = prev; + CURRENT.set(prev); res } } diff --git a/src/gfx_apis/vulkan/instance.rs b/src/gfx_apis/vulkan/instance.rs index 56985968..e64a7453 100644 --- a/src/gfx_apis/vulkan/instance.rs +++ b/src/gfx_apis/vulkan/instance.rs @@ -146,7 +146,8 @@ impl Drop for VulkanInstance { const REQUIRED_INSTANCE_EXTENSIONS: &[&CStr] = &[ExtDebugUtilsFn::name()]; -const VALIDATION_LAYER: &CStr = c"VK_LAYER_KHRONOS_validation"; +const VALIDATION_LAYER: &CStr = + unsafe { CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0") }; pub type Extensions = AHashMap; diff --git a/src/it/test_config.rs b/src/it/test_config.rs index 0a3428c5..e98dc8a7 100644 --- a/src/it/test_config.rs +++ b/src/it/test_config.rs @@ -27,26 +27,25 @@ pub static TEST_CONFIG_ENTRY: ConfigEntry = ConfigEntry { handle_msg, }; -#[thread_local] -static mut CONFIG: *const TestConfig = ptr::null(); +thread_local! { + static CONFIG: Cell<*const TestConfig> = const { Cell::new(ptr::null()) }; +} pub fn with_test_config(f: F) -> T where F: FnOnce(Rc) -> T, { - unsafe { - let tc = Rc::new(TestConfig { - srv: Cell::new(None), - responses: Default::default(), - invoked_shortcuts: Default::default(), - graphics_initialized: Cell::new(false), - }); - let old = CONFIG; - CONFIG = tc.deref(); - let res = f(tc.clone()); - CONFIG = old; - res - } + let tc = Rc::new(TestConfig { + srv: Cell::new(None), + responses: Default::default(), + invoked_shortcuts: Default::default(), + graphics_initialized: Cell::new(false), + }); + let old = CONFIG.get(); + CONFIG.set(tc.deref()); + let res = f(tc.clone()); + CONFIG.set(old); + res } unsafe extern "C" fn init( @@ -56,7 +55,7 @@ unsafe extern "C" fn init( _msg: *const u8, _size: usize, ) -> *const u8 { - let tc = CONFIG; + let tc = CONFIG.get(); assert!(tc.is_not_null()); Rc::increment_strong_count(tc); { diff --git a/src/it/test_logger.rs b/src/it/test_logger.rs index d07ef06e..d8bde2c5 100644 --- a/src/it/test_logger.rs +++ b/src/it/test_logger.rs @@ -13,8 +13,9 @@ use { static LEVEL: AtomicUsize = AtomicUsize::new(Level::Info as usize); -#[thread_local] -static FILE: CloneCell>> = CloneCell::new(None); +thread_local! { + static FILE: CloneCell>> = CloneCell::new(None); +} pub fn install() { log::set_logger(&Logger).unwrap(); @@ -27,11 +28,11 @@ pub fn set_level(level: Level) { } pub fn set_file(file: Rc) { - FILE.set(Some(file)); + FILE.with(|f| f.set(Some(file))); } pub fn unset_file() { - FILE.set(None); + FILE.with(|f| f.set(None)); } struct Logger; @@ -65,7 +66,7 @@ impl Log for Logger { record.args(), ) }; - let mut fd = match FILE.get() { + let mut fd = match FILE.with(|f| f.get()) { Some(f) => f.borrow(), _ => Fd::new(2), }; diff --git a/src/leaks.rs b/src/leaks.rs index 97072151..10ae0af5 100644 --- a/src/leaks.rs +++ b/src/leaks.rs @@ -52,27 +52,27 @@ mod leaks { std::{ alloc::{GlobalAlloc, Layout}, any, + cell::Cell, marker::PhantomData, mem, ptr, }, uapi::c, }; - #[thread_local] - static mut MAP: *mut AHashMap = ptr::null_mut(); - - #[thread_local] - static mut ID: u64 = 0; + thread_local! { + static MAP: Cell<*mut AHashMap> = const { Cell::new(ptr::null_mut()) }; + static ID: Cell = const { Cell::new(0) }; + } pub fn init() { unsafe { if INITIALIZED { return; } - MAP = Box::into_raw(Box::new(AHashMap::new())); - ALLOCATIONS = Box::into_raw(Box::new(AHashMap::new())); - IN_ALLOCATOR = 0; - INITIALIZED = true; + MAP.set(Box::into_raw(Box::new(AHashMap::new()))); + ALLOCATIONS.set(Box::into_raw(Box::new(AHashMap::new()))); + IN_ALLOCATOR.set(0); + INITIALIZED.set(true); } } @@ -151,7 +151,7 @@ mod leaks { pub fn log_leaked() { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut map: AHashMap> = AHashMap::new(); for (id, obj) in MAP.deref_mut().drain() { map.entry(obj.client).or_default().push((id, obj)); @@ -176,7 +176,7 @@ mod leaks { } } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); } } // @@ -210,8 +210,8 @@ mod leaks { fn default() -> Self { Self { id: unsafe { - let id = ID; - ID += 1; + let id = ID.get(); + ID.set(id + 1); id }, _phantom: Default::default(), @@ -227,7 +227,7 @@ mod leaks { tv_nsec: 0, }; uapi::clock_gettime(c::CLOCK_REALTIME, &mut time).unwrap(); - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); MAP.deref_mut().insert( self.id, Tracked { @@ -237,7 +237,7 @@ mod leaks { time: (time.tv_sec as i64, time.tv_nsec as u32), }, ); - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); } } } @@ -262,20 +262,17 @@ mod leaks { pub backtrace: Backtrace, } - #[thread_local] - static mut ALLOCATIONS: *mut AHashMap<*mut u8, Allocation> = ptr::null_mut(); - - #[thread_local] - static mut IN_ALLOCATOR: u32 = 1; - - #[thread_local] - static mut INITIALIZED: bool = false; + thread_local! { + static ALLOCATIONS: Cell<*mut AHashMap<*mut u8, Allocation>> = const { Cell::new(ptr::null_mut()) }; + static IN_ALLOCATOR: Cell = const { Cell::new(1) }; + static INITIALIZED: Cell = const { Cell::new(false) }; + } unsafe impl GlobalAlloc for TracingAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { let res = c::calloc(layout.size(), 1) as *mut u8; - if IN_ALLOCATOR == 0 { - IN_ALLOCATOR = 1; + if IN_ALLOCATOR.get() == 0 { + IN_ALLOCATOR.set(1); ALLOCATIONS.deref_mut().insert( res, Allocation { @@ -301,7 +298,7 @@ mod leaks { fn find_allocations_pointing_to(addr: *mut u8) -> Vec<(Allocation, usize)> { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut res = vec![]; for allocation in ALLOCATIONS.deref().values() { let num = allocation.len / mem::size_of::(); @@ -313,14 +310,14 @@ mod leaks { } } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); res } } fn find_allocation_containing(addr: usize) -> Option { unsafe { - IN_ALLOCATOR += 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() + 1); let mut res = None; for allocation in ALLOCATIONS.deref().values() { let aaddr = allocation.addr as usize; @@ -329,7 +326,7 @@ mod leaks { break; } } - IN_ALLOCATOR -= 1; + IN_ALLOCATOR.set(IN_ALLOCATOR.get() - 1); res } } diff --git a/src/libinput.rs b/src/libinput.rs index fc637456..1723d3db 100644 --- a/src/libinput.rs +++ b/src/libinput.rs @@ -22,16 +22,11 @@ use { }, }, udev::UdevError, - utils::{ - errorfmt::ErrorFmt, oserror::OsError, ptr_ext::PtrExt, trim::AsciiTrim, - vasprintf::vasprintf_, - }, + utils::{errorfmt::ErrorFmt, oserror::OsError, ptr_ext::PtrExt, trim::AsciiTrim}, }, bstr::ByteSlice, - std::{ - ffi::{CStr, VaList}, - rc::Rc, - }, + isnt::std_1::primitive::IsntConstPtrExt, + std::{ffi::CStr, rc::Rc}, thiserror::Error, uapi::{c, Errno, IntoUstr, OwnedFd}, }; @@ -91,6 +86,10 @@ pub struct LibInput { li: *mut libinput, } +extern "C" { + fn jay_libinput_log_handler_bridge(); +} + impl LibInput { pub fn new(adapter: Rc) -> Result { let mut ud = Box::new(UserData { adapter }); @@ -101,7 +100,7 @@ impl LibInput { return Err(LibInputError::New); } unsafe { - libinput_log_set_handler(li, log_handler); + libinput_log_set_handler(li, jay_libinput_log_handler_bridge); let priority = if log::log_enabled!(log::Level::Debug) { LIBINPUT_LOG_PRIORITY_DEBUG } else if log::log_enabled!(log::Level::Info) { @@ -167,19 +166,14 @@ impl Drop for LibInput { } } -unsafe extern "C" fn log_handler( +#[no_mangle] +unsafe extern "C" fn jay_libinput_log_handler( _libinput: *mut libinput, priority: libinput_log_priority, - format: *const c::c_char, - args: VaList, + line: *const c::c_char, ) { - let str = match vasprintf_(format, args) { - Some(s) => s, - _ => { - log::error!("Could not format log message"); - return; - } - }; + assert!(line.is_not_null()); + let str = CStr::from_ptr(line); let priority = match LogPriority(priority as _) { LIBINPUT_LOG_PRIORITY_DEBUG => log::Level::Debug, LIBINPUT_LOG_PRIORITY_INFO => log::Level::Info, diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index 00f109b8..acd9dc7b 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -1,22 +1,22 @@ -use {std::ffi::VaList, uapi::c}; +use uapi::c; include!(concat!(env!("OUT_DIR"), "/libinput_tys.rs")); -pub type libinput_log_handler = unsafe extern "C" fn( - libinput: *mut libinput, - priority: libinput_log_priority, - format: *const c::c_char, - args: VaList, -); +pub type libinput_log_handler = unsafe extern "C" fn(); + +#[repr(transparent)] +pub struct libinput(u8); +#[repr(transparent)] +pub struct libinput_device(u8); +#[repr(transparent)] +pub struct libinput_event(u8); +#[repr(transparent)] +pub struct libinput_event_keyboard(u8); +#[repr(transparent)] +pub struct libinput_event_pointer(u8); #[link(name = "input")] extern "C" { - pub type libinput; - pub type libinput_device; - pub type libinput_event; - pub type libinput_event_keyboard; - pub type libinput_event_pointer; - pub fn libinput_log_set_handler(libinput: *mut libinput, log_handler: libinput_log_handler); pub fn libinput_log_set_priority(libinput: *mut libinput, priority: libinput_log_priority); pub fn libinput_path_create_context( diff --git a/src/logger.rs b/src/logger.rs index 32b4666c..274604a2 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -4,9 +4,11 @@ use { bstr::{BStr, BString, ByteSlice}, log::{Level, Log, Metadata, Record}, std::{ + cell::Cell, fs::DirBuilder, io::Write, os::unix::{ffi::OsStringExt, fs::DirBuilderExt}, + ptr, sync::{ atomic::{AtomicU32, Ordering::Relaxed}, Arc, @@ -16,8 +18,9 @@ use { uapi::{c, format_ustr, Errno, Fd, OwnedFd}, }; -#[thread_local] -static mut BUFFER: Vec = Vec::new(); +thread_local! { + static BUFFER: Cell<*mut Vec> = const { Cell::new(ptr::null_mut()) }; +} pub struct Logger { level: AtomicU32, @@ -141,7 +144,12 @@ impl Log for LogWrapper { if record.level() as u32 > self.logger.level.load(Relaxed) { return; } - let buffer = unsafe { &mut BUFFER }; + let mut buffer = BUFFER.get(); + if buffer.is_null() { + buffer = Box::into_raw(Box::default()); + BUFFER.set(buffer); + } + let buffer = unsafe { &mut *buffer }; buffer.clear(); let now = SystemTime::now(); let _ = if let Some(mp) = record.module_path() { diff --git a/src/main.rs b/src/main.rs index e2133382..e22cbc93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,3 @@ -#![feature( - c_variadic, // https://github.com/rust-lang/rust/issues/44930 - thread_local, // https://github.com/rust-lang/rust/issues/29594 - extern_types, // https://github.com/rust-lang/rust/issues/43467 - c_str_literals, // https://github.com/rust-lang/rust/issues/105723 -)] #![allow( clippy::len_zero, clippy::needless_lifetimes, diff --git a/src/pango.rs b/src/pango.rs index 087fb10e..afce8b40 100644 --- a/src/pango.rs +++ b/src/pango.rs @@ -14,11 +14,13 @@ pub mod consts; include!(concat!(env!("OUT_DIR"), "/pango_tys.rs")); +#[repr(transparent)] +struct cairo_surface_t(u8); +#[repr(transparent)] +struct cairo_t(u8); + #[link(name = "cairo")] extern "C" { - type cairo_surface_t; - type cairo_t; - fn cairo_image_surface_create( format: cairo_format_t, width: c::c_int, @@ -41,26 +43,30 @@ extern "C" { fn cairo_move_to(cr: *mut cairo_t, x: f64, y: f64); } +#[repr(transparent)] +struct PangoContext_(u8); + #[link(name = "pangocairo-1.0")] extern "C" { - type PangoContext_; - fn pango_cairo_create_context(cr: *mut cairo_t) -> *mut PangoContext_; fn pango_cairo_show_layout(cr: *mut cairo_t, layout: *mut PangoLayout_); } +#[repr(transparent)] +struct GObject(u8); + #[link(name = "gobject-2.0")] extern "C" { - type GObject; - fn g_object_unref(object: *mut GObject); } +#[repr(transparent)] +struct PangoFontDescription_(u8); +#[repr(transparent)] +struct PangoLayout_(u8); + #[link(name = "pango-1.0")] extern "C" { - type PangoFontDescription_; - type PangoLayout_; - fn pango_font_description_from_string(str: *const c::c_char) -> *mut PangoFontDescription_; fn pango_font_description_free(desc: *mut PangoFontDescription_); fn pango_font_description_get_size(desc: *mut PangoFontDescription_) -> c::c_int; diff --git a/src/rect/region.rs b/src/rect/region.rs index 98c46257..f004c1af 100644 --- a/src/rect/region.rs +++ b/src/rect/region.rs @@ -4,18 +4,17 @@ use { region::{extents, rects_to_bands, subtract, union}, RectRaw, }, - once_cell::unsync::Lazy, smallvec::SmallVec, std::{mem, ops::Deref, rc::Rc}, }; -#[thread_local] -static EMPTY: Lazy> = Lazy::new(|| { - Rc::new(Region { - rects: Default::default(), - extents: Default::default(), - }) -}); +thread_local! { + static EMPTY: Rc = + Rc::new(Region { + rects: Default::default(), + extents: Default::default(), + }); +} impl Region { pub fn new(rect: Rect) -> Rc { @@ -28,7 +27,7 @@ impl Region { } pub fn empty() -> Rc { - EMPTY.clone() + EMPTY.with(|e| e.clone()) } pub fn from_rects(rects: &[Rect]) -> Rc { diff --git a/src/udev.rs b/src/udev.rs index 6f534a1c..0ee165ab 100644 --- a/src/udev.rs +++ b/src/udev.rs @@ -1,3 +1,5 @@ +#![allow(non_camel_case_types)] + use { crate::utils::oserror::OsError, std::{ffi::CStr, marker::PhantomData, ptr, rc::Rc}, @@ -5,14 +7,19 @@ use { uapi::{c, ustr, Errno, IntoUstr, Ustr}, }; +#[repr(transparent)] +struct udev(u8); +#[repr(transparent)] +struct udev_monitor(u8); +#[repr(transparent)] +struct udev_enumerate(u8); +#[repr(transparent)] +struct udev_list_entry(u8); +#[repr(transparent)] +struct udev_device(u8); + #[link(name = "udev")] extern "C" { - type udev; - type udev_monitor; - type udev_enumerate; - type udev_list_entry; - type udev_device; - fn udev_new() -> *mut udev; fn udev_unref(udev: *mut udev) -> *mut udev; diff --git a/src/utils.rs b/src/utils.rs index c345a3a3..13a84df6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,7 +39,6 @@ pub mod toplevel_identifier; pub mod tri; pub mod trim; pub mod unlink_on_drop; -pub mod vasprintf; pub mod vec_ext; pub mod vecstorage; pub mod windows; diff --git a/src/utils/vasprintf.rs b/src/utils/vasprintf.rs deleted file mode 100644 index e7a0dac1..00000000 --- a/src/utils/vasprintf.rs +++ /dev/null @@ -1,42 +0,0 @@ -use { - std::{ - ffi::{CStr, VaList}, - ops::Deref, - ptr, - }, - uapi::c, -}; - -extern "C" { - fn vasprintf(strp: *mut *mut c::c_char, fmt: *const c::c_char, ap: VaList) -> c::c_int; -} - -pub struct OwnedCStr { - val: &'static CStr, -} - -impl Deref for OwnedCStr { - type Target = CStr; - - fn deref(&self) -> &Self::Target { - self.val - } -} - -impl Drop for OwnedCStr { - fn drop(&mut self) { - unsafe { - c::free(self.val.as_ptr() as _); - } - } -} - -pub unsafe fn vasprintf_(fmt: *const c::c_char, ap: VaList) -> Option { - let mut res = ptr::null_mut(); - if vasprintf(&mut res, fmt, ap) == -1 { - return None; - } - Some(OwnedCStr { - val: CStr::from_ptr(res), - }) -} diff --git a/src/xkbcommon.rs b/src/xkbcommon.rs index 9088ee5a..0fba7212 100644 --- a/src/xkbcommon.rs +++ b/src/xkbcommon.rs @@ -7,13 +7,8 @@ include!(concat!(env!("OUT_DIR"), "/xkbcommon_tys.rs")); pub use consts::*; use { bstr::{BStr, ByteSlice}, - std::{ - ffi::{CStr, VaList}, - io::Write, - ops::Deref, - ptr, - rc::Rc, - }, + isnt::std_1::primitive::IsntConstPtrExt, + std::{ffi::CStr, io::Write, ops::Deref, ptr, rc::Rc}, }; use { @@ -69,15 +64,7 @@ extern "C" { fn xkb_context_new(flags: xkb_context_flags) -> *mut xkb_context; fn xkb_context_unref(context: *mut xkb_context); fn xkb_context_set_log_verbosity(context: *mut xkb_context, verbosity: c::c_int); - fn xkb_context_set_log_fn( - context: *mut xkb_context, - log_fn: unsafe extern "C" fn( - context: *mut xkb_context, - level: xkb_log_level, - format: *const c::c_char, - args: VaList, - ), - ); + fn xkb_context_set_log_fn(context: *mut xkb_context, log_fn: unsafe extern "C" fn()); fn xkb_keymap_new_from_buffer( context: *mut xkb_context, buffer: *const u8, @@ -116,6 +103,10 @@ pub struct XkbContext { context: *mut xkb_context, } +extern "C" { + fn jay_xkbcommon_log_handler_bridge(); +} + impl XkbContext { pub fn new() -> Result { let res = unsafe { xkb_context_new(XKB_CONTEXT_NO_FLAGS.raw() as _) }; @@ -124,7 +115,7 @@ impl XkbContext { } unsafe { xkb_context_set_log_verbosity(res, 10); - xkb_context_set_log_fn(res, xkbcommon_logger); + xkb_context_set_log_fn(res, jay_xkbcommon_log_handler_bridge); } Ok(Self { context: res }) } @@ -303,22 +294,14 @@ impl Drop for XkbState { } } -unsafe extern "C" fn xkbcommon_logger( +#[no_mangle] +unsafe extern "C" fn jay_xkbcommon_log_handler( _ctx: *mut xkb_context, level: xkb_log_level, - format: *const c::c_char, - args: VaList, + line: *const c::c_char, ) { - extern "C" { - fn vasprintf(buf: *mut *mut c::c_char, fmt: *const c::c_char, args: VaList) -> c::c_int; - } - let mut buf = ptr::null_mut(); - let res = vasprintf(&mut buf, format, args); - if res < 0 { - log::error!("Could not vasprintf"); - return; - } - let buf = std::slice::from_raw_parts(buf as *const u8, res as usize); + assert!(line.is_not_null()); + let buf = CStr::from_ptr(line); let level = match XkbLogLevel(level) { XKB_LOG_LEVEL_CRITICAL | XKB_LOG_LEVEL_ERROR => log::Level::Error, XKB_LOG_LEVEL_WARNING => log::Level::Warn, @@ -326,5 +309,5 @@ unsafe extern "C" fn xkbcommon_logger( XKB_LOG_LEVEL_DEBUG => log::Level::Debug, _ => log::Level::Error, }; - log::log!(level, "xkbcommon: {}", buf.trim_end().as_bstr()); + log::log!(level, "xkbcommon: {}", buf.to_bytes().trim_end().as_bstr()); }