diff --git a/.mailmap b/.mailmap index 911248c..1778cb9 100644 --- a/.mailmap +++ b/.mailmap @@ -1 +1,3 @@ Lennart Jablonka +Leonardo Hernández Hernández +Leonardo Hernández Hernández diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aefd6f..07c9ee4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,22 @@ ## Unreleased ### Added + +* Support for the linux-drm-syncobj-v1 protocol ([wlroots!4715][wlroots!4715], [#685][685]) +* Allow the use of non-system wlroots library ([#646][646]) + +[wlroots!4715]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4715 +[685]: https://codeberg.org/dwl/dwl/pulls/685 +[646]: https://codeberg.org/dwl/dwl/pulls/646 + + ### Changed ### Deprecated ### Removed ### Fixed + +* Crash when a client is created while all outputs are disabled. + ### Security ### Contributors diff --git a/Makefile b/Makefile index 02736d6..d14a70b 100644 --- a/Makefile +++ b/Makefile @@ -6,15 +6,15 @@ include config.mk # flags for compiling DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ -DVERSION=\"$(VERSION)\" $(XWAYLAND) -DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ +DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ -Wfloat-conversion # CFLAGS / LDFLAGS -PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) -DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) +PKGS = wayland-server xkbcommon libinput $(XLIBS) +DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) +LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) all: dwl dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o @@ -68,6 +68,7 @@ dist: clean install: dwl mkdir -p $(DESTDIR)$(PREFIX)/bin + rm -f $(DESTDIR)$(PREFIX)/bin/dwl cp -f dwl $(DESTDIR)$(PREFIX)/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl mkdir -p $(DESTDIR)$(MANDIR)/man1 diff --git a/README.md b/README.md index 90222e6..1bcc36e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # dwl - dwm for Wayland Join us on our IRC channel: [#dwl on Libera Chat] -Or on our [Discord server]. +Or on the community-maintained [Discord server]. dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is intended to fill the same space in the Wayland world that dwm does in X11, diff --git a/client.h b/client.h index c43dbfd..389b4f0 100644 --- a/client.h +++ b/client.h @@ -126,15 +126,14 @@ client_get_appid(Client *c) { #ifdef XWAYLAND if (client_is_x11(c)) - return c->surface.xwayland->class; + return c->surface.xwayland->class ? c->surface.xwayland->class : "broken"; #endif - return c->surface.xdg->toplevel->app_id; + return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id : "broken"; } static inline void client_get_clip(Client *c, struct wlr_box *clip) { - struct wlr_box xdg_geom = {0}; *clip = (struct wlr_box){ .x = 0, .y = 0, @@ -147,9 +146,8 @@ client_get_clip(Client *c, struct wlr_box *clip) return; #endif - wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom); - clip->x = xdg_geom.x; - clip->y = xdg_geom.y; + clip->x = c->surface.xdg->geometry.x; + clip->y = c->surface.xdg->geometry.y; } static inline void @@ -164,7 +162,7 @@ client_get_geometry(Client *c, struct wlr_box *geom) return; } #endif - wlr_xdg_surface_get_geometry(c->surface.xdg, geom); + *geom = c->surface.xdg->geometry; } static inline Client * @@ -200,9 +198,9 @@ client_get_title(Client *c) { #ifdef XWAYLAND if (client_is_x11(c)) - return c->surface.xwayland->title; + return c->surface.xwayland->title ? c->surface.xwayland->title : "broken"; #endif - return c->surface.xdg->toplevel->title; + return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title : "broken"; } static inline int @@ -301,17 +299,6 @@ client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); } -static inline void -client_restack_surface(Client *c) -{ -#ifdef XWAYLAND - if (client_is_x11(c)) - wlr_xwayland_surface_restack(c->surface.xwayland, NULL, - XCB_STACK_MODE_ABOVE); -#endif - return; -} - static inline void client_send_close(Client *c) { @@ -344,6 +331,13 @@ client_set_fullscreen(Client *c, int fullscreen) wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); } +static inline void +client_set_scale(struct wlr_surface *s, float scale) +{ + wlr_fractional_scale_v1_notify_scale(s, scale); + wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); +} + static inline uint32_t client_set_size(Client *c, uint32_t width, uint32_t height) { @@ -364,8 +358,11 @@ static inline void client_set_tiled(Client *c, uint32_t edges) { #ifdef XWAYLAND - if (client_is_x11(c)) + if (client_is_x11(c)) { + wlr_xwayland_surface_set_maximized(c->surface.xwayland, + edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE); return; + } #endif if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { diff --git a/config.mk b/config.mk index 1d5ac38..e2f1816 100644 --- a/config.mk +++ b/config.mk @@ -8,10 +8,29 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man DATADIR = $(PREFIX)/share +WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19` +WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19` + +# Allow using an alternative wlroots installations +# This has to have all the includes required by wlroots, e.g: +# Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build" +#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ +# -I$(PWD)/wlroots/include +# Set -rpath to avoid using the wrong library. +#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19 + +# Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install" +#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ +# -I$(PWD)/wlroots/0.19/include/wlroots-0.19 +#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19 + XWAYLAND = XLIBS = # Uncomment to build XWayland support #XWAYLAND = -DXWAYLAND #XLIBS = xcb xcb-icccm -CC = gcc +# dwl itself only uses C99 features, but wlroots' headers use anonymous unions (C11). +# To avoid warnings about them, we do not use -std=c99 and instead of using the +# gmake default 'CC=c99', we use cc. +CC = cc diff --git a/dwl.c b/dwl.c index 78740df..288afc9 100644 --- a/dwl.c +++ b/dwl.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -106,15 +107,18 @@ typedef struct { typedef struct Monitor Monitor; typedef struct { - /* Must keep these three elements in this order */ + /* Must keep this field first */ unsigned int type; /* XDGShell or X11* */ - struct wlr_box geom; /* layout-relative, includes border */ + Monitor *mon; struct wlr_scene_tree *scene; struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ struct wlr_scene_tree *scene_surface; struct wl_list link; struct wl_list flink; + struct wlr_box geom; /* layout-relative, includes border */ + struct wlr_box prev; /* layout-relative, includes border */ + struct wlr_box bounds; /* only width and height are used */ union { struct wlr_xdg_surface *xdg; struct wlr_xwayland_surface *xwayland; @@ -129,8 +133,6 @@ typedef struct { struct wl_listener fullscreen; struct wl_listener set_decoration_mode; struct wl_listener destroy_decoration; - struct wlr_box prev; /* layout-relative, includes border */ - struct wlr_box bounds; #ifdef XWAYLAND struct wl_listener activate; struct wl_listener associate; @@ -158,7 +160,6 @@ typedef struct { } Key; typedef struct { - struct wl_list link; struct wlr_keyboard_group *wlr_group; int nsyms; @@ -172,9 +173,9 @@ typedef struct { } KeyboardGroup; typedef struct { - /* Must keep these three elements in this order */ + /* Must keep this field first */ unsigned int type; /* LayerShell */ - struct wlr_box geom; + Monitor *mon; struct wlr_scene_tree *scene; struct wlr_scene_tree *popups; @@ -347,7 +348,6 @@ static void setcursor(struct wl_listener *listener, void *data); static void setcursorshape(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); -static void setgamma(struct wl_listener *listener, void *data); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setmon(Client *c, Monitor *m, uint32_t newtags); @@ -382,7 +382,6 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, static void zoom(const Arg *arg); /* variables */ -static const char broken[] = "broken"; static pid_t child_pid = -1; static int locked; static void *exclusive_focus; @@ -410,7 +409,6 @@ static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; static struct wlr_layer_shell_v1 *layer_shell; static struct wlr_output_manager_v1 *output_mgr; -static struct wlr_gamma_control_manager_v1 *gamma_control_mgr; static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; @@ -488,10 +486,8 @@ applyrules(Client *c) Monitor *mon = selmon, *m; c->isfloating = client_is_float_type(c); - if (!(appid = client_get_appid(c))) - appid = broken; - if (!(title = client_get_title(c))) - title = broken; + appid = client_get_appid(c); + title = client_get_title(c); for (r = rules; r < END(rules); r++) { if ((!r->title || strstr(title, r->title)) @@ -562,8 +558,6 @@ arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area); wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y); - l->geom.x = l->scene->node.x; - l->geom.y = l->scene->node.y; } } @@ -657,17 +651,17 @@ buttonpress(struct wl_listener *listener, void *data) break; case WL_POINTER_BUTTON_STATE_RELEASED: /* If you released any buttons, we exit interactive move/resize mode. */ - /* TODO should reset to the pointer focus's current setcursor */ + /* TODO: should reset to the pointer focus's current setcursor */ if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); cursor_mode = CurNormal; /* Drop the window off on its new monitor */ selmon = xytomon(cursor->x, cursor->y); setmon(grabc, selmon, 0); + grabc = NULL; return; - } else { - cursor_mode = CurNormal; } + cursor_mode = CurNormal; break; } /* If the event wasn't handled by the compositor, notify the client with @@ -793,8 +787,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) struct wlr_layer_surface_v1_state old_state; if (l->layer_surface->initial_commit) { - wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale); - wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale)); + client_set_scale(layer_surface->surface, l->mon->wlr_output->scale); /* Temporarily set the layer's current state to pending * so that we can easily arrange it */ @@ -833,19 +826,20 @@ commitnotify(struct wl_listener *listener, void *data) * a wrong monitor. */ applyrules(c); - wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale)); - wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale); + if (c->mon) { + client_set_scale(client_surface(c), c->mon->wlr_output->scale); + } setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */ - wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); - wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); + wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); if (c->decoration) requestdecorationmode(&c->set_decoration_mode, c->decoration); + wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0); return; } - if (client_surface(c)->mapped && c->mon) - resize(c, c->geom, (c->isfloating && !c->isfullscreen)); + resize(c, c->geom, (c->isfloating && !c->isfullscreen)); /* mark a pending resize as completed */ if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) @@ -870,11 +864,13 @@ commitpopup(struct wl_listener *listener, void *data) return; popup->base->surface->data = wlr_scene_xdg_surface_create( popup->parent->data, popup->base); - if ((l && !l->mon) || (c && !c->mon)) + if ((l && !l->mon) || (c && !c->mon)) { + wlr_xdg_popup_destroy(popup); return; + } box = type == LayerShell ? l->mon->m : c->mon->w; - box.x -= (type == LayerShell ? l->geom.x : c->geom.x); - box.y -= (type == LayerShell ? l->geom.y : c->geom.y); + box.x -= (type == LayerShell ? l->scene->node.x : c->geom.x); + box.y -= (type == LayerShell ? l->scene->node.y : c->geom.y); wlr_xdg_popup_unconstrain_from_box(popup, &box); wl_list_remove(&listener->link); } @@ -1130,10 +1126,10 @@ createpointer(struct wlr_pointer *pointer) libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation); if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) - libinput_device_config_scroll_set_method (device, scroll_method); + libinput_device_config_scroll_set_method(device, scroll_method); if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) - libinput_device_config_click_set_method (device, click_method); + libinput_device_config_click_set_method(device, click_method); if (libinput_device_config_send_events_get_modes(device)) { const char *dev_name = libinput_device_get_name(device); @@ -1222,7 +1218,6 @@ void destroydecoration(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, destroy_decoration); - c->decoration = NULL; wl_list_remove(&c->destroy_decoration.link); wl_list_remove(&c->set_decoration_mode.link); @@ -1323,6 +1318,7 @@ destroynotify(struct wl_listener *listener, void *data) wl_list_remove(&c->commit.link); wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); + wl_list_remove(&c->maximize.link); } free(c); } @@ -1620,7 +1616,6 @@ focusclient(Client *c, int lift) wl_list_insert(&fstack, &c->flink); selmon = c->mon; c->isurgent = 0; - client_restack_surface(c); /* Don't change border color if there is an exclusive focus or we are * handling a drag operation */ @@ -1948,7 +1943,8 @@ mapnotify(struct wl_listener *listener, void *data) /* Create scene tree for this client and its border */ c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); - wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell); + /* Enabled later by a call to arrange() */ + wlr_scene_node_set_enabled(&c->scene->node, client_is_unmanaged(c)); c->scene_surface = c->type == XDGShell ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); @@ -1961,6 +1957,7 @@ mapnotify(struct wl_listener *listener, void *data) /* Unmanaged clients always are floating */ wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]); wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + client_set_size(c, c->geom.width, c->geom.height); if (client_wants_focus(c)) { focusclient(c, 1); exclusive_focus = c; @@ -2078,8 +2075,8 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) { c = w; surface = seat->pointer_state.focused_surface; - sx = cursor->x - (l ? l->geom.x : w->geom.x); - sy = cursor->y - (l ? l->geom.y : w->geom.y); + sx = cursor->x - (l ? l->scene->node.x : w->geom.x); + sy = cursor->y - (l ? l->scene->node.y : w->geom.y); } /* time is 0 in internal calls meant to restore pointer focus. */ @@ -2343,6 +2340,7 @@ powermgrsetmode(struct wl_listener *listener, void *data) wlr_output_commit_state(m->wlr_output, &state); m->asleep = !event->mode; + updatemons(NULL, NULL); } void @@ -2359,7 +2357,6 @@ rendermon(struct wl_listener *listener, void *data) Monitor *m = wl_container_of(listener, m, frame); Client *c; struct wlr_output_state pending = {0}; - struct wlr_gamma_control_v1 *gamma_control; struct timespec now; /* Render if no XDG clients have an outstanding resize and are visible on @@ -2369,32 +2366,7 @@ rendermon(struct wl_listener *listener, void *data) goto skip; } - /* - * HACK: The "correct" way to set the gamma is to commit it together with - * the rest of the state in one go, but to do that we would need to rewrite - * wlr_scene_output_commit() in order to add the gamma to the pending - * state before committing, instead try to commit the gamma in one frame, - * and commit the rest of the state in the next one (or in the same frame if - * the gamma can not be committed). - */ - if (m->gamma_lut_changed) { - gamma_control - = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output); - m->gamma_lut_changed = 0; - - if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) - goto commit; - - if (!wlr_output_test_state(m->wlr_output, &pending)) { - wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); - goto commit; - } - wlr_output_commit_state(m->wlr_output, &pending); - wlr_output_schedule_frame(m->wlr_output); - } else { -commit: - wlr_scene_output_commit(m->scene_output, NULL); - } + wlr_scene_output_commit(m->scene_output, NULL); skip: /* Let clients know a frame has been rendered */ @@ -2438,7 +2410,7 @@ resize(Client *c, struct wlr_box geo, int interact) struct wlr_box *bbox; struct wlr_box clip; - if (!c->mon || !c->scene) + if (!c->mon || !client_surface(c)->mapped) return; bbox = interact ? &sgeom : &c->mon->w; @@ -2596,17 +2568,6 @@ setfullscreen(Client *c, int fullscreen) printstatus(); } -void -setgamma(struct wl_listener *listener, void *data) -{ - struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - Monitor *m = event->output->data; - if (!m) - return; - m->gamma_lut_changed = 1; - wlr_output_schedule_frame(m->wlr_output); -} - void setlayout(const Arg *arg) { @@ -2684,7 +2645,7 @@ setsel(struct wl_listener *listener, void *data) void setup(void) { - int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; + int drm_fd, i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; sigemptyset(&sa.sa_mask); @@ -2734,6 +2695,10 @@ setup(void) wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw)); } + if ((drm_fd = wlr_renderer_get_drm_fd(drw)) >= 0 && drw->features.timeline + && backend->features.timeline) + wlr_linux_drm_syncobj_manager_v1_create(dpy, 1, drm_fd); + /* Autocreates an allocator for us. * The allocator is the bridge between the renderer and the backend. It * handles the buffer creation, allowing wlroots to render onto the @@ -2757,15 +2722,14 @@ setup(void) wlr_viewporter_create(dpy); wlr_single_pixel_buffer_manager_v1_create(dpy); wlr_fractional_scale_manager_v1_create(dpy, 1); - wlr_presentation_create(dpy, backend); + wlr_presentation_create(dpy, backend, 2); wlr_alpha_modifier_v1_create(dpy); /* Initializes the interface used to implement urgency hints */ activation = wlr_xdg_activation_v1_create(dpy); LISTEN_STATIC(&activation->events.request_activate, urgent); - gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy); - LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma); + wlr_scene_set_gamma_control_manager_v1(scene, wlr_gamma_control_manager_v1_create(dpy)); power_mgr = wlr_output_power_manager_v1_create(dpy); LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode); @@ -3260,11 +3224,11 @@ void virtualpointer(struct wl_listener *listener, void *data) { struct wlr_virtual_pointer_v1_new_pointer_event *event = data; - struct wlr_pointer pointer = event->new_pointer->pointer; + struct wlr_input_device *device = &event->new_pointer->pointer.base; - wlr_cursor_attach_input_device(cursor, &pointer.base); + wlr_cursor_attach_input_device(cursor, device); if (event->suggested_output) - wlr_cursor_map_input_to_output(cursor, &pointer.base, event->suggested_output); + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); } Monitor * @@ -3363,17 +3327,24 @@ configurex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, configure); struct wlr_xwayland_surface_configure_event *event = data; - /* TODO: figure out if there is another way to do this */ - if (!c->mon) { + if (!client_surface(c) || !client_surface(c)->mapped) { wlr_xwayland_surface_configure(c->surface.xwayland, event->x, event->y, event->width, event->height); return; } - if (c->isfloating || client_is_unmanaged(c)) - resize(c, (struct wlr_box){.x = event->x, .y = event->y, - .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0); - else + if (client_is_unmanaged(c)) { + wlr_scene_node_set_position(&c->scene->node, event->x, event->y); + wlr_xwayland_surface_configure(c->surface.xwayland, + event->x, event->y, event->width, event->height); + return; + } + if ((c->isfloating && c != grabc) || !c->mon->lt[c->mon->sellt]->arrange) { + resize(c, (struct wlr_box){.x = event->x - c->bw, + .y = event->y - c->bw, .width = event->width + c->bw * 2, + .height = event->height + c->bw * 2}, 0); + } else { arrange(c->mon); + } } void diff --git a/util.c b/util.c index 51130af..b925987 100644 --- a/util.c +++ b/util.c @@ -38,14 +38,14 @@ ecalloc(size_t nmemb, size_t size) int fd_set_nonblock(int fd) { int flags = fcntl(fd, F_GETFL); - if (flags < 0) { + if (flags < 0) { perror("fcntl(F_GETFL):"); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { perror("fcntl(F_SETFL):"); return -1; - } + } return 0; }