@@ -40,11 +40,13 @@ use crate::input::{
4040 Seat , SeatHandler ,
4141} ;
4242use crate :: utils:: { Logical , Point , Rectangle , SERIAL_COUNTER } ;
43+ use crate :: wayland:: compositor;
4344use crate :: wayland:: seat:: keyboard:: for_each_focused_kbds;
4445
4546const INPUT_METHOD_VERSION : u32 = 1 ;
4647const TEXT_INPUT_VERSION : u32 = 1 ;
4748const INPUT_PANEL_VERSION : u32 = 1 ;
49+ const INPUT_PANEL_SURFACE_ROLE : & str = "zwp_input_panel_surface_v1" ;
4850
4951/// Parent surface and geometry used to place an IME popup.
5052#[ derive( Debug , Clone ) ]
@@ -772,12 +774,24 @@ where
772774 fn request (
773775 state : & mut D ,
774776 _client : & Client ,
775- _resource : & ZwpInputMethodContextV1 ,
777+ resource : & ZwpInputMethodContextV1 ,
776778 request : zwp_input_method_context_v1:: Request ,
777779 data : & InputMethodContextUserData ,
778780 _dhandle : & DisplayHandle ,
779781 data_init : & mut DataInit < ' _ , D > ,
780782 ) {
783+ let is_active_context = {
784+ let inner = data. handle . inner . lock ( ) . unwrap ( ) ;
785+ inner
786+ . active
787+ . context
788+ . as_ref ( )
789+ . is_some_and ( |ctx| ctx. id ( ) == resource. id ( ) )
790+ } ;
791+ if !is_active_context {
792+ return ;
793+ }
794+
781795 match request {
782796 zwp_input_method_context_v1:: Request :: CommitString { serial, text } => {
783797 if let Some ( ti) = data. handle . inner . lock ( ) . unwrap ( ) . active . text_input . as_ref ( ) {
@@ -937,13 +951,22 @@ where
937951 fn destroyed (
938952 state : & mut D ,
939953 _client : ClientId ,
940- _resource : & ZwpInputMethodContextV1 ,
954+ resource : & ZwpInputMethodContextV1 ,
941955 data : & InputMethodContextUserData ,
942956 ) {
943957 let active_seat = {
944958 let mut inner = data. handle . inner . lock ( ) . unwrap ( ) ;
945- inner. active . context = None ;
946- inner. active . seat . clone ( )
959+ let is_active_context = inner
960+ . active
961+ . context
962+ . as_ref ( )
963+ . is_some_and ( |ctx| ctx. id ( ) == resource. id ( ) ) ;
964+ if is_active_context {
965+ inner. active . context = None ;
966+ inner. active . seat . clone ( )
967+ } else {
968+ None
969+ }
947970 } ;
948971
949972 if let Some ( seat) = active_seat. and_then ( |s| Seat :: < D > :: from_resource ( & s) ) {
@@ -973,19 +996,22 @@ where
973996 fn destroyed (
974997 state : & mut D ,
975998 _client : ClientId ,
976- _resource : & WlKeyboard ,
999+ resource : & WlKeyboard ,
9771000 data : & InputMethodKeyboardUserData < D > ,
9781001 ) {
979- data. handle
980- . inner
981- . lock ( )
982- . unwrap ( )
983- . keyboard_grab
984- . inner
985- . lock ( )
986- . unwrap ( )
987- . grab = None ;
988- data. keyboard_handle . unset_grab ( state) ;
1002+ let should_unset = {
1003+ let inner = data. handle . inner . lock ( ) . unwrap ( ) ;
1004+ let mut grab = inner. keyboard_grab . inner . lock ( ) . unwrap ( ) ;
1005+ if grab. grab . as_ref ( ) . is_some_and ( |g| g. id ( ) == resource. id ( ) ) {
1006+ grab. grab = None ;
1007+ true
1008+ } else {
1009+ false
1010+ }
1011+ } ;
1012+ if should_unset {
1013+ data. keyboard_handle . unset_grab ( state) ;
1014+ }
9891015 }
9901016}
9911017
@@ -998,13 +1024,21 @@ where
9981024 fn request (
9991025 state : & mut D ,
10001026 _client : & Client ,
1001- _resource : & ZwpInputPanelV1 ,
1027+ resource : & ZwpInputPanelV1 ,
10021028 request : zwp_input_panel_v1:: Request ,
10031029 data : & InputPanelUserData ,
10041030 _dhandle : & DisplayHandle ,
10051031 data_init : & mut DataInit < ' _ , D > ,
10061032 ) {
10071033 if let zwp_input_panel_v1:: Request :: GetInputPanelSurface { id, surface } = request {
1034+ if compositor:: give_role ( & surface, INPUT_PANEL_SURFACE_ROLE ) . is_err ( )
1035+ && compositor:: get_role ( & surface) != Some ( INPUT_PANEL_SURFACE_ROLE )
1036+ {
1037+ // Protocol requires this raise an error, but doesn't define an error enum.
1038+ resource. post_error ( 0u32 , "Surface already has a role." ) ;
1039+ return ;
1040+ }
1041+
10081042 let panel_surface = data_init. init (
10091043 id,
10101044 InputPanelSurfaceUserData {
@@ -1039,12 +1073,23 @@ where
10391073 fn request (
10401074 state : & mut D ,
10411075 _client : & Client ,
1042- _resource : & ZwpInputPanelSurfaceV1 ,
1076+ resource : & ZwpInputPanelSurfaceV1 ,
10431077 request : zwp_input_panel_surface_v1:: Request ,
10441078 data : & InputPanelSurfaceUserData ,
10451079 _dhandle : & DisplayHandle ,
10461080 _data_init : & mut DataInit < ' _ , D > ,
10471081 ) {
1082+ let is_active_popup_surface = {
1083+ let inner = data. handle . inner . lock ( ) . unwrap ( ) ;
1084+ inner
1085+ . popup
1086+ . as_ref ( )
1087+ . is_some_and ( |popup| popup. surface_role . id ( ) == resource. id ( ) )
1088+ } ;
1089+ if !is_active_popup_surface {
1090+ return ;
1091+ }
1092+
10481093 match request {
10491094 zwp_input_panel_surface_v1:: Request :: SetOverlayPanel => {
10501095 data. handle . inner . lock ( ) . unwrap ( ) . popup_enabled = true ;
@@ -1061,9 +1106,20 @@ where
10611106 fn destroyed (
10621107 state : & mut D ,
10631108 _client : ClientId ,
1064- _resource : & ZwpInputPanelSurfaceV1 ,
1109+ resource : & ZwpInputPanelSurfaceV1 ,
10651110 data : & InputPanelSurfaceUserData ,
10661111 ) {
1112+ let is_active_popup_surface = {
1113+ let inner = data. handle . inner . lock ( ) . unwrap ( ) ;
1114+ inner
1115+ . popup
1116+ . as_ref ( )
1117+ . is_some_and ( |popup| popup. surface_role . id ( ) == resource. id ( ) )
1118+ } ;
1119+ if !is_active_popup_surface {
1120+ return ;
1121+ }
1122+
10671123 {
10681124 let mut inner = data. handle . inner . lock ( ) . unwrap ( ) ;
10691125 inner. popup = None ;
0 commit comments