ImeClient

Struct ImeClient 

Source
pub struct ImeClient { /* private fields */ }
Expand description

Input Method Editor (IME) client.

ImeClient represents one instance of an Input Method Editor client. It provides callbacks for event handling as well as control over the position of the IME window. There should be only one IME client per application and it is advised to create at most one instance.

Implementations§

Source§

impl ImeClient

Source

pub fn set_logger<F>(f: F)
where F: for<'a> FnMut(&'a str) + Send + 'static,

Set the global logger for xcb-imdkit.

The callback will receive debug messages from the C library this crate is wrapping.

Examples found in repository?
examples/example.rs (line 45)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn new( conn: Arc<Connection>, screen_id: i32, input_style: InputStyle, im_name: Option<&str>, ) -> Pin<Box<Self>>

Create a new ImeClient.

The first two arguments correspond to the result of xcb::Connection::connect with the connection wrapped into an Arc to ensure that the Ime does not outlive its connection. For documentation on input_style refer to InputStyle. im_name can be used to specify a custom IME server to connect to using the syntax @im=custom_server.

Examples found in repository?
examples/example.rs (lines 46-51)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub unsafe fn unsafe_new( conn: &Connection, screen_id: i32, input_style: InputStyle, im_name: Option<&str>, ) -> Pin<Box<Self>>

Create a new ImeClient.

This is the same as new, except that the xcb::Connection is not wrapped into an Arc.

§Safety

The caller is responsible to ensure that the ImeClient does not outlive the connection.

Source

pub fn process_event(&mut self, event: &GenericEvent) -> bool

Let the IME client process XCB’s events.

Return true if the IME client is handling the event and false if the event is ignored by the IME client and has to be handled separately.

This method should be called on any event from the event queue and not just keypress/keyrelease events as it handles other events as well.

Typically you will want to let the IME client handle all keypress/keyrelease events in your main loop. The IME client will then forward all key events that were not used for input composition to the callback set by set_forward_event_cb. Often those events include all keyrelease events as well as the events for ESC, Enter or key combinations such as CTRL+C. To obtain the text currently typed into the IME and the final string consult set_preedit_draw_cb and set_commit_string_cb.

Examples found in repository?
examples/example.rs (line 101)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn update_pos(&mut self, win: u32, x: i16, y: i16) -> bool

Set the position at which to place the IME window.

Set the position of the IME window relative to the window specified by win. Coordinates increase from the top left corner of the window.

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.

Examples found in repository?
examples/example.rs (line 93)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn set_commit_string_cb<F>(&mut self, f: F)
where F: for<'a> FnMut(u32, &'a str) + 'static,

Set callback to be called once input composition is done.

The window (set by update_pos) as well as the completed input are passed as arguments.

Examples found in repository?
examples/example.rs (line 52)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn set_forward_event_cb<F>(&mut self, f: F)
where F: for<'a> FnMut(u32, &'a KeyPressEvent) + 'static,

Often those events include all keyrelease events as well as the events for ESC, Enter or key combinations such as CTRL+C. Please note that xcb::KeyPressEvent == xcb::KeyReleaseEvent (see xcb::ffi::xcb_key_release_event_t) and keyrelease events are also supplied.

Examples found in repository?
examples/example.rs (lines 53-69)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn set_preedit_start_cb<F>(&mut self, f: F)
where F: FnMut(u32) + 'static,

Callback called once the IME has been opened.

The current window (set by update_pos) is supplied as argument. Calls callback only if InputStyle::PREEDIT_CALLBACKS is set.

Source

pub fn set_preedit_draw_cb<F>(&mut self, f: F)
where F: for<'a> FnMut(u32, PreeditInfo<'a>) + 'static,

Callback called whenever the text whitin the IME has changed.

The current window (set by update_pos) is supplied as argument as well as PreeditInfo, which contains, among other things, the current text of the IME. Calls callback only if InputStyle::PREEDIT_CALLBACKS is set.

Examples found in repository?
examples/example.rs (lines 70-72)
36fn main() {
37    let (connection, screen_default_nbr) = xcb::Connection::connect(None).unwrap();
38    let connection = Arc::new(connection);
39    let screen = connection
40        .get_setup()
41        .roots()
42        .nth(screen_default_nbr as usize)
43        .unwrap();
44
45    ImeClient::set_logger(|msg| println!("Log: {}", msg));
46    let mut ime = ImeClient::new(
47        connection.clone(),
48        screen_default_nbr,
49        InputStyle::PREEDIT_CALLBACKS,
50        None,
51    );
52    ime.set_commit_string_cb(|win, input| println!("Win {}, got: {}", win, input));
53    ime.set_forward_event_cb(|win, e| {
54        dbg!(
55            win,
56            e.response_type(),
57            e.detail(),
58            e.time(),
59            e.root(),
60            e.event(),
61            e.child(),
62            e.root_x(),
63            e.root_y(),
64            e.event_x(),
65            e.event_y(),
66            e.state(),
67            e.same_screen(),
68        );
69    });
70    ime.set_preedit_draw_cb(|win, info| {
71        dbg!(win, info);
72    });
73
74    let mut wins = vec![];
75    for _ in 0..3 {
76        wins.push(create_window(connection.clone(), &screen));
77    }
78
79    let mut focus_win = wins[0];
80    let mut n = 0;
81    loop {
82        let event = connection.wait_for_event();
83        if event.is_none() {
84            break;
85        }
86        let event = event.unwrap();
87        dbg!(event.response_type());
88
89        let event_type = event.response_type() & !0x80;
90        if xcb::FOCUS_IN == event_type {
91            let event: &xcb::FocusInEvent = unsafe { xcb::cast_event(&event) };
92            focus_win = event.event();
93            ime.update_pos(focus_win, 0, 0);
94        }
95
96        if xcb::CONFIGURE_NOTIFY == event_type {
97            ime.update_pos(focus_win, 0, 0);
98        }
99
100        println!(">>>>{}>>>>", n);
101        ime.process_event(&event);
102        println!("<<<<{}<<<<", n);
103        n += 1;
104    }
105}
Source

pub fn set_preedit_done_cb<F>(&mut self, f: F)
where F: FnMut(u32) + 'static,

Callback called once the IME has been closed.

The current window (set by update_pos) is supplied as argument. Calls callback only if InputStyle::PREEDIT_CALLBACKS is set.

Trait Implementations§

Source§

impl Drop for ImeClient

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.