1use gdk;
6use glib::object::Cast;
7use glib::object::IsA;
8use glib::signal::connect_raw;
9use glib::signal::SignalHandlerId;
10use glib::translate::*;
11use glib::GString;
12use glib::StaticType;
13use glib::Value;
14use glib_sys;
15use gobject_sys;
16use gtk_sys;
17use libc;
18use pango;
19use std::boxed::Box as Box_;
20use std::fmt;
21use std::mem;
22use std::mem::transmute;
23use std::ptr;
24use InputHints;
25use InputPurpose;
26
27glib_wrapper! {
28 pub struct IMContext(Object<gtk_sys::GtkIMContext, gtk_sys::GtkIMContextClass, IMContextClass>);
29
30 match fn {
31 get_type => || gtk_sys::gtk_im_context_get_type(),
32 }
33}
34
35pub const NONE_IM_CONTEXT: Option<&IMContext> = None;
36
37pub trait IMContextExt: 'static {
38 fn delete_surrounding(&self, offset: i32, n_chars: i32) -> bool;
39
40 fn filter_keypress(&self, event: &gdk::EventKey) -> bool;
41
42 fn focus_in(&self);
43
44 fn focus_out(&self);
45
46 fn get_preedit_string(&self) -> (GString, pango::AttrList, i32);
47
48 fn get_surrounding(&self) -> Option<(GString, i32)>;
49
50 fn reset(&self);
51
52 fn set_client_window<P: IsA<gdk::Window>>(&self, window: Option<&P>);
53
54 fn set_cursor_location(&self, area: &gdk::Rectangle);
55
56 fn set_surrounding(&self, text: &str, cursor_index: i32);
57
58 fn set_use_preedit(&self, use_preedit: bool);
59
60 fn get_property_input_hints(&self) -> InputHints;
61
62 fn set_property_input_hints(&self, input_hints: InputHints);
63
64 fn get_property_input_purpose(&self) -> InputPurpose;
65
66 fn set_property_input_purpose(&self, input_purpose: InputPurpose);
67
68 fn connect_commit<F: Fn(&Self, &str) + 'static>(&self, f: F) -> SignalHandlerId;
69
70 fn connect_delete_surrounding<F: Fn(&Self, i32, i32) -> bool + 'static>(
71 &self,
72 f: F,
73 ) -> SignalHandlerId;
74
75 fn connect_preedit_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
76
77 fn connect_preedit_end<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
78
79 fn connect_preedit_start<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
80
81 fn connect_retrieve_surrounding<F: Fn(&Self) -> bool + 'static>(&self, f: F)
82 -> SignalHandlerId;
83
84 fn connect_property_input_hints_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
85
86 fn connect_property_input_purpose_notify<F: Fn(&Self) + 'static>(
87 &self,
88 f: F,
89 ) -> SignalHandlerId;
90}
91
92impl<O: IsA<IMContext>> IMContextExt for O {
93 fn delete_surrounding(&self, offset: i32, n_chars: i32) -> bool {
94 unsafe {
95 from_glib(gtk_sys::gtk_im_context_delete_surrounding(
96 self.as_ref().to_glib_none().0,
97 offset,
98 n_chars,
99 ))
100 }
101 }
102
103 fn filter_keypress(&self, event: &gdk::EventKey) -> bool {
104 unsafe {
105 from_glib(gtk_sys::gtk_im_context_filter_keypress(
106 self.as_ref().to_glib_none().0,
107 mut_override(event.to_glib_none().0),
108 ))
109 }
110 }
111
112 fn focus_in(&self) {
113 unsafe {
114 gtk_sys::gtk_im_context_focus_in(self.as_ref().to_glib_none().0);
115 }
116 }
117
118 fn focus_out(&self) {
119 unsafe {
120 gtk_sys::gtk_im_context_focus_out(self.as_ref().to_glib_none().0);
121 }
122 }
123
124 fn get_preedit_string(&self) -> (GString, pango::AttrList, i32) {
125 unsafe {
126 let mut str = ptr::null_mut();
127 let mut attrs = ptr::null_mut();
128 let mut cursor_pos = mem::uninitialized();
129 gtk_sys::gtk_im_context_get_preedit_string(
130 self.as_ref().to_glib_none().0,
131 &mut str,
132 &mut attrs,
133 &mut cursor_pos,
134 );
135 (from_glib_full(str), from_glib_full(attrs), cursor_pos)
136 }
137 }
138
139 fn get_surrounding(&self) -> Option<(GString, i32)> {
140 unsafe {
141 let mut text = ptr::null_mut();
142 let mut cursor_index = mem::uninitialized();
143 let ret = from_glib(gtk_sys::gtk_im_context_get_surrounding(
144 self.as_ref().to_glib_none().0,
145 &mut text,
146 &mut cursor_index,
147 ));
148 if ret {
149 Some((from_glib_full(text), cursor_index))
150 } else {
151 None
152 }
153 }
154 }
155
156 fn reset(&self) {
157 unsafe {
158 gtk_sys::gtk_im_context_reset(self.as_ref().to_glib_none().0);
159 }
160 }
161
162 fn set_client_window<P: IsA<gdk::Window>>(&self, window: Option<&P>) {
163 unsafe {
164 gtk_sys::gtk_im_context_set_client_window(
165 self.as_ref().to_glib_none().0,
166 window.map(|p| p.as_ref()).to_glib_none().0,
167 );
168 }
169 }
170
171 fn set_cursor_location(&self, area: &gdk::Rectangle) {
172 unsafe {
173 gtk_sys::gtk_im_context_set_cursor_location(
174 self.as_ref().to_glib_none().0,
175 area.to_glib_none().0,
176 );
177 }
178 }
179
180 fn set_surrounding(&self, text: &str, cursor_index: i32) {
181 let len = text.len() as i32;
182 unsafe {
183 gtk_sys::gtk_im_context_set_surrounding(
184 self.as_ref().to_glib_none().0,
185 text.to_glib_none().0,
186 len,
187 cursor_index,
188 );
189 }
190 }
191
192 fn set_use_preedit(&self, use_preedit: bool) {
193 unsafe {
194 gtk_sys::gtk_im_context_set_use_preedit(
195 self.as_ref().to_glib_none().0,
196 use_preedit.to_glib(),
197 );
198 }
199 }
200
201 fn get_property_input_hints(&self) -> InputHints {
202 unsafe {
203 let mut value = Value::from_type(<InputHints as StaticType>::static_type());
204 gobject_sys::g_object_get_property(
205 self.to_glib_none().0 as *mut gobject_sys::GObject,
206 b"input-hints\0".as_ptr() as *const _,
207 value.to_glib_none_mut().0,
208 );
209 value.get().unwrap()
210 }
211 }
212
213 fn set_property_input_hints(&self, input_hints: InputHints) {
214 unsafe {
215 gobject_sys::g_object_set_property(
216 self.to_glib_none().0 as *mut gobject_sys::GObject,
217 b"input-hints\0".as_ptr() as *const _,
218 Value::from(&input_hints).to_glib_none().0,
219 );
220 }
221 }
222
223 fn get_property_input_purpose(&self) -> InputPurpose {
224 unsafe {
225 let mut value = Value::from_type(<InputPurpose as StaticType>::static_type());
226 gobject_sys::g_object_get_property(
227 self.to_glib_none().0 as *mut gobject_sys::GObject,
228 b"input-purpose\0".as_ptr() as *const _,
229 value.to_glib_none_mut().0,
230 );
231 value.get().unwrap()
232 }
233 }
234
235 fn set_property_input_purpose(&self, input_purpose: InputPurpose) {
236 unsafe {
237 gobject_sys::g_object_set_property(
238 self.to_glib_none().0 as *mut gobject_sys::GObject,
239 b"input-purpose\0".as_ptr() as *const _,
240 Value::from(&input_purpose).to_glib_none().0,
241 );
242 }
243 }
244
245 fn connect_commit<F: Fn(&Self, &str) + 'static>(&self, f: F) -> SignalHandlerId {
246 unsafe extern "C" fn commit_trampoline<P, F: Fn(&P, &str) + 'static>(
247 this: *mut gtk_sys::GtkIMContext,
248 str: *mut libc::c_char,
249 f: glib_sys::gpointer,
250 ) where
251 P: IsA<IMContext>,
252 {
253 let f: &F = &*(f as *const F);
254 f(
255 &IMContext::from_glib_borrow(this).unsafe_cast(),
256 &GString::from_glib_borrow(str),
257 )
258 }
259 unsafe {
260 let f: Box_<F> = Box_::new(f);
261 connect_raw(
262 self.as_ptr() as *mut _,
263 b"commit\0".as_ptr() as *const _,
264 Some(transmute(commit_trampoline::<Self, F> as usize)),
265 Box_::into_raw(f),
266 )
267 }
268 }
269
270 fn connect_delete_surrounding<F: Fn(&Self, i32, i32) -> bool + 'static>(
271 &self,
272 f: F,
273 ) -> SignalHandlerId {
274 unsafe extern "C" fn delete_surrounding_trampoline<
275 P,
276 F: Fn(&P, i32, i32) -> bool + 'static,
277 >(
278 this: *mut gtk_sys::GtkIMContext,
279 offset: libc::c_int,
280 n_chars: libc::c_int,
281 f: glib_sys::gpointer,
282 ) -> glib_sys::gboolean
283 where
284 P: IsA<IMContext>,
285 {
286 let f: &F = &*(f as *const F);
287 f(
288 &IMContext::from_glib_borrow(this).unsafe_cast(),
289 offset,
290 n_chars,
291 )
292 .to_glib()
293 }
294 unsafe {
295 let f: Box_<F> = Box_::new(f);
296 connect_raw(
297 self.as_ptr() as *mut _,
298 b"delete-surrounding\0".as_ptr() as *const _,
299 Some(transmute(delete_surrounding_trampoline::<Self, F> as usize)),
300 Box_::into_raw(f),
301 )
302 }
303 }
304
305 fn connect_preedit_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
306 unsafe extern "C" fn preedit_changed_trampoline<P, F: Fn(&P) + 'static>(
307 this: *mut gtk_sys::GtkIMContext,
308 f: glib_sys::gpointer,
309 ) where
310 P: IsA<IMContext>,
311 {
312 let f: &F = &*(f as *const F);
313 f(&IMContext::from_glib_borrow(this).unsafe_cast())
314 }
315 unsafe {
316 let f: Box_<F> = Box_::new(f);
317 connect_raw(
318 self.as_ptr() as *mut _,
319 b"preedit-changed\0".as_ptr() as *const _,
320 Some(transmute(preedit_changed_trampoline::<Self, F> as usize)),
321 Box_::into_raw(f),
322 )
323 }
324 }
325
326 fn connect_preedit_end<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
327 unsafe extern "C" fn preedit_end_trampoline<P, F: Fn(&P) + 'static>(
328 this: *mut gtk_sys::GtkIMContext,
329 f: glib_sys::gpointer,
330 ) where
331 P: IsA<IMContext>,
332 {
333 let f: &F = &*(f as *const F);
334 f(&IMContext::from_glib_borrow(this).unsafe_cast())
335 }
336 unsafe {
337 let f: Box_<F> = Box_::new(f);
338 connect_raw(
339 self.as_ptr() as *mut _,
340 b"preedit-end\0".as_ptr() as *const _,
341 Some(transmute(preedit_end_trampoline::<Self, F> as usize)),
342 Box_::into_raw(f),
343 )
344 }
345 }
346
347 fn connect_preedit_start<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
348 unsafe extern "C" fn preedit_start_trampoline<P, F: Fn(&P) + 'static>(
349 this: *mut gtk_sys::GtkIMContext,
350 f: glib_sys::gpointer,
351 ) where
352 P: IsA<IMContext>,
353 {
354 let f: &F = &*(f as *const F);
355 f(&IMContext::from_glib_borrow(this).unsafe_cast())
356 }
357 unsafe {
358 let f: Box_<F> = Box_::new(f);
359 connect_raw(
360 self.as_ptr() as *mut _,
361 b"preedit-start\0".as_ptr() as *const _,
362 Some(transmute(preedit_start_trampoline::<Self, F> as usize)),
363 Box_::into_raw(f),
364 )
365 }
366 }
367
368 fn connect_retrieve_surrounding<F: Fn(&Self) -> bool + 'static>(
369 &self,
370 f: F,
371 ) -> SignalHandlerId {
372 unsafe extern "C" fn retrieve_surrounding_trampoline<P, F: Fn(&P) -> bool + 'static>(
373 this: *mut gtk_sys::GtkIMContext,
374 f: glib_sys::gpointer,
375 ) -> glib_sys::gboolean
376 where
377 P: IsA<IMContext>,
378 {
379 let f: &F = &*(f as *const F);
380 f(&IMContext::from_glib_borrow(this).unsafe_cast()).to_glib()
381 }
382 unsafe {
383 let f: Box_<F> = Box_::new(f);
384 connect_raw(
385 self.as_ptr() as *mut _,
386 b"retrieve-surrounding\0".as_ptr() as *const _,
387 Some(transmute(
388 retrieve_surrounding_trampoline::<Self, F> as usize,
389 )),
390 Box_::into_raw(f),
391 )
392 }
393 }
394
395 fn connect_property_input_hints_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
396 unsafe extern "C" fn notify_input_hints_trampoline<P, F: Fn(&P) + 'static>(
397 this: *mut gtk_sys::GtkIMContext,
398 _param_spec: glib_sys::gpointer,
399 f: glib_sys::gpointer,
400 ) where
401 P: IsA<IMContext>,
402 {
403 let f: &F = &*(f as *const F);
404 f(&IMContext::from_glib_borrow(this).unsafe_cast())
405 }
406 unsafe {
407 let f: Box_<F> = Box_::new(f);
408 connect_raw(
409 self.as_ptr() as *mut _,
410 b"notify::input-hints\0".as_ptr() as *const _,
411 Some(transmute(notify_input_hints_trampoline::<Self, F> as usize)),
412 Box_::into_raw(f),
413 )
414 }
415 }
416
417 fn connect_property_input_purpose_notify<F: Fn(&Self) + 'static>(
418 &self,
419 f: F,
420 ) -> SignalHandlerId {
421 unsafe extern "C" fn notify_input_purpose_trampoline<P, F: Fn(&P) + 'static>(
422 this: *mut gtk_sys::GtkIMContext,
423 _param_spec: glib_sys::gpointer,
424 f: glib_sys::gpointer,
425 ) where
426 P: IsA<IMContext>,
427 {
428 let f: &F = &*(f as *const F);
429 f(&IMContext::from_glib_borrow(this).unsafe_cast())
430 }
431 unsafe {
432 let f: Box_<F> = Box_::new(f);
433 connect_raw(
434 self.as_ptr() as *mut _,
435 b"notify::input-purpose\0".as_ptr() as *const _,
436 Some(transmute(
437 notify_input_purpose_trampoline::<Self, F> as usize,
438 )),
439 Box_::into_raw(f),
440 )
441 }
442 }
443}
444
445impl fmt::Display for IMContext {
446 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
447 write!(f, "IMContext")
448 }
449}