Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 30d3c76

Browse files
tadeokondrakemersion
authored andcommitted
Implement input_method_v2 popups
1 parent e0daa65 commit 30d3c76

File tree

3 files changed

+172
-8
lines changed

3 files changed

+172
-8
lines changed

include/wlr/types/wlr_input_method_v2.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <stdlib.h>
1313
#include <wayland-server-core.h>
1414
#include <wlr/types/wlr_seat.h>
15+
#include <wlr/util/box.h>
1516

1617
struct wlr_input_method_v2_preedit_string {
1718
char *text;
@@ -42,6 +43,7 @@ struct wlr_input_method_v2 {
4243
bool client_active; // state known to the client
4344
uint32_t current_serial; // received in last commit call
4445

46+
struct wl_list popup_surfaces;
4547
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab;
4648

4749
struct wl_list link;
@@ -50,11 +52,31 @@ struct wlr_input_method_v2 {
5052

5153
struct {
5254
struct wl_signal commit; // (struct wlr_input_method_v2*)
55+
struct wl_signal new_popup_surface; // (struct wlr_input_popup_surface_v2*)
5356
struct wl_signal grab_keyboard; // (struct wlr_input_method_keyboard_grab_v2*)
5457
struct wl_signal destroy; // (struct wlr_input_method_v2*)
5558
} events;
5659
};
5760

61+
struct wlr_input_popup_surface_v2 {
62+
struct wl_resource *resource;
63+
struct wlr_input_method_v2 *input_method;
64+
struct wl_list link;
65+
bool mapped;
66+
67+
struct wlr_surface *surface;
68+
69+
struct wl_listener surface_destroy;
70+
71+
struct {
72+
struct wl_signal map;
73+
struct wl_signal unmap;
74+
struct wl_signal destroy;
75+
} events;
76+
77+
void *data;
78+
};
79+
5880
struct wlr_input_method_keyboard_grab_v2 {
5981
struct wl_resource *resource;
6082
struct wlr_input_method_v2 *input_method;
@@ -100,6 +122,12 @@ void wlr_input_method_v2_send_done(struct wlr_input_method_v2 *input_method);
100122
void wlr_input_method_v2_send_unavailable(
101123
struct wlr_input_method_v2 *input_method);
102124

125+
bool wlr_surface_is_input_popup_surface_v2(struct wlr_surface *surface);
126+
struct wlr_input_popup_surface_v2 *wlr_input_popup_surface_v2_from_wlr_surface(
127+
struct wlr_surface *surface);
128+
void wlr_input_popup_surface_v2_send_text_input_rectangle(
129+
struct wlr_input_popup_surface_v2 *popup_surface, struct wlr_box *sbox);
130+
103131
void wlr_input_method_keyboard_grab_v2_send_key(
104132
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab,
105133
uint32_t time, uint32_t key, uint32_t state);

include/wlr/types/wlr_text_input_v3.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <wayland-server-core.h>
1313
#include <wlr/types/wlr_seat.h>
1414
#include <wlr/types/wlr_surface.h>
15+
#include <wlr/util/box.h>
1516

1617
enum wlr_text_input_v3_features {
1718
WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT = 1 << 0,
@@ -33,12 +34,7 @@ struct wlr_text_input_v3_state {
3334
uint32_t purpose;
3435
} content_type;
3536

36-
struct {
37-
int32_t x;
38-
int32_t y;
39-
int32_t width;
40-
int32_t height;
41-
} cursor_rectangle;
37+
struct wlr_box cursor_rectangle;
4238

4339
// Tracks which features were used in the current commit.
4440
// Useful in the enabling commit, where usage means support.

types/wlr_input_method_v2.c

Lines changed: 142 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
static const struct zwp_input_method_v2_interface input_method_impl;
1818
static 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+
2023
static 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

3538
static 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+
111196
static 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

117249
void 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

356494
void 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

Comments
 (0)