adopt dwl/suckless style

also merge main and wlroots-next
requires swaywm/wlroots@30d3c76
This commit is contained in:
Leonardo Hernandez Hernandez 2021-10-10 19:34:33 -05:00
parent fe1764e328
commit 52a061dbda
No known key found for this signature in database
GPG Key ID: E538897EE11B9624

416
dwl.c
View File

@ -215,9 +215,9 @@ typedef struct {
* in the focused state, wl_keyboard sent an enter as well. However, having * in the focused state, wl_keyboard sent an enter as well. However, having
* wl_keyboard focused doesn't mean that text-input will be focused. * wl_keyboard focused doesn't mean that text-input will be focused.
*/ */
struct dwl_input_method_relay { typedef struct {
struct wl_list text_inputs; // dwl_text_input::link struct wl_list text_inputs; // TextInput::link
struct wl_list input_popups; // dwl_input_popup::link struct wl_list input_popups; // InputPopup::link
struct wlr_input_method_v2 *input_method; // doesn't have to be present struct wlr_input_method_v2 *input_method; // doesn't have to be present
struct wl_listener text_input_new; struct wl_listener text_input_new;
@ -228,10 +228,10 @@ struct dwl_input_method_relay {
struct wl_listener input_method_new_popup_surface; struct wl_listener input_method_new_popup_surface;
struct wl_listener input_method_grab_keyboard; struct wl_listener input_method_grab_keyboard;
struct wl_listener input_method_keyboard_grab_destroy; struct wl_listener input_method_keyboard_grab_destroy;
}; } InputMethodRelay;
struct dwl_text_input { typedef struct {
struct dwl_input_method_relay *relay; InputMethodRelay *relay;
struct wlr_text_input_v3 *input; struct wlr_text_input_v3 *input;
// The surface getting seat's focus. Stored for when text-input cannot // The surface getting seat's focus. Stored for when text-input cannot
@ -247,11 +247,10 @@ struct dwl_text_input {
struct wl_listener text_input_commit; struct wl_listener text_input_commit;
struct wl_listener text_input_disable; struct wl_listener text_input_disable;
struct wl_listener text_input_destroy; struct wl_listener text_input_destroy;
}; } TextInput;
typedef struct {
struct dwl_input_popup { InputMethodRelay *relay;
struct dwl_input_method_relay *relay;
struct wlr_input_popup_surface_v2 *popup_surface; struct wlr_input_popup_surface_v2 *popup_surface;
int x, y; int x, y;
@ -265,7 +264,7 @@ struct dwl_input_popup {
struct wl_listener popup_destroy; struct wl_listener popup_destroy;
struct wl_listener popup_surface_commit; struct wl_listener popup_surface_commit;
struct wl_listener focused_surface_unmap; struct wl_listener focused_surface_unmap;
}; } InputPopup;
/* Used to move all of the data necessary to render a surface from the top-level /* Used to move all of the data necessary to render a surface from the top-level
* frame handler to the per-surface render function. */ * frame handler to the per-surface render function. */
@ -302,14 +301,33 @@ static void createpointer(struct wlr_input_device *device);
static void cursorframe(struct wl_listener *listener, void *data); static void cursorframe(struct wl_listener *listener, void *data);
static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data);
static void destroypendingfocusedsurface(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir); static Monitor *dirtomon(enum wlr_direction dir);
static void focusclient(Client *c, int lift); static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg); static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg); static void focusstack(const Arg *arg);
static void fullscreennotify(struct wl_listener *listener, void *data); static void fullscreennotify(struct wl_listener *listener, void *data);
static Client *focustop(Monitor *m); static Client *focustop(Monitor *m);
static void getparentandoutputbox(struct wlr_surface *focused_surface,
struct wlr_box *parent, struct wlr_box *output_box);
static void incnmaster(const Arg *arg); static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data); static void inputdevice(struct wl_listener *listener, void *data);
static void inputmethodrelaysetfocus(InputMethodRelay *relay, struct wlr_surface *surface);
static TextInput *textinputcreate(InputMethodRelay *relay,
struct wlr_text_input_v3 *text_input);
static void inputmethodgrabkeyboard(struct wl_listener *listener, void *data);
static void inputmethodkeyboardgrabdestroy(struct wl_listener *listener, void *data);
static void inputmethodcommit(struct wl_listener *listener, void *data);
static void inputmethodfocusedsurfacedestroy(struct wl_listener *listener, void *data);
static void inputmethoddestroy(struct wl_listener *listener, void *data);
static void inputmethodrelaysetfocus(InputMethodRelay *relay, struct wlr_surface *surface);
static void inputpopupsetfocus(InputPopup *popup, struct wlr_surface *surface);
static void inputpopupsendoutputs(InputPopup *popup, wlr_surface_iterator_func_t iterator);
static void inputmethodnewpopupsurface(struct wl_listener *listener, void *data);
static void inputmethodpopupdestroy(struct wl_listener *listener, void *data);
static void inputmethodpopupmap(struct wl_listener *listener, void *data);
static void inputmethodpopupunmap(struct wl_listener *listener, void *data);
static void inputmethodpopupsurfacecommit(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym); static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data); static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data);
@ -329,6 +347,12 @@ static void pointerfocus(Client *c, struct wlr_surface *surface,
static void printstatus(void); static void printstatus(void);
static void quit(const Arg *arg); static void quit(const Arg *arg);
static void quitsignal(int signo); static void quitsignal(int signo);
static void relaycreateinputmethod(struct wl_listener *listener, void *data);
static void relaycreatetextinput(struct wl_listener *listener, void *data);
static void relaydisabletextinput(InputMethodRelay *relay, TextInput *text_input);
static TextInput *relaygetfocusabletextinput(InputMethodRelay *relay);
static TextInput *relaygetfocusedtextinput(InputMethodRelay *relay);
static void relaysendinputmethodstate(InputMethodRelay *relay, struct wlr_text_input_v3 *input);
static void render(struct wlr_surface *surface, int sx, int sy, void *data); static void render(struct wlr_surface *surface, int sx, int sy, void *data);
static void renderclients(Monitor *m, struct timespec *now); static void renderclients(Monitor *m, struct timespec *now);
static void renderlayer(struct wl_list *layer_surfaces, struct timespec *now); static void renderlayer(struct wl_list *layer_surfaces, struct timespec *now);
@ -348,8 +372,17 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags);
static void setup(void); static void setup(void);
static void sigchld(int unused); static void sigchld(int unused);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void surfacesendenter(struct wlr_surface *surface, int x, int y, void *data);
static void surfacesendleave(struct wlr_surface *surface, int x, int y, void *data);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static void tagmon(const Arg *arg); static void tagmon(const Arg *arg);
static void textinputcommit(struct wl_listener *listener, void *data);
static TextInput *textinputcreate(InputMethodRelay *relay, struct wlr_text_input_v3 *text_input);
static void textinputenable(struct wl_listener *listener, void *data);
static void textinputdestroy(struct wl_listener *listener, void *data);
static void textinputdisable(struct wl_listener *listener, void *data);
static void textinputsetpendingfocusedsurface(TextInput *text_input,
struct wlr_surface *surface);
static void tile(Monitor *m); static void tile(Monitor *m);
static void togglefloating(const Arg *arg); static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg); static void togglefullscreen(const Arg *arg);
@ -358,6 +391,7 @@ static void toggleview(const Arg *arg);
static void unmaplayersurface(LayerSurface *layersurface); static void unmaplayersurface(LayerSurface *layersurface);
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
static void unmapnotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data);
static void updateinputpopup(InputPopup *popup);
static void updatemons(struct wl_listener *listener, void *data); static void updatemons(struct wl_listener *listener, void *data);
static void updatetitle(struct wl_listener *listener, void *data); static void updatetitle(struct wl_listener *listener, void *data);
static void urgent(struct wl_listener *listener, void *data); static void urgent(struct wl_listener *listener, void *data);
@ -367,17 +401,6 @@ static Client *xytoclient(double x, double y);
static struct wlr_surface *xytolayersurface(struct wl_list *layer_surfaces, static struct wlr_surface *xytolayersurface(struct wl_list *layer_surfaces,
double x, double y, double *sx, double *sy); double x, double y, double *sx, double *sy);
static Monitor *xytomon(double x, double y); static Monitor *xytomon(double x, double y);
void dwl_input_method_relay_init(struct dwl_input_method_relay *relay);
// Updates currently focused surface. Surface must belong to the same
// seat.
void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
struct wlr_surface *surface);
struct dwl_text_input *dwl_text_input_create(
struct dwl_input_method_relay *relay,
struct wlr_text_input_v3 *text_input);
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data);
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener,
void *data);
static void zoom(const Arg *arg); static void zoom(const Arg *arg);
/* variables */ /* variables */
@ -393,7 +416,7 @@ static struct wl_list clients; /* tiling order */
static struct wl_list fstack; /* focus order */ static struct wl_list fstack; /* focus order */
static struct wl_list stack; /* stacking z-order */ static struct wl_list stack; /* stacking z-order */
static struct wl_list independents; static struct wl_list independents;
static struct wl_list input_popups; /* dwl_input_popup::view_link to be rendered for the input method */ static struct wl_list input_popups; /* InputPopup::view_link to be rendered for the input method */
static struct wlr_idle *idle; static struct wlr_idle *idle;
static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_layer_shell_v1 *layer_shell;
static struct wlr_output_manager_v1 *output_mgr; static struct wlr_output_manager_v1 *output_mgr;
@ -404,9 +427,9 @@ static struct wlr_cursor *cursor;
static struct wlr_xcursor_manager *cursor_mgr; static struct wlr_xcursor_manager *cursor_mgr;
static struct wlr_seat *seat; static struct wlr_seat *seat;
struct wlr_input_method_manager_v2 *input_method_manager; struct wlr_input_method_manager_v2 *input_method_mgr;
struct wlr_text_input_manager_v3 *text_input_manager; struct wlr_text_input_manager_v3 *text_input_mgr;
struct dwl_input_method_relay *input_relay; InputMethodRelay *input_relay;
static struct wl_list keyboards; static struct wl_list keyboards;
static unsigned int cursor_mode; static unsigned int cursor_mode;
static Client *grabc; static Client *grabc;
@ -1203,7 +1226,7 @@ focusclient(Client *c, int lift)
kb = wlr_seat_get_keyboard(seat); kb = wlr_seat_get_keyboard(seat);
wlr_seat_keyboard_notify_enter(seat, client_surface(c), wlr_seat_keyboard_notify_enter(seat, client_surface(c),
kb->keycodes, kb->num_keycodes, &kb->modifiers); kb->keycodes, kb->num_keycodes, &kb->modifiers);
dwl_input_method_relay_set_focus(input_relay, client_surface(c)); inputmethodrelaysetfocus(input_relay, client_surface(c));
/* Activate the new client */ /* Activate the new client */
client_activate_surface(client_surface(c), 1); client_activate_surface(client_surface(c), 1);
@ -1444,8 +1467,10 @@ mapnotify(struct wl_listener *listener, void *data)
applyrules(c); applyrules(c);
} }
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) { void
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, inputmethodgrabkeyboard(struct wl_listener *listener, void *data)
{
InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_grab_keyboard); input_method_grab_keyboard);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
@ -1459,11 +1484,13 @@ static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
wl_signal_add(&keyboard_grab->events.destroy, wl_signal_add(&keyboard_grab->events.destroy,
&relay->input_method_keyboard_grab_destroy); &relay->input_method_keyboard_grab_destroy);
relay->input_method_keyboard_grab_destroy.notify = relay->input_method_keyboard_grab_destroy.notify =
handle_im_keyboard_grab_destroy; inputmethodkeyboardgrabdestroy;
} }
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) { void
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, inputmethodkeyboardgrabdestroy(struct wl_listener *listener, void *data)
{
InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_keyboard_grab_destroy); input_method_keyboard_grab_destroy);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link); wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
@ -1887,7 +1914,7 @@ void
render_input_popups(struct wlr_output* output, struct wl_list *input_popups, render_input_popups(struct wlr_output* output, struct wl_list *input_popups,
struct timespec *now) struct timespec *now)
{ {
struct dwl_input_popup *popup; InputPopup *popup;
wl_list_for_each(popup, input_popups, view_link) { wl_list_for_each(popup, input_popups, view_link) {
struct render_data rdata = { struct render_data rdata = {
@ -2157,9 +2184,10 @@ setsel(struct wl_listener *listener, void *data)
} }
// text-input-, and input_method-relevant functions // text-input-, and input_method-relevant functions
static struct dwl_text_input *relay_get_focusable_text_input( TextInput *
struct dwl_input_method_relay *relay) { relaygetfocusabletextinput(InputMethodRelay *relay)
struct dwl_text_input *text_input = NULL; {
TextInput *text_input = NULL;
wl_list_for_each(text_input, &relay->text_inputs, link) { wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->pending_focused_surface) { if (text_input->pending_focused_surface) {
return text_input; return text_input;
@ -2168,9 +2196,10 @@ static struct dwl_text_input *relay_get_focusable_text_input(
return NULL; return NULL;
} }
static struct dwl_text_input *relay_get_focused_text_input( TextInput *
struct dwl_input_method_relay *relay) { relaygetfocusedtextinput(InputMethodRelay *relay)
struct dwl_text_input *text_input = NULL; {
TextInput *text_input = NULL;
wl_list_for_each(text_input, &relay->text_inputs, link) { wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->input->focused_surface) { if (text_input->input->focused_surface) {
return text_input; return text_input;
@ -2179,13 +2208,15 @@ static struct dwl_text_input *relay_get_focused_text_input(
return NULL; return NULL;
} }
static void handle_im_commit(struct wl_listener *listener, void *data) { void
inputmethodcommit(struct wl_listener *listener, void *data)
{
struct wlr_input_method_v2 *context; struct wlr_input_method_v2 *context;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_commit); input_method_commit);
struct dwl_text_input *text_input = relay_get_focused_text_input(relay); TextInput *text_input = relaygetfocusedtextinput(relay);
if (!text_input) { if (!text_input) {
return; return;
} }
@ -2211,8 +2242,10 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
wlr_text_input_v3_send_done(text_input->input); wlr_text_input_v3_send_done(text_input->input);
} }
static void text_input_set_pending_focused_surface( void
struct dwl_text_input *text_input, struct wlr_surface *surface) { textinputsetpendingfocusedsurface(
TextInput *text_input, struct wlr_surface *surface)
{
wl_list_remove(&text_input->pending_focused_surface_destroy.link); wl_list_remove(&text_input->pending_focused_surface_destroy.link);
text_input->pending_focused_surface = surface; text_input->pending_focused_surface = surface;
@ -2224,27 +2257,31 @@ static void text_input_set_pending_focused_surface(
} }
} }
static void handle_im_destroy(struct wl_listener *listener, void *data) { void
struct dwl_text_input *text_input; inputmethoddestroy(struct wl_listener *listener, void *data)
{
TextInput *text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_destroy); input_method_destroy);
struct wlr_input_method_v2 *context = data; struct wlr_input_method_v2 *context = data;
assert(context == relay->input_method); assert(context == relay->input_method);
relay->input_method = NULL; relay->input_method = NULL;
text_input = relay_get_focused_text_input(relay); text_input = relaygetfocusedtextinput(relay);
if (text_input) { if (text_input) {
// keyboard focus is still there, so keep the surface at hand in case // keyboard focus is still there, so keep the surface at hand in case
// the input method returns // the input method returns
text_input_set_pending_focused_surface(text_input, textinputsetpendingfocusedsurface(text_input,
text_input->input->focused_surface); text_input->input->focused_surface);
wlr_text_input_v3_send_leave(text_input->input); wlr_text_input_v3_send_leave(text_input->input);
} }
} }
static void relay_send_im_state(struct dwl_input_method_relay *relay, void
struct wlr_text_input_v3 *input) { relaysendinputmethodstate(InputMethodRelay *relay,
struct wlr_text_input_v3 *input)
{
struct wlr_input_method_v2 *input_method = relay->input_method; struct wlr_input_method_v2 *input_method = relay->input_method;
if (!input_method) { if (!input_method) {
wlr_log(WLR_INFO, "Sending IM_DONE but im is gone"); wlr_log(WLR_INFO, "Sending IM_DONE but im is gone");
@ -2262,20 +2299,23 @@ static void relay_send_im_state(struct dwl_input_method_relay *relay,
// TODO: pass intent, display popup size // TODO: pass intent, display popup size
} }
static void handle_text_input_enable(struct wl_listener *listener, void *data) { void
struct dwl_text_input *text_input = wl_container_of(listener, text_input, textinputenable(struct wl_listener *listener, void *data)
{
TextInput *text_input = wl_container_of(listener, text_input,
text_input_enable); text_input_enable);
if (text_input->relay->input_method == NULL) { if (text_input->relay->input_method == NULL) {
wlr_log(WLR_INFO, "Enabling text input when input method is gone"); wlr_log(WLR_INFO, "Enabling text input when input method is gone");
return; return;
} }
wlr_input_method_v2_send_activate(text_input->relay->input_method); wlr_input_method_v2_send_activate(text_input->relay->input_method);
relay_send_im_state(text_input->relay, text_input->input); relaysendinputmethodstate(text_input->relay, text_input->input);
} }
static void handle_text_input_commit(struct wl_listener *listener, void
void *data) { textinputcommit(struct wl_listener *listener, void *data)
struct dwl_text_input *text_input = wl_container_of(listener, text_input, {
TextInput *text_input = wl_container_of(listener, text_input,
text_input_commit); text_input_commit);
if (!text_input->input->current_enabled) { if (!text_input->input->current_enabled) {
wlr_log(WLR_INFO, "Inactive text input tried to commit an update"); wlr_log(WLR_INFO, "Inactive text input tried to commit an update");
@ -2286,35 +2326,38 @@ static void handle_text_input_commit(struct wl_listener *listener,
wlr_log(WLR_INFO, "Text input committed, but input method is gone"); wlr_log(WLR_INFO, "Text input committed, but input method is gone");
return; return;
} }
relay_send_im_state(text_input->relay, text_input->input); relaysendinputmethodstate(text_input->relay, text_input->input);
} }
static void relay_disable_text_input(struct dwl_input_method_relay *relay, void
struct dwl_text_input *text_input) { relaydisabletextinput(InputMethodRelay *relay, TextInput *text_input)
{
if (relay->input_method == NULL) { if (relay->input_method == NULL) {
wlr_log(WLR_DEBUG, "Disabling text input, but input method is gone"); wlr_log(WLR_DEBUG, "Disabling text input, but input method is gone");
return; return;
} }
wlr_input_method_v2_send_deactivate(relay->input_method); wlr_input_method_v2_send_deactivate(relay->input_method);
relay_send_im_state(relay, text_input->input); relaysendinputmethodstate(relay, text_input->input);
} }
static void handle_text_input_disable(struct wl_listener *listener, void
void *data) { textinputdisable(struct wl_listener *listener, void *data)
struct dwl_text_input *text_input = wl_container_of(listener, text_input, {
TextInput *text_input = wl_container_of(listener, text_input,
text_input_disable); text_input_disable);
relay_disable_text_input(text_input->relay, text_input); relaydisabletextinput(text_input->relay, text_input);
} }
static void handle_text_input_destroy(struct wl_listener *listener, void
void *data) { textinputdestroy(struct wl_listener *listener, void *data)
struct dwl_text_input *text_input = wl_container_of(listener, text_input, {
TextInput *text_input = wl_container_of(listener, text_input,
text_input_destroy); text_input_destroy);
if (text_input->input->current_enabled) { if (text_input->input->current_enabled) {
relay_disable_text_input(text_input->relay, text_input); relaydisabletextinput(text_input->relay, text_input);
} }
text_input_set_pending_focused_surface(text_input, NULL); textinputsetpendingfocusedsurface(text_input, NULL);
wl_list_remove(&text_input->text_input_commit.link); wl_list_remove(&text_input->text_input_commit.link);
wl_list_remove(&text_input->text_input_destroy.link); wl_list_remove(&text_input->text_input_destroy.link);
wl_list_remove(&text_input->text_input_disable.link); wl_list_remove(&text_input->text_input_disable.link);
@ -2323,9 +2366,10 @@ static void handle_text_input_destroy(struct wl_listener *listener,
free(text_input); free(text_input);
} }
static void handle_pending_focused_surface_destroy(struct wl_listener *listener, void
void *data) { destroypendingfocusedsurface(struct wl_listener *listener, void *data)
struct dwl_text_input *text_input = wl_container_of(listener, text_input, {
TextInput *text_input = wl_container_of(listener, text_input,
pending_focused_surface_destroy); pending_focused_surface_destroy);
struct wlr_surface *surface = data; struct wlr_surface *surface = data;
assert(text_input->pending_focused_surface == surface); assert(text_input->pending_focused_surface == surface);
@ -2334,10 +2378,10 @@ static void handle_pending_focused_surface_destroy(struct wl_listener *listener,
wl_list_init(&text_input->pending_focused_surface_destroy.link); wl_list_init(&text_input->pending_focused_surface_destroy.link);
} }
struct dwl_text_input *dwl_text_input_create( TextInput *
struct dwl_input_method_relay *relay, textinputcreate(InputMethodRelay *relay, struct wlr_text_input_v3 *text_input)
struct wlr_text_input_v3 *text_input) { {
struct dwl_text_input *input; TextInput *input;
input = calloc(1, sizeof(*input)); input = calloc(1, sizeof(*input));
if (!input) { if (!input) {
return NULL; return NULL;
@ -2347,53 +2391,45 @@ struct dwl_text_input *dwl_text_input_create(
wl_list_insert(&relay->text_inputs, &input->link); wl_list_insert(&relay->text_inputs, &input->link);
input->text_input_enable.notify = handle_text_input_enable; input->text_input_enable.notify = textinputenable;
wl_signal_add(&text_input->events.enable, &input->text_input_enable); wl_signal_add(&text_input->events.enable, &input->text_input_enable);
input->text_input_commit.notify = handle_text_input_commit; input->text_input_commit.notify = textinputcommit;
wl_signal_add(&text_input->events.commit, &input->text_input_commit); wl_signal_add(&text_input->events.commit, &input->text_input_commit);
input->text_input_disable.notify = handle_text_input_disable; input->text_input_disable.notify = textinputdisable;
wl_signal_add(&text_input->events.disable, &input->text_input_disable); wl_signal_add(&text_input->events.disable, &input->text_input_disable);
input->text_input_destroy.notify = handle_text_input_destroy; input->text_input_destroy.notify = textinputdestroy;
wl_signal_add(&text_input->events.destroy, &input->text_input_destroy); wl_signal_add(&text_input->events.destroy, &input->text_input_destroy);
input->pending_focused_surface_destroy.notify = input->pending_focused_surface_destroy.notify =
handle_pending_focused_surface_destroy; destroypendingfocusedsurface;
wl_list_init(&input->pending_focused_surface_destroy.link); wl_list_init(&input->pending_focused_surface_destroy.link);
return input; return input;
} }
static void relay_handle_text_input(struct wl_listener *listener, void
void *data) { relaycreatetextinput(struct wl_listener *listener, void *data)
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, {
InputMethodRelay *relay = wl_container_of(listener, relay,
text_input_new); text_input_new);
struct wlr_text_input_v3 *wlr_text_input = data; struct wlr_text_input_v3 *wlr_text_input = data;
if (seat != wlr_text_input->seat) { if (seat != wlr_text_input->seat) {
return; return;
} }
dwl_text_input_create(relay, wlr_text_input); textinputcreate(relay, wlr_text_input);
} }
static LayerSurface* layer_surface_from_wlr_layer_surface_v1( void
struct wlr_layer_surface_v1* layer_surface) { inputpopupsendoutputs(InputPopup *popup, wlr_surface_iterator_func_t iterator)
return layer_surface->data; {
}
static Client* client_from_wlr_surface(struct wlr_surface* surface) {
return surface->data;
}
static void input_popup_send_outputs(struct dwl_input_popup *popup,
wlr_surface_iterator_func_t iterator) {
struct wlr_surface* focused_surface; struct wlr_surface* focused_surface;
struct wlr_output* output; struct wlr_output* output;
Client* client; Client* client;
struct dwl_text_input *text_input = TextInput *text_input = relaygetfocusedtextinput(popup->relay);
relay_get_focused_text_input(popup->relay);
if (!text_input || !text_input->input->focused_surface) { if (!text_input || !text_input->input->focused_surface) {
return; return;
} }
@ -2407,41 +2443,44 @@ static void input_popup_send_outputs(struct dwl_input_popup *popup,
return; return;
} }
client = client_from_wlr_surface(focused_surface); client = focused_surface->data;
output = client->mon->wlr_output; output = client->mon->wlr_output;
wlr_surface_for_each_surface(popup->popup_surface->surface, wlr_surface_for_each_surface(popup->popup_surface->surface,
iterator, output); iterator, output);
} }
static void surface_send_enter_iterator(struct wlr_surface *surface, void
int x, int y, void *data) { surfacesendenter(struct wlr_surface *surface, int x, int y, void *data)
{
struct wlr_output *wlr_output = data; struct wlr_output *wlr_output = data;
wlr_surface_send_enter(surface, wlr_output); wlr_surface_send_enter(surface, wlr_output);
} }
static void surface_send_leave_iterator(struct wlr_surface *surface, void
int x, int y, void *data) { surfacesendleave(struct wlr_surface *surface, int x, int y, void *data)
{
struct wlr_output *wlr_output = data; struct wlr_output *wlr_output = data;
wlr_surface_send_leave(surface, wlr_output); wlr_surface_send_leave(surface, wlr_output);
} }
static void get_parent_and_output_box(struct wlr_surface *focused_surface, void
struct wlr_box *parent, struct wlr_box *output_box) { getparentandoutputbox(struct wlr_surface *focused_surface,
struct wlr_box *parent, struct wlr_box *output_box)
{
struct wlr_output *output; struct wlr_output *output;
struct wlr_box *output_box_tmp; struct wlr_box *output_box_tmp;
if (wlr_surface_is_layer_surface(focused_surface)) { if (wlr_surface_is_layer_surface(focused_surface)) {
struct wlr_layer_surface_v1 *layer_surface = struct wlr_layer_surface_v1 *layer_surface =
wlr_layer_surface_v1_from_wlr_surface(focused_surface); wlr_layer_surface_v1_from_wlr_surface(focused_surface);
LayerSurface* layer = LayerSurface* layer = layer_surface->data;
layer_surface_from_wlr_layer_surface_v1(layer_surface);
output = layer->layer_surface->output; output = layer->layer_surface->output;
output_box_tmp = wlr_output_layout_get_box(output_layout, output); output_box_tmp = wlr_output_layout_get_box(output_layout, output);
*parent = layer->geo; *parent = layer->geo;
parent->x += output_box_tmp->x; parent->x += output_box_tmp->x;
parent->y += output_box_tmp->y; parent->y += output_box_tmp->y;
} else { } else {
Client *client = client_from_wlr_surface(focused_surface); Client *client = focused_surface->data;
output = wlr_output_layout_output_at(output_layout, output = wlr_output_layout_output_at(output_layout,
client->geom.x, client->geom.y); client->geom.x, client->geom.y);
output_box_tmp = wlr_output_layout_get_box(output_layout, output); output_box_tmp = wlr_output_layout_get_box(output_layout, output);
@ -2454,15 +2493,17 @@ static void get_parent_and_output_box(struct wlr_surface *focused_surface,
*output_box = *output_box_tmp; *output_box = *output_box_tmp;
} }
static void input_popup_update(struct dwl_input_popup *popup) { void
updateinputpopup(InputPopup *popup)
{
struct wlr_surface* focused_surface; struct wlr_surface* focused_surface;
struct wlr_box output_box, parent, cursor; struct wlr_box output_box, parent, cursor;
int x1, x2, y1, y2, x, y, available_right, available_left, available_down, int x1, x2, y1, y2, x, y, available_right, available_left, available_down,
available_up, popup_width, popup_height; available_up, popup_width, popup_height;
bool cursor_rect, x1_in_bounds, y1_in_bounds, x2_in_bounds, y2_in_bounds; bool cursor_rect, x1_in_bounds, y1_in_bounds, x2_in_bounds, y2_in_bounds;
struct dwl_text_input *text_input = TextInput *text_input =
relay_get_focused_text_input(popup->relay); relaygetfocusedtextinput(popup->relay);
if (!text_input|| !text_input->input->focused_surface) { if (!text_input|| !text_input->input->focused_surface) {
return; return;
} }
@ -2476,7 +2517,7 @@ static void input_popup_update(struct dwl_input_popup *popup) {
focused_surface = text_input->input->focused_surface; focused_surface = text_input->input->focused_surface;
cursor = text_input->input->current.cursor_rectangle; cursor = text_input->input->current.cursor_rectangle;
get_parent_and_output_box(focused_surface, &parent, &output_box); getparentandoutputbox(focused_surface, &parent, &output_box);
if (!cursor_rect) { if (!cursor_rect) {
cursor.x = 0; cursor.x = 0;
@ -2531,22 +2572,28 @@ static void input_popup_update(struct dwl_input_popup *popup) {
} }
} }
static void handle_im_popup_map(struct wl_listener *listener, void *data) { void
struct dwl_input_popup *popup = inputmethodpopupmap(struct wl_listener *listener, void *data)
{
InputPopup *popup =
wl_container_of(listener, popup, popup_map); wl_container_of(listener, popup, popup_map);
input_popup_send_outputs(popup, surface_send_enter_iterator); inputpopupsendoutputs(popup, surfacesendenter);
input_popup_update(popup); updateinputpopup(popup);
} }
static void handle_im_popup_unmap(struct wl_listener *listener, void *data) { void
struct dwl_input_popup *popup = inputmethodpopupunmap(struct wl_listener *listener, void *data)
{
InputPopup *popup =
wl_container_of(listener, popup, popup_unmap); wl_container_of(listener, popup, popup_unmap);
input_popup_send_outputs(popup, surface_send_leave_iterator); inputpopupsendoutputs(popup, surfacesendleave);
input_popup_update(popup); updateinputpopup(popup);
} }
static void handle_im_popup_destroy(struct wl_listener *listener, void *data) { void
struct dwl_input_popup *popup = inputmethodpopupdestroy(struct wl_listener *listener, void *data)
{
InputPopup *popup =
wl_container_of(listener, popup, popup_destroy); wl_container_of(listener, popup, popup_destroy);
wl_list_remove(&popup->focused_surface_unmap.link); wl_list_remove(&popup->focused_surface_unmap.link);
wl_list_remove(&popup->popup_surface_commit.link); wl_list_remove(&popup->popup_surface_commit.link);
@ -2558,56 +2605,64 @@ static void handle_im_popup_destroy(struct wl_listener *listener, void *data) {
free(popup); free(popup);
} }
static void handle_im_popup_surface_commit(struct wl_listener *listener, void
void *data) { inputmethodpopupsurfacecommit(struct wl_listener *listener, void *data)
struct dwl_input_popup *popup = {
InputPopup *popup =
wl_container_of(listener, popup, popup_surface_commit); wl_container_of(listener, popup, popup_surface_commit);
input_popup_update(popup); updateinputpopup(popup);
} }
static void handle_im_focused_surface_destroy( void
struct wl_listener *listener, void *data) { inputmethodfocusedsurfacedestroy(struct wl_listener *listener, void *data)
struct dwl_input_popup *popup = {
InputPopup *popup =
wl_container_of(listener, popup, focused_surface_unmap); wl_container_of(listener, popup, focused_surface_unmap);
wl_list_remove(&popup->view_link); wl_list_remove(&popup->view_link);
wl_list_init(&popup->view_link); wl_list_init(&popup->view_link);
input_popup_update(popup); updateinputpopup(popup);
} }
static void input_popup_set_focus(struct dwl_input_popup *popup, void
struct wlr_surface *surface) { inputpopupsetfocus(InputPopup *popup, struct wlr_surface *surface)
{
Client* client; Client* client;
struct wlr_layer_surface_v1* layer_surface; struct wlr_layer_surface_v1* layer_surface;
LayerSurface* layer; LayerSurface* layer;
if (!surface)
return;
wl_list_remove(&popup->view_link); wl_list_remove(&popup->view_link);
wl_list_remove(&popup->focused_surface_unmap.link); wl_list_remove(&popup->focused_surface_unmap.link);
if (wlr_surface_is_layer_surface(surface)) { if (wlr_surface_is_layer_surface(surface)) {
layer_surface = wlr_layer_surface_v1_from_wlr_surface(surface); layer_surface = wlr_layer_surface_v1_from_wlr_surface(surface);
layer = layer_surface_from_wlr_layer_surface_v1(layer_surface); layer = layer_surface->data;
wl_list_insert(&input_popups, &popup->view_link); wl_list_insert(&input_popups, &popup->view_link);
wl_signal_add(&layer->layer_surface->events.unmap, wl_signal_add(&layer->layer_surface->events.unmap,
&popup->focused_surface_unmap); &popup->focused_surface_unmap);
input_popup_update(popup); updateinputpopup(popup);
return; return;
} }
client = client_from_wlr_surface(surface); client = surface->data;
wl_list_insert(&input_popups, &popup->view_link); wl_list_insert(&input_popups, &popup->view_link);
wl_signal_add(&client->surface.xdg->events.unmap, wl_signal_add(&client->surface.xdg->events.unmap,
&popup->focused_surface_unmap); &popup->focused_surface_unmap);
input_popup_update(popup); updateinputpopup(popup);
} }
static void handle_im_new_popup_surface(struct wl_listener *listener, void *data) { void
struct dwl_text_input* text_input; inputmethodnewpopupsurface(struct wl_listener *listener, void *data)
{
TextInput* text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_new_popup_surface); input_method_new_popup_surface);
struct dwl_input_popup *popup = calloc(1, sizeof(*popup)); InputPopup *popup = calloc(1, sizeof(*popup));
popup->relay = relay; popup->relay = relay;
popup->popup_surface = data; popup->popup_surface = data;
popup->popup_surface->data = popup; popup->popup_surface->data = popup;
@ -2615,39 +2670,40 @@ static void handle_im_new_popup_surface(struct wl_listener *listener, void *data
wl_list_init(&popup->view_link); wl_list_init(&popup->view_link);
wl_signal_add(&popup->popup_surface->events.map, &popup->popup_map); wl_signal_add(&popup->popup_surface->events.map, &popup->popup_map);
popup->popup_map.notify = handle_im_popup_map; popup->popup_map.notify = inputmethodpopupmap;
wl_signal_add( wl_signal_add(
&popup->popup_surface->events.unmap, &popup->popup_unmap); &popup->popup_surface->events.unmap, &popup->popup_unmap);
popup->popup_unmap.notify = handle_im_popup_unmap; popup->popup_unmap.notify = inputmethodpopupunmap;
wl_signal_add( wl_signal_add(
&popup->popup_surface->events.destroy, &popup->popup_destroy); &popup->popup_surface->events.destroy, &popup->popup_destroy);
popup->popup_destroy.notify = handle_im_popup_destroy; popup->popup_destroy.notify = inputmethodpopupdestroy;
wl_signal_add(&popup->popup_surface->surface->events.commit, wl_signal_add(&popup->popup_surface->surface->events.commit,
&popup->popup_surface_commit); &popup->popup_surface_commit);
popup->popup_surface_commit.notify = handle_im_popup_surface_commit; popup->popup_surface_commit.notify = inputmethodpopupsurfacecommit;
wl_list_init(&popup->focused_surface_unmap.link); wl_list_init(&popup->focused_surface_unmap.link);
popup->focused_surface_unmap.notify = handle_im_focused_surface_destroy; popup->focused_surface_unmap.notify = inputmethodfocusedsurfacedestroy;
text_input = relay_get_focused_text_input(relay); text_input = relaygetfocusedtextinput(relay);
if (text_input) { if (text_input) {
input_popup_set_focus(popup, text_input->input->focused_surface); inputpopupsetfocus(popup, text_input->input->focused_surface);
} else { } else {
input_popup_set_focus(popup, NULL); inputpopupsetfocus(popup, NULL);
} }
wl_list_insert(&relay->input_popups, &popup->link); wl_list_insert(&relay->input_popups, &popup->link);
} }
static void relay_handle_input_method(struct wl_listener *listener, void
void *data) { relaycreateinputmethod(struct wl_listener *listener, void *data)
struct dwl_text_input *text_input; {
TextInput *text_input;
struct dwl_input_method_relay *relay = wl_container_of(listener, relay, InputMethodRelay *relay = wl_container_of(listener, relay,
input_method_new); input_method_new);
struct wlr_input_method_v2 *input_method = data; struct wlr_input_method_v2 *input_method = data;
@ -2664,51 +2720,39 @@ static void relay_handle_input_method(struct wl_listener *listener,
relay->input_method = input_method; relay->input_method = input_method;
wl_signal_add(&relay->input_method->events.commit, wl_signal_add(&relay->input_method->events.commit,
&relay->input_method_commit); &relay->input_method_commit);
relay->input_method_commit.notify = handle_im_commit; relay->input_method_commit.notify = inputmethodcommit;
wl_signal_add(&relay->input_method->events.new_popup_surface, wl_signal_add(&relay->input_method->events.new_popup_surface,
&relay->input_method_new_popup_surface); &relay->input_method_new_popup_surface);
relay->input_method_new_popup_surface.notify = handle_im_new_popup_surface; relay->input_method_new_popup_surface.notify = inputmethodnewpopupsurface;
wl_signal_add(&relay->input_method->events.grab_keyboard, wl_signal_add(&relay->input_method->events.grab_keyboard,
&relay->input_method_grab_keyboard); &relay->input_method_grab_keyboard);
relay->input_method_grab_keyboard.notify = handle_im_grab_keyboard; relay->input_method_grab_keyboard.notify = inputmethodgrabkeyboard;
wl_signal_add(&relay->input_method->events.destroy, wl_signal_add(&relay->input_method->events.destroy,
&relay->input_method_destroy); &relay->input_method_destroy);
relay->input_method_destroy.notify = handle_im_destroy; relay->input_method_destroy.notify = inputmethoddestroy;
text_input = relay_get_focusable_text_input(relay); text_input = relaygetfocusabletextinput(relay);
if (text_input) { if (text_input) {
wlr_text_input_v3_send_enter(text_input->input, wlr_text_input_v3_send_enter(text_input->input,
text_input->pending_focused_surface); text_input->pending_focused_surface);
text_input_set_pending_focused_surface(text_input, NULL); textinputsetpendingfocusedsurface(text_input, NULL);
} }
} }
void dwl_input_method_relay_init(struct dwl_input_method_relay *relay) { void
wl_list_init(&relay->text_inputs); inputmethodrelaysetfocus(InputMethodRelay *relay, struct wlr_surface *surface)
wl_list_init(&relay->input_popups); {
TextInput *text_input;
relay->text_input_new.notify = relay_handle_text_input;
wl_signal_add(&text_input_manager->events.text_input,
&relay->text_input_new);
relay->input_method_new.notify = relay_handle_input_method;
wl_signal_add(&input_method_manager->events.input_method,
&relay->input_method_new);
}
void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
struct wlr_surface *surface) {
struct dwl_text_input *text_input;
wl_list_for_each(text_input, &relay->text_inputs, link) { wl_list_for_each(text_input, &relay->text_inputs, link) {
if (text_input->pending_focused_surface) { if (text_input->pending_focused_surface) {
assert(text_input->input->focused_surface == NULL); assert(text_input->input->focused_surface == NULL);
if (surface != text_input->pending_focused_surface) { if (surface != text_input->pending_focused_surface) {
text_input_set_pending_focused_surface(text_input, NULL); textinputsetpendingfocusedsurface(text_input, NULL);
} }
} else if (text_input->input->focused_surface) { } else if (text_input->input->focused_surface) {
assert(text_input->pending_focused_surface == NULL); assert(text_input->pending_focused_surface == NULL);
if (surface != text_input->input->focused_surface) { if (surface != text_input->input->focused_surface) {
relay_disable_text_input(relay, text_input); relaydisabletextinput(relay, text_input);
wlr_text_input_v3_send_leave(text_input->input); wlr_text_input_v3_send_leave(text_input->input);
} else { } else {
wlr_log(WLR_DEBUG, "IM relay set_focus already focused"); wlr_log(WLR_DEBUG, "IM relay set_focus already focused");
@ -2722,7 +2766,7 @@ void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
if (relay->input_method) { if (relay->input_method) {
wlr_text_input_v3_send_enter(text_input->input, surface); wlr_text_input_v3_send_enter(text_input->input, surface);
} else { } else {
text_input_set_pending_focused_surface(text_input, surface); textinputsetpendingfocusedsurface(text_input, surface);
} }
} }
} }
@ -2870,11 +2914,21 @@ setup(void)
presentation = wlr_presentation_create(dpy, backend); presentation = wlr_presentation_create(dpy, backend);
/* create text_input-, and input_method-protocol relevant globals */ /* create text_input-, and input_method-protocol relevant globals */
input_method_manager = wlr_input_method_manager_v2_create(dpy); input_method_mgr = wlr_input_method_manager_v2_create(dpy);
text_input_manager = wlr_text_input_manager_v3_create(dpy); text_input_mgr = wlr_text_input_manager_v3_create(dpy);
input_relay = calloc(1, sizeof(*input_relay)); input_relay = calloc(1, sizeof(*input_relay));
dwl_input_method_relay_init(input_relay);
wl_list_init(&input_relay->text_inputs);
wl_list_init(&input_relay->input_popups);
input_relay->text_input_new.notify = relaycreatetextinput;
wl_signal_add(&text_input_mgr->events.text_input,
&input_relay->text_input_new);
input_relay->input_method_new.notify = relaycreateinputmethod;
wl_signal_add(&input_method_mgr->events.input_method,
&input_relay->input_method_new);
#ifdef XWAYLAND #ifdef XWAYLAND
/* /*