Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for xcb 1.1 #2

Merged
merged 2 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xcb-imdkit"
version = "0.1.2"
version = "0.2.0"
edition = "2018"
license = "LGPL-2.1-only"
description = "Wrapper around xcb-imdkit, providing an IME client for the XIM protocol using XCB"
Expand All @@ -19,7 +19,7 @@ name = "example"
path = "examples/example.rs"

[dependencies]
xcb = "0.9.0"
xcb = {version="1.1", features=["xkb"], git="https://github.com/wez/rust-xcb", branch="ffi"}
lazy_static = "1.4.0"
bitflags = "1.3"

Expand Down
99 changes: 37 additions & 62 deletions examples/example.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
use std::sync::Arc;
use xcb::x::{Cw, EventMask, Window};
use xcb::Event;
use xcb_imdkit::{ImeClient, InputStyle};

fn create_window(connection: Arc<xcb::Connection>, screen: &xcb::Screen) -> u32 {
let w = connection.generate_id();
let mask = xcb::EVENT_MASK_KEY_PRESS
| xcb::EVENT_MASK_KEY_RELEASE
| xcb::EVENT_MASK_FOCUS_CHANGE
| xcb::EVENT_MASK_VISIBILITY_CHANGE
| xcb::EVENT_MASK_STRUCTURE_NOTIFY;
let values = [
(xcb::CW_BACK_PIXEL, screen.white_pixel()),
(xcb::CW_EVENT_MASK, mask),
];
xcb::create_window(
&connection,
xcb::COPY_FROM_PARENT as u8,
w,
screen.root(),
0,
0,
400,
400,
10,
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
screen.root_visual(),
&values,
);
xcb::map_window(&connection, w);
unsafe {
xcb::ffi::xcb_flush(connection.get_raw_conn());
}
w
fn create_window(connection: Arc<xcb::Connection>, screen: &xcb::x::Screen) -> Window {
let wid = connection.generate_id();
let mask = EventMask::KEY_PRESS
| EventMask::KEY_RELEASE
| EventMask::FOCUS_CHANGE
| EventMask::VISIBILITY_CHANGE
| EventMask::STRUCTURE_NOTIFY;
connection.send_request(&xcb::x::CreateWindow {
depth: xcb::x::COPY_FROM_PARENT as u8,
wid,
parent: screen.root(),
x: 0,
y: 0,
width: 400,
height: 400,
border_width: 10,
class: xcb::x::WindowClass::InputOutput,
visual: screen.root_visual(),
value_list: &[Cw::BackPixel(screen.white_pixel()), Cw::EventMask(mask)],
});
connection.send_request(&xcb::x::MapWindow { window: wid });
connection.flush().unwrap();
wid
}

fn main() {
Expand All @@ -49,23 +44,9 @@ fn main() {
InputStyle::PREEDIT_CALLBACKS,
None,
);
ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
ime.set_commit_string_cb(|win, input| println!("Win {:?}, got: {}", win, input));
ime.set_forward_event_cb(|win, e| {
dbg!(
win,
e.response_type(),
e.detail(),
e.time(),
e.root(),
e.event(),
e.child(),
e.root_x(),
e.root_y(),
e.event_x(),
e.event_y(),
e.state(),
e.same_screen(),
);
eprintln!("win={:?} {:?}", win, e);
});
ime.set_preedit_draw_cb(|win, info| {
dbg!(win, info);
Expand All @@ -79,22 +60,16 @@ fn main() {
let mut focus_win = wins[0];
let mut n = 0;
loop {
let event = connection.wait_for_event();
if event.is_none() {
break;
}
let event = event.unwrap();
dbg!(event.response_type());

let event_type = event.response_type() & !0x80;
if xcb::FOCUS_IN == event_type {
let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
focus_win = event.event();
ime.update_pos(focus_win, 0, 0);
}

if xcb::CONFIGURE_NOTIFY == event_type {
ime.update_pos(focus_win, 0, 0);
let event = dbg!(connection.wait_for_event().unwrap());
match &event {
Event::X(xcb::x::Event::FocusIn(event)) => {
focus_win = event.event();
ime.update_pos(focus_win, 0, 0);
}
Event::X(xcb::x::Event::ConfigureNotify(_)) => {
ime.update_pos(focus_win, 0, 0);
}
_ => {}
}

println!(">>>>{}>>>>", n);
Expand Down
1 change: 0 additions & 1 deletion src/clib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,3 @@ impl Default for xcb_xim_im_callback {
}
}
}

67 changes: 44 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ extern crate lazy_static;
use std::os::raw::{c_char, c_void};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use xcb::x::Window;
use xcb::{Raw, Xid, XidNew};

use bitflags::bitflags;

Expand Down Expand Up @@ -121,7 +123,7 @@ extern "C" fn commit_string_callback(
) {
let input = unsafe { xim_encoding_to_utf8(im, input, length as usize) };
let ime = unsafe { ime_from_user_data(user_data) };
let win = ime.pos_req.win;
let win = unsafe { Window::new(ime.pos_req.win) };
ime.callbacks.commit_string.as_mut().map(|f| f(win, &input));
}

Expand All @@ -135,16 +137,30 @@ extern "C" fn update_pos_callback(_im: *mut xcb_xim_t, ic: xcb_xic_t, user_data:
}
}

const XCB_KEY_PRESS: u8 = 2;
const XCB_KEY_RELEASE: u8 = 3;

extern "C" fn forward_event_callback(
_im: *mut xcb_xim_t,
_ic: xcb_xic_t,
event: *mut xcb_key_press_event_t,
user_data: *mut c_void,
) {
let ptr = event as *const xcb::ffi::xcb_key_press_event_t;
let event = xcb::KeyPressEvent { ptr: ptr as _ };
let pressed = unsafe { ((*event).response_type & 0x7f) == XCB_KEY_PRESS };
let ptr = event as *const xcb::ffi::xcb_generic_event_t;
let event = unsafe {
if pressed {
xcb::Event::X(xcb::x::Event::KeyPress(xcb::x::KeyPressEvent::from_raw(
ptr as _,
)))
} else {
xcb::Event::X(xcb::x::Event::KeyRelease(
xcb::x::KeyReleaseEvent::from_raw(ptr as _),
))
}
};
let ime = unsafe { ime_from_user_data(user_data) };
let win = ime.pos_req.win;
let win = unsafe { Window::new(ime.pos_req.win) };
ime.callbacks.forward_event.as_mut().map(|f| f(win, &event));

// xcb::KeyPressEvent has a Drop impl that will free `event`, but since we don't own it, we
Expand All @@ -154,7 +170,7 @@ extern "C" fn forward_event_callback(

extern "C" fn preedit_start_callback(_im: *mut xcb_xim_t, _ic: xcb_xic_t, user_data: *mut c_void) {
let ime = unsafe { ime_from_user_data(user_data) };
let win = ime.pos_req.win;
let win = unsafe { Window::new(ime.pos_req.win) };
ime.callbacks.preedit_start.as_mut().map(|f| f(win));
}

Expand All @@ -167,7 +183,7 @@ extern "C" fn preedit_draw_callback(
let frame = unsafe { &*frame };
let preedit_info = PreeditInfo { inner: frame, im };
let ime = unsafe { ime_from_user_data(user_data) };
let win = ime.pos_req.win;
let win = unsafe { Window::new(ime.pos_req.win) };
ime.callbacks
.preedit_draw
.as_mut()
Expand All @@ -176,7 +192,7 @@ extern "C" fn preedit_draw_callback(

extern "C" fn preedit_done_callback(_im: *mut xcb_xim_t, _ic: xcb_xic_t, user_data: *mut c_void) {
let ime = unsafe { ime_from_user_data(user_data) };
let win = ime.pos_req.win;
let win = unsafe { Window::new(ime.pos_req.win) };
ime.callbacks.preedit_done.as_mut().map(|f| f(win));
}

Expand All @@ -195,10 +211,10 @@ bitflags! {
}
}

type StringCB = dyn for<'a> FnMut(u32, &'a str);
type KeyPressCB = dyn for<'a> FnMut(u32, &'a xcb::KeyPressEvent);
type PreeditDrawCB = dyn for<'a> FnMut(u32, PreeditInfo<'a>);
type NotifyCB = dyn FnMut(u32);
type StringCB = dyn for<'a> FnMut(Window, &'a str);
type KeyPressCB = dyn for<'a> FnMut(Window, &'a xcb::Event);
type PreeditDrawCB = dyn for<'a> FnMut(Window, PreeditInfo<'a>);
type NotifyCB = dyn FnMut(Window);

#[derive(Default)]
struct Callbacks {
Expand Down Expand Up @@ -403,14 +419,15 @@ impl ImeClient {
/// [`set_forward_event_cb`]: ImeClient::set_forward_event_cb
/// [`set_commit_string_cb`]: ImeClient::set_commit_string_cb
/// [`set_preedit_draw_cb`]: ImeClient::set_preedit_draw_cb
pub fn process_event(&mut self, event: &xcb::GenericEvent) -> bool {
if !unsafe { xcb_xim_filter_event(self.im, event.ptr as _) } {
let mask = event.response_type() & !0x80;
if (mask == xcb::ffi::XCB_KEY_PRESS) || (mask == xcb::ffi::XCB_KEY_RELEASE) {
pub fn process_event(&mut self, event: &xcb::Event) -> bool {
let raw = event.as_raw();
if !unsafe { xcb_xim_filter_event(self.im, raw as _) } {
let mask = unsafe { (*raw).response_type & !0x80 };
if (mask == XCB_KEY_PRESS) || (mask == XCB_KEY_RELEASE) {
match self.ic {
Some(ic) => {
unsafe {
xcb_xim_forward_event(self.im, ic, event.ptr as _);
xcb_xim_forward_event(self.im, ic, raw as _);
}
return true;
}
Expand All @@ -431,8 +448,12 @@ impl ImeClient {
/// Return `true` if an update for the IME window position has been sent to the IME, `false` if
/// the update has been queued. If there is still an update request queued and this method is
/// called, the previously queued request is discarded in favor of the new one.
pub fn update_pos(&mut self, win: u32, x: i16, y: i16) -> bool {
self.pos_req = ImePos { win, x, y };
pub fn update_pos(&mut self, win: Window, x: i16, y: i16) -> bool {
self.pos_req = ImePos {
win: win.resource_id(),
x,
y,
};
match self.ic {
Some(ic) => {
if self.is_processing_pos_update {
Expand Down Expand Up @@ -504,7 +525,7 @@ impl ImeClient {
/// [`update_pos`]: ImeClient::update_pos
pub fn set_commit_string_cb<F>(&mut self, f: F)
where
F: for<'a> FnMut(u32, &'a str) + 'static,
F: for<'a> FnMut(Window, &'a str) + 'static,
{
self.callbacks.commit_string = Some(Box::new(f));
}
Expand All @@ -520,7 +541,7 @@ impl ImeClient {
/// [`update_pos`]: ImeClient::update_pos
pub fn set_forward_event_cb<F>(&mut self, f: F)
where
F: for<'a> FnMut(u32, &'a xcb::KeyPressEvent) + 'static,
F: for<'a> FnMut(Window, &'a xcb::Event) + 'static,
{
self.callbacks.forward_event = Some(Box::new(f));
}
Expand All @@ -533,7 +554,7 @@ impl ImeClient {
/// [`update_pos`]: ImeClient::update_pos
pub fn set_preedit_start_cb<F>(&mut self, f: F)
where
F: FnMut(u32) + 'static,
F: FnMut(Window) + 'static,
{
self.callbacks.preedit_start = Some(Box::new(f));
}
Expand All @@ -547,7 +568,7 @@ impl ImeClient {
/// [`update_pos`]: ImeClient::update_pos
pub fn set_preedit_draw_cb<F>(&mut self, f: F)
where
F: for<'a> FnMut(u32, PreeditInfo<'a>) + 'static,
F: for<'a> FnMut(Window, PreeditInfo<'a>) + 'static,
{
self.callbacks.preedit_draw = Some(Box::new(f));
}
Expand All @@ -560,7 +581,7 @@ impl ImeClient {
/// [`update_pos`]: ImeClient::update_pos
pub fn set_preedit_done_cb<F>(&mut self, f: F)
where
F: FnMut(u32) + 'static,
F: FnMut(Window) + 'static,
{
self.callbacks.preedit_done = Some(Box::new(f));
}
Expand Down