3 Commits
Author SHA1 Message Date
julmajustus d16036e690 Fix input_method_relay double allocation
- input_method_relay is allocated inside input_method_relay_create(), which leads the extra allocation to leak memory.
2026-09-18 22:09:39 +03:00
save196 45054a34a4 always apply a minimum size of 1x1
Resizing with the mouse can make the size negative, which makes dwl
crash, and the minimum is 1 because 0 makes some X11 clients crash.
2026-09-18 10:37:27 +02:00
save196 669b26d0a9 let the focus leave an unmanaged surface
Unmanaged clients spawned by a parent window, like menus, would not
close if the user changed workspace or focused another client while the
menu was selected, because the parent was never told that it lost the
focus. This remembers the last managed client and deactivates it on a
focus change, so that it closes the menu itself.

This also fixes a regression introduced by f6e3a28, where menus would
close immediately after being opened.
2026-09-18 09:17:40 +02:00
+23 -12
View File
@@ -377,6 +377,7 @@ static void zoom(const Arg *arg);
static pid_t child_pid = -1; static pid_t child_pid = -1;
static int locked; static int locked;
static void *exclusive_focus; static void *exclusive_focus;
static Client *focused_client;
static struct wl_display *dpy; static struct wl_display *dpy;
static struct wl_event_loop *event_loop; static struct wl_event_loop *event_loop;
static struct wlr_backend *backend; static struct wlr_backend *backend;
@@ -487,6 +488,10 @@ static struct wlr_xwayland *xwayland;
void void
applybounds(Client *c, struct wlr_box *bbox) applybounds(Client *c, struct wlr_box *bbox)
{ {
/* set minimum client size to 1 */
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
if (!c->isfullscreen) { if (!c->isfullscreen) {
struct wlr_box min = {0}, max = {0}; struct wlr_box min = {0}, max = {0};
client_get_size_hints(c, &max, &min); client_get_size_hints(c, &max, &min);
@@ -1523,6 +1528,9 @@ focusclient(Client *c, int lift)
wlr_xdg_popup_destroy(popup); wlr_xdg_popup_destroy(popup);
} }
if (old_c && old_c == exclusive_focus && client_wants_focus(old_c))
exclusive_focus = NULL;
/* Put the new client atop the focus stack and select its monitor */ /* Put the new client atop the focus stack and select its monitor */
if (c && !client_is_unmanaged(c)) { if (c && !client_is_unmanaged(c)) {
wl_list_remove(&c->flink); wl_list_remove(&c->flink);
@@ -1536,24 +1544,23 @@ focusclient(Client *c, int lift)
client_set_border_color(c, focuscolor); client_set_border_color(c, focuscolor);
} }
/* Deactivate old client if focus is changing */
if (old && (!c || client_surface(c) != old)) {
/* If an overlay is focused, don't focus or activate the client, /* If an overlay is focused, don't focus or activate the client,
* but only update its position in fstack to render its border with focuscolor * but only update its position in fstack to render its border with focuscolor
* and focus it after the overlay is closed. */ * and focus it after the overlay is closed. */
if (old_client_type == LayerShell && wlr_scene_node_coords( if (old && (!c || client_surface(c) != old)
&& old_client_type == LayerShell && wlr_scene_node_coords(
&old_l->scene->node, &unused_lx, &unused_ly) &old_l->scene->node, &unused_lx, &unused_ly)
&& old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP
&& old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { && old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
return; return;
} else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
return;
} else if (old_c && !client_is_unmanaged(old_c)) {
if (c && !client_is_unmanaged(c))
client_set_border_color(old_c, bordercolor);
client_activate_surface(old, 0); if (focused_client && focused_client != c && !(c && client_is_unmanaged(c))) {
} struct wlr_surface *s = client_surface(focused_client);
if (c)
client_set_border_color(focused_client, bordercolor);
if (s && s->mapped)
client_activate_surface(s, 0);
focused_client = NULL;
} }
printstatus(); printstatus();
@@ -1574,6 +1581,9 @@ focusclient(Client *c, int lift)
/* Activate the new client */ /* Activate the new client */
client_activate_surface(client_surface(c), 1); client_activate_surface(client_surface(c), 1);
if (!client_is_unmanaged(c))
focused_client = c;
} }
void void
@@ -2804,7 +2814,6 @@ setup(void)
input_method_manager = wlr_input_method_manager_v2_create(dpy); input_method_manager = wlr_input_method_manager_v2_create(dpy);
text_input_manager = wlr_text_input_manager_v3_create(dpy); text_input_manager = wlr_text_input_manager_v3_create(dpy);
input_method_relay = ecalloc(1, sizeof(*input_method_relay));
input_method_relay = input_method_relay_create(); input_method_relay = input_method_relay_create();
/* Make sure XWayland clients don't connect to the parent X server, /* Make sure XWayland clients don't connect to the parent X server,
@@ -2980,6 +2989,8 @@ unmapnotify(struct wl_listener *listener, void *data)
cursor_mode = CurNormal; cursor_mode = CurNormal;
grabc = NULL; grabc = NULL;
} }
if (c == focused_client)
focused_client = NULL;
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
if (c == exclusive_focus) { if (c == exclusive_focus) {