1717static const struct zwp_input_method_v2_interface input_method_impl ;
1818static const struct zwp_input_method_keyboard_grab_v2_interface keyboard_grab_impl ;
1919
20+ static void popup_surface_destroy (
21+ struct wlr_input_popup_surface_v2 * popup_surface );
22+
2023static struct wlr_input_method_v2 * input_method_from_resource (
2124 struct wl_resource * resource ) {
2225 assert (wl_resource_instance_of (resource ,
@@ -33,6 +36,11 @@ static struct wlr_input_method_keyboard_grab_v2 *keyboard_grab_from_resource(
3336}
3437
3538static void input_method_destroy (struct wlr_input_method_v2 * input_method ) {
39+ struct wlr_input_popup_surface_v2 * popup_surface , * tmp ;
40+ wl_list_for_each_safe (
41+ popup_surface , tmp , & input_method -> popup_surfaces , link ) {
42+ popup_surface_destroy (popup_surface );
43+ }
3644 wlr_signal_emit_safe (& input_method -> events .destroy , input_method );
3745 wl_list_remove (wl_resource_get_link (input_method -> resource ));
3846 wl_list_remove (& input_method -> seat_client_destroy .link );
@@ -108,10 +116,134 @@ static void im_delete_surrounding_text(struct wl_client *client,
108116 input_method -> pending .delete .after_length = after_length ;
109117}
110118
119+ struct wlr_input_popup_surface_v2 * wlr_input_popup_surface_v2_from_wlr_surface (
120+ struct wlr_surface * surface ) {
121+ assert (wlr_surface_is_input_popup_surface_v2 (surface ));
122+ return (struct wlr_input_popup_surface_v2 * )surface -> role_data ;
123+ }
124+
125+ void wlr_input_popup_surface_v2_send_text_input_rectangle (
126+ struct wlr_input_popup_surface_v2 * popup_surface ,
127+ struct wlr_box * sbox ) {
128+ zwp_input_popup_surface_v2_send_text_input_rectangle (
129+ popup_surface -> resource , sbox -> x , sbox -> y , sbox -> width , sbox -> height );
130+ }
131+
132+ static void popup_surface_set_mapped (
133+ struct wlr_input_popup_surface_v2 * popup_surface , bool mapped ) {
134+ if (mapped && !popup_surface -> mapped ) {
135+ popup_surface -> mapped = true;
136+ wlr_signal_emit_safe (& popup_surface -> events .map , popup_surface );
137+ } else if (!mapped && popup_surface -> mapped ) {
138+ wlr_signal_emit_safe (& popup_surface -> events .unmap , popup_surface );
139+ popup_surface -> mapped = false;
140+ }
141+ }
142+
143+ static void popup_surface_surface_role_commit (struct wlr_surface * surface ) {
144+ struct wlr_input_popup_surface_v2 * popup_surface = surface -> role_data ;
145+ if (popup_surface == NULL ) {
146+ return ;
147+ }
148+ popup_surface_set_mapped (popup_surface , wlr_surface_has_buffer (surface )
149+ && popup_surface -> input_method -> client_active );
150+ }
151+
152+ static const struct wlr_surface_role input_popup_surface_v2_role = {
153+ .name = "zwp_input_popup_surface_v2" ,
154+ .commit = popup_surface_surface_role_commit ,
155+ };
156+
157+ bool wlr_surface_is_input_popup_surface_v2 (struct wlr_surface * surface ) {
158+ return surface -> role == & input_popup_surface_v2_role ;
159+ }
160+
161+ static void popup_surface_destroy (
162+ struct wlr_input_popup_surface_v2 * popup_surface ) {
163+ popup_surface_set_mapped (popup_surface , false);
164+ wlr_signal_emit_safe (& popup_surface -> events .destroy , NULL );
165+ wl_list_remove (& popup_surface -> surface_destroy .link );
166+ wl_list_remove (& popup_surface -> link );
167+ wl_resource_set_user_data (popup_surface -> resource , NULL );
168+ free (popup_surface );
169+ }
170+
171+ static void popup_surface_handle_surface_destroy (struct wl_listener * listener ,
172+ void * data ) {
173+ struct wlr_input_popup_surface_v2 * popup_surface =
174+ wl_container_of (listener , popup_surface , surface_destroy );
175+ popup_surface_destroy (popup_surface );
176+ }
177+
178+ static void popup_resource_destroy (struct wl_resource * resource ) {
179+ struct wlr_input_popup_surface_v2 * popup_surface =
180+ wl_resource_get_user_data (resource );
181+ if (popup_surface == NULL ) {
182+ return ;
183+ }
184+ popup_surface_destroy (popup_surface );
185+ }
186+
187+ static void popup_destroy (struct wl_client * client ,
188+ struct wl_resource * resource ) {
189+ wl_resource_destroy (resource );
190+ }
191+
192+ static const struct zwp_input_popup_surface_v2_interface input_popup_impl = {
193+ .destroy = popup_destroy ,
194+ };
195+
111196static void im_get_input_popup_surface (struct wl_client * client ,
112197 struct wl_resource * resource , uint32_t id ,
113- struct wl_resource * surface ) {
114- wlr_log (WLR_INFO , "Stub: zwp_input_method_v2::get_input_popup_surface" );
198+ struct wl_resource * surface_resource ) {
199+ struct wlr_input_method_v2 * input_method =
200+ input_method_from_resource (resource );
201+ if (!input_method ) {
202+ return ;
203+ }
204+
205+ struct wl_resource * popup_resource = wl_resource_create (
206+ client , & zwp_input_popup_surface_v2_interface ,
207+ wl_resource_get_version (resource ), id );
208+ if (!popup_resource ) {
209+ wl_client_post_no_memory (client );
210+ return ;
211+ }
212+
213+ struct wlr_input_popup_surface_v2 * popup_surface =
214+ calloc (1 , sizeof (struct wlr_input_popup_surface_v2 ));
215+ if (!popup_surface ) {
216+ wl_client_post_no_memory (client );
217+ return ;
218+ }
219+ wl_resource_set_implementation (popup_resource , & input_popup_impl ,
220+ popup_surface , popup_resource_destroy );
221+
222+ struct wlr_surface * surface = wlr_surface_from_resource (surface_resource );
223+ if (!wlr_surface_set_role (surface , & input_popup_surface_v2_role ,
224+ popup_surface , resource , ZWP_INPUT_METHOD_V2_ERROR_ROLE )) {
225+ free (popup_surface );
226+ return ;
227+ }
228+
229+ popup_surface -> resource = popup_resource ;
230+ popup_surface -> input_method = input_method ;
231+ popup_surface -> surface = surface ;
232+ wl_signal_add (& popup_surface -> surface -> events .destroy ,
233+ & popup_surface -> surface_destroy );
234+ popup_surface -> surface_destroy .notify =
235+ popup_surface_handle_surface_destroy ;
236+
237+ wl_signal_init (& popup_surface -> events .map );
238+ wl_signal_init (& popup_surface -> events .unmap );
239+ wl_signal_init (& popup_surface -> events .destroy );
240+
241+ popup_surface_set_mapped (popup_surface ,
242+ wlr_surface_has_buffer (popup_surface -> surface )
243+ && popup_surface -> input_method -> client_active );
244+
245+ wl_list_insert (& input_method -> popup_surfaces , & popup_surface -> link );
246+ wlr_signal_emit_safe (& input_method -> events .new_popup_surface , popup_surface );
115247}
116248
117249void wlr_input_method_keyboard_grab_v2_destroy (
@@ -351,6 +483,12 @@ void wlr_input_method_v2_send_done(struct wlr_input_method_v2 *input_method) {
351483 zwp_input_method_v2_send_done (input_method -> resource );
352484 input_method -> client_active = input_method -> active ;
353485 input_method -> current_serial ++ ;
486+ struct wlr_input_popup_surface_v2 * popup_surface ;
487+ wl_list_for_each (popup_surface , & input_method -> popup_surfaces , link ) {
488+ popup_surface_set_mapped (popup_surface ,
489+ wlr_surface_has_buffer (popup_surface -> surface ) &&
490+ input_method -> client_active );
491+ }
354492}
355493
356494void wlr_input_method_v2_send_unavailable (
@@ -390,7 +528,9 @@ static void manager_get_input_method(struct wl_client *client,
390528 wl_client_post_no_memory (client );
391529 return ;
392530 }
531+ wl_list_init (& input_method -> popup_surfaces );
393532 wl_signal_init (& input_method -> events .commit );
533+ wl_signal_init (& input_method -> events .new_popup_surface );
394534 wl_signal_init (& input_method -> events .grab_keyboard );
395535 wl_signal_init (& input_method -> events .destroy );
396536 int version = wl_resource_get_version (resource );
0 commit comments