@@ -19,6 +19,7 @@ use crate::input::{
1919    KeyEvent ,  KeyboardModifiers ,  MouseEvent ,  StandardShortcut ,  TextShortcut , 
2020} ; 
2121use  crate :: item_rendering:: { CachedRenderingData ,  ItemRenderer ,  RenderText } ; 
22+ use  crate :: items:: FocusPolicy ; 
2223use  crate :: layout:: { LayoutInfo ,  Orientation } ; 
2324use  crate :: lengths:: { 
2425    LogicalLength ,  LogicalPoint ,  LogicalRect ,  LogicalSize ,  ScaleFactor ,  SizeLengths , 
@@ -520,6 +521,7 @@ pub struct TextInput {
520521    pub  single_line :  Property < bool > , 
521522    pub  read_only :  Property < bool > , 
522523    pub  preedit_text :  Property < SharedString > , 
524+     pub  focus_policy :  Property < FocusPolicy > , 
523525    /// A selection within the preedit (cursor and anchor) 
524526     preedit_selection :  Property < PreEditSelection > , 
525527    pub  cached_rendering_data :  CachedRenderingData , 
@@ -610,6 +612,11 @@ impl Item for TextInput {
610612        } 
611613        match  event { 
612614            MouseEvent :: Pressed  {  position,  button :  PointerEventButton :: Left ,  click_count }  => { 
615+                 #[ cfg( not( target_os = "android" ) ) ]  
616+                 if  !self . ensure_click_focus_and_ime ( window_adapter,  self_rc)  { 
617+                     return  InputEventResult :: EventIgnored ; 
618+                 } 
619+ 
613620                let  clicked_offset =
614621                    self . byte_offset_for_position ( * position,  window_adapter,  self_rc)  as  i32 ; 
615622                self . as_ref ( ) . pressed . set ( ( click_count % 3 )  + 1 ) ; 
@@ -618,9 +625,6 @@ impl Item for TextInput {
618625                    self . as_ref ( ) . anchor_position_byte_offset . set ( clicked_offset) ; 
619626                } 
620627
621-                 #[ cfg( not( target_os = "android" ) ) ]  
622-                 self . ensure_focus_and_ime ( window_adapter,  self_rc) ; 
623- 
624628                match  click_count % 3  { 
625629                    0  => self . set_cursor_position ( 
626630                        clicked_offset, 
@@ -638,13 +642,17 @@ impl Item for TextInput {
638642            } 
639643            MouseEvent :: Pressed  {  button :  PointerEventButton :: Middle ,  .. }  => { 
640644                #[ cfg( not( target_os = "android" ) ) ]  
641-                 self . ensure_focus_and_ime ( window_adapter,  self_rc) ; 
645+                 if  !self . ensure_click_focus_and_ime ( window_adapter,  self_rc)  { 
646+                     return  InputEventResult :: EventIgnored ; 
647+                 } 
642648            } 
643649            MouseEvent :: Released  {  button :  PointerEventButton :: Left ,  .. }  => { 
644650                self . as_ref ( ) . pressed . set ( 0 ) ; 
645651                self . copy_clipboard ( window_adapter,  Clipboard :: SelectionClipboard ) ; 
646652                #[ cfg( target_os = "android" ) ]  
647-                 self . ensure_focus_and_ime ( window_adapter,  self_rc) ; 
653+                 if  !self . ensure_click_focus_and_ime ( window_adapter,  self_rc)  { 
654+                     return  InputEventResult :: EventIgnored ; 
655+                 } 
648656            } 
649657            MouseEvent :: Released  {  position,  button :  PointerEventButton :: Middle ,  .. }  => { 
650658                let  clicked_offset =
@@ -936,6 +944,20 @@ impl Item for TextInput {
936944        window_adapter :  & Rc < dyn  WindowAdapter > , 
937945        self_rc :  & ItemRc , 
938946    )  -> FocusEventResult  { 
947+         let  reason = match  event { 
948+             FocusEvent :: FocusIn ( reason)  | FocusEvent :: FocusOut ( reason)  => * reason, 
949+         } ; 
950+ 
951+         match  ( reason,  self . focus_policy ( ) )  { 
952+             ( FocusReason :: TabNavigation ,  FocusPolicy :: ClickOnly )  => { 
953+                 return  FocusEventResult :: FocusIgnored 
954+             } 
955+             ( FocusReason :: PointerClick ,  FocusPolicy :: TabOnly )  => { 
956+                 return  FocusEventResult :: FocusIgnored 
957+             } 
958+             _ => ( ) , 
959+         } 
960+ 
939961        match  event { 
940962            FocusEvent :: FocusIn ( _reason)  => { 
941963                if  !self . enabled ( )  { 
@@ -1827,12 +1849,16 @@ impl TextInput {
18271849
18281850    /// When pressing the mouse (or releasing the finger, on android) we should take the focus if we don't have it already. 
18291851     /// Setting the focus will show the virtual keyboard, otherwise we should make sure that the keyboard is shown if it was hidden by the user 
1830-      fn  ensure_focus_and_ime ( 
1852+      /// Returns true if the focus was set, false if the focus policy is configured to not focus on click. 
1853+      fn  ensure_click_focus_and_ime ( 
18311854        self :  Pin < & Self > , 
18321855        window_adapter :  & Rc < dyn  WindowAdapter > , 
18331856        self_rc :  & ItemRc , 
1834-     )  { 
1857+     )  ->  bool   { 
18351858        if  !self . has_focus ( )  { 
1859+             if  self . focus_policy ( )  == FocusPolicy :: TabOnly  { 
1860+                 return  false ; 
1861+             } 
18361862            WindowInner :: from_pub ( window_adapter. window ( ) ) . set_focus_item ( 
18371863                self_rc, 
18381864                true , 
@@ -1845,6 +1871,7 @@ impl TextInput {
18451871                ) ) ; 
18461872            } 
18471873        } 
1874+         true 
18481875    } 
18491876
18501877    fn  add_undo_item ( self :  Pin < & Self > ,  item :  UndoItem )  { 
0 commit comments