@@ -7,14 +7,18 @@ use crate::{
77 clipboard:: LayerShellClipboard ,
88 conversion,
99 error:: Error ,
10+ ime_preedit:: Preedit ,
1011 settings:: VirtualKeyboardSettings ,
1112} ;
1213
1314use super :: { Appearance , DefaultStyle } ;
1415use iced_graphics:: { Compositor , compositor} ;
1516use state:: State ;
1617
17- use iced_core:: { Event as IcedCoreEvent , Size , time:: Instant , window as IcedCoreWindow } ;
18+ use iced_core:: {
19+ Event as IcedCoreEvent , InputMethod , Size , input_method, time:: Instant ,
20+ window as IcedCoreWindow ,
21+ } ;
1822
1923use iced_runtime:: { Action , Debug , Program , UserInterface , task:: Task , user_interface} ;
2024
@@ -333,6 +337,25 @@ where
333337 LayerShellAction :: RedrawWindow ( index) => {
334338 ev. append_return_data ( ReturnData :: RedrawIndexRequest ( index) ) ;
335339 }
340+ LayerShellAction :: Ime ( ime) => match ime {
341+ iced_core:: InputMethod :: Disabled => {
342+ ev. set_ime_allowed ( false ) ;
343+ }
344+ iced_core:: InputMethod :: Enabled {
345+ position, purpose, ..
346+ } => {
347+ ev. set_ime_allowed ( true ) ;
348+ ev. set_ime_purpose ( conversion:: ime_purpose ( purpose) ) ;
349+ ev. set_ime_cursor_area (
350+ layershellev:: dpi:: LogicalPosition :: new ( position. x , position. y ) ,
351+ layershellev:: dpi:: LogicalSize {
352+ width : 10 ,
353+ height : 10 ,
354+ } ,
355+ ev. main_window ( ) . id ( ) ,
356+ ) ;
357+ }
358+ } ,
336359 _ => { }
337360 }
338361 }
@@ -341,6 +364,94 @@ where
341364 Ok ( ( ) )
342365}
343366
367+ struct IMDrawer < A >
368+ where
369+ A : Application ,
370+ A :: Theme : iced_core:: theme:: Base ,
371+ {
372+ preedit : Option < Preedit < A :: Renderer > > ,
373+ ime_state : Option < ( iced_core:: Point , input_method:: Purpose ) > ,
374+ }
375+
376+ impl < A > IMDrawer < A >
377+ where
378+ A : Application ,
379+ A :: Theme : iced_core:: theme:: Base ,
380+ {
381+ fn new ( ) -> Self {
382+ Self {
383+ preedit : None ,
384+ ime_state : None ,
385+ }
386+ }
387+ pub fn request_input_method (
388+ & mut self ,
389+ background_color : iced_core:: Color ,
390+ input_method : InputMethod ,
391+ renderer : & A :: Renderer ,
392+ ) {
393+ match input_method {
394+ InputMethod :: Disabled => {
395+ self . disable_ime ( ) ;
396+ }
397+ InputMethod :: Enabled {
398+ position,
399+ purpose,
400+ preedit,
401+ } => {
402+ self . enable_ime ( position, purpose) ;
403+
404+ if let Some ( preedit) = preedit {
405+ if preedit. content . is_empty ( ) {
406+ self . preedit = None ;
407+ } else {
408+ let mut overlay = self . preedit . take ( ) . unwrap_or_else ( Preedit :: new) ;
409+
410+ overlay. update ( position, & preedit, background_color, renderer) ;
411+
412+ self . preedit = Some ( overlay) ;
413+ }
414+ } else {
415+ self . preedit = None ;
416+ }
417+ }
418+ }
419+ }
420+
421+ pub fn draw_preedit (
422+ & mut self ,
423+ renderer : & mut A :: Renderer ,
424+ text_color : iced_core:: Color ,
425+ background_color : iced_core:: Color ,
426+ logical_size : iced_core:: Size ,
427+ ) {
428+ use iced_core:: Point ;
429+ use iced_core:: Rectangle ;
430+ if let Some ( preedit) = & self . preedit {
431+ preedit. draw (
432+ renderer,
433+ text_color,
434+ background_color,
435+ & Rectangle :: new ( Point :: ORIGIN , logical_size) ,
436+ ) ;
437+ }
438+ }
439+
440+ fn enable_ime ( & mut self , position : iced_core:: Point , purpose : input_method:: Purpose ) {
441+ if self . ime_state != Some ( ( position, purpose) ) {
442+ self . ime_state = Some ( ( position, purpose) ) ;
443+ }
444+ }
445+
446+ fn disable_ime ( & mut self ) {
447+ if self . ime_state . is_some ( ) {
448+ self . ime_state = None ;
449+ }
450+
451+ self . preedit = None ;
452+ }
453+ }
454+
344455#[ allow( clippy:: too_many_arguments) ]
345456async fn run_instance < A , E , C > (
346457 mut application : A ,
@@ -370,6 +481,7 @@ async fn run_instance<A, E, C>(
370481 }
371482
372483 let mut renderer = compositor. create_renderer ( ) ;
484+ let mut im_drawer: IMDrawer < A > = IMDrawer :: new ( ) ;
373485
374486 let cache = user_interface:: Cache :: default ( ) ;
375487
@@ -435,14 +547,33 @@ async fn run_instance<A, E, C>(
435547 let redraw_event =
436548 IcedCoreEvent :: Window ( IcedCoreWindow :: Event :: RedrawRequested ( Instant :: now ( ) ) ) ;
437549
438- user_interface. update (
550+ let ( ui_state , _ ) = user_interface. update (
439551 & [ redraw_event. clone ( ) ] ,
440552 state. cursor ( ) ,
441553 & mut renderer,
442554 & mut clipboard,
443555 & mut messages,
444556 ) ;
445- events. push ( redraw_event. clone ( ) ) ;
557+ if let user_interface:: State :: Updated {
558+ redraw_request : _, // NOTE: I do not know how to use it now
559+ input_method,
560+ } = ui_state
561+ {
562+ events. push ( redraw_event. clone ( ) ) ;
563+ custom_actions. push ( LayerShellAction :: Ime ( input_method. clone ( ) ) ) ;
564+ im_drawer. request_input_method (
565+ state. background_color ( ) ,
566+ input_method,
567+ & renderer,
568+ ) ;
569+ }
570+ im_drawer. draw_preedit (
571+ & mut renderer,
572+ state. text_color ( ) ,
573+ state. background_color ( ) ,
574+ state. viewport ( ) . logical_size ( ) ,
575+ ) ;
576+
446577 runtime. broadcast ( iced_futures:: subscription:: Event :: Interaction {
447578 window : main_id,
448579 event : redraw_event,
0 commit comments