Merge remote-tracking branch 'upstream/main' into wlroots-next

This commit is contained in:
Leonardo Hernández Hernández 2022-12-05 23:43:47 -06:00
commit b5229636a3
No known key found for this signature in database
GPG key ID: E538897EE11B9624
5 changed files with 137 additions and 136 deletions

166
client.h
View file

@ -16,40 +16,6 @@ client_is_x11(Client *c)
#endif #endif
} }
static inline Client *
client_from_wlr_surface(struct wlr_surface *s)
{
struct wlr_xdg_surface *surface;
#ifdef XWAYLAND
struct wlr_xwayland_surface *xsurface;
if (s && wlr_surface_is_xwayland_surface(s)
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(s)))
return xsurface->data;
#endif
if (s && wlr_surface_is_xdg_surface(s)
&& (surface = wlr_xdg_surface_from_wlr_surface(s))
&& surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return surface->data;
if (s && wlr_surface_is_subsurface(s))
return client_from_wlr_surface(wlr_surface_get_root_surface(s));
return NULL;
}
static inline Client *
client_get_parent(Client *c)
{
#ifdef XWAYLAND
if (client_is_x11(c) && c->surface.xwayland->parent)
return client_from_wlr_surface(c->surface.xwayland->parent->surface);
#endif
if (c->surface.xdg->toplevel->parent)
return client_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface);
return NULL;
}
static inline void static inline void
client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min) client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min)
{ {
@ -85,6 +51,69 @@ client_surface(Client *c)
return c->surface.xdg->surface; return c->surface.xdg->surface;
} }
static inline int
toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
{
struct wlr_xdg_surface *xdg_surface;
struct wlr_surface *root_surface;
struct wlr_layer_surface_v1 *layer_surface;
Client *c = NULL;
LayerSurface *l = NULL;
int type = -1;
#ifdef XWAYLAND
struct wlr_xwayland_surface *xsurface;
#endif
if (!s)
return type;
root_surface = wlr_surface_get_root_surface(s);
#ifdef XWAYLAND
if (wlr_surface_is_xwayland_surface(root_surface)
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) {
c = xsurface->data;
type = c->type;
goto end;
}
#endif
if (wlr_surface_is_layer_surface(root_surface)
&& (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) {
l = layer_surface->data;
type = LayerShell;
goto end;
}
if (wlr_surface_is_xdg_surface(root_surface)
&& (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) {
while (1) {
switch (xdg_surface->role) {
case WLR_XDG_SURFACE_ROLE_POPUP:
if (!xdg_surface->popup->parent)
return -1;
else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent))
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent);
break;
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
c = xdg_surface->data;
type = c->type;
goto end;
case WLR_XDG_SURFACE_ROLE_NONE:
return -1;
}
}
}
end:
if (pl)
*pl = l;
if (pc)
*pc = c;
return type;
}
/* The others */ /* The others */
static inline void static inline void
client_activate_surface(struct wlr_surface *s, int activated) client_activate_surface(struct wlr_surface *s, int activated)
@ -153,6 +182,20 @@ client_get_geometry(Client *c, struct wlr_box *geom)
wlr_xdg_surface_get_geometry(c->surface.xdg, geom); wlr_xdg_surface_get_geometry(c->surface.xdg, geom);
} }
static inline Client *
client_get_parent(Client *c)
{
Client *p = NULL;
#ifdef XWAYLAND
if (client_is_x11(c) && c->surface.xwayland->parent)
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL);
#endif
if (c->surface.xdg->toplevel->parent)
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
return p;
}
static inline const char * static inline const char *
client_get_title(Client *c) client_get_title(Client *c)
{ {
@ -197,6 +240,21 @@ client_is_mapped(Client *c)
return c->surface.xdg->mapped; return c->surface.xdg->mapped;
} }
static inline int
client_is_rendered_on_mon(Client *c, Monitor *m)
{
/* This is needed for when you don't want to check formal assignment,
* but rather actual displaying of the pixels.
* Usually VISIBLEON suffices and is also faster. */
struct wlr_surface_output *s;
if (!c->scene->node.enabled)
return 0;
wl_list_for_each(s, &client_surface(c)->current_outputs, link)
if (s->output == m->wlr_output)
return 1;
return 0;
}
static inline int static inline int
client_is_unmanaged(Client *c) client_is_unmanaged(Client *c)
{ {
@ -305,43 +363,3 @@ client_wants_fullscreen(Client *c)
#endif #endif
return c->surface.xdg->toplevel->requested.fullscreen; return c->surface.xdg->toplevel->requested.fullscreen;
} }
static inline void *
toplevel_from_popup(struct wlr_xdg_popup *popup)
{
struct wlr_xdg_surface *surface = popup->base;
while (1) {
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_POPUP:
if (!surface->popup->parent)
return NULL;
else if (wlr_surface_is_layer_surface(surface->popup->parent))
return wlr_layer_surface_v1_from_wlr_surface(surface->popup->parent)->data;
else if (!wlr_surface_is_xdg_surface(surface->popup->parent))
return NULL;
surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent);
break;
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
return surface->data;
case WLR_XDG_SURFACE_ROLE_NONE:
return NULL;
}
}
}
static inline void *
toplevel_from_wlr_layer_surface(struct wlr_surface *s)
{
Client *c;
struct wlr_layer_surface_v1 *wlr_layer_surface;
if ((c = client_from_wlr_surface(s)))
return c;
else if (s && wlr_surface_is_layer_surface(s)
&& (wlr_layer_surface = wlr_layer_surface_v1_from_wlr_surface(s)))
return wlr_layer_surface->data;
return NULL;
}

View file

@ -85,6 +85,11 @@ LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
*/ */
static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
static const double accel_speed = 0.0; static const double accel_speed = 0.0;
/* You can choose between:
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
*/
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT #define MODKEY WLR_MODIFIER_ALT

View file

@ -1,4 +1,4 @@
_VERSION = 0.4-rc1 _VERSION = 0.4-rc2
VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_VERSION)` VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config

4
dwl.1
View file

@ -51,7 +51,7 @@ Spawn
.Nm bemenu-run . .Nm bemenu-run .
.It Mod-Shift-Return .It Mod-Shift-Return
Spawn Spawn
.Nm alacritty . .Nm foot .
.It Mod-[jk] .It Mod-[jk]
Move focus down/up the stack. Move focus down/up the stack.
.It Mod-[id] .It Mod-[id]
@ -135,7 +135,7 @@ Start
with s6 in the background: with s6 in the background:
.Dl dwl -s 's6-svscan <&-' .Dl dwl -s 's6-svscan <&-'
.Sh SEE ALSO .Sh SEE ALSO
.Xr alacritty 1 , .Xr foot 1 ,
.Xr bemenu 1 , .Xr bemenu 1 ,
.Xr dwm 1 , .Xr dwm 1 ,
.Xr xkeyboard-config 7 .Xr xkeyboard-config 7

96
dwl.c
View file

@ -183,7 +183,6 @@ struct Monitor {
unsigned int tagset[2]; unsigned int tagset[2];
double mfact; double mfact;
int nmaster; int nmaster;
int un_map; /* If a map/unmap happened on this monitor, then this should be true */
}; };
typedef struct { typedef struct {
@ -600,8 +599,9 @@ checkidleinhibitor(struct wlr_surface *exclude)
int inhibited = 0; int inhibited = 0;
struct wlr_idle_inhibitor_v1 *inhibitor; struct wlr_idle_inhibitor_v1 *inhibitor;
wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
struct wlr_scene_tree *tree = inhibitor->surface->data; struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface);
if (bypass_surface_visibility || (exclude != inhibitor->surface struct wlr_scene_tree *tree = surface->data;
if (bypass_surface_visibility || (exclude != surface
&& tree->node.enabled)) { && tree->node.enabled)) {
inhibited = 1; inhibited = 1;
break; break;
@ -733,14 +733,9 @@ commitnotify(struct wl_listener *listener, void *data)
struct wlr_box box = {0}; struct wlr_box box = {0};
client_get_geometry(c, &box); client_get_geometry(c, &box);
if (c->mon && !wlr_box_empty(&box) && (box.width != c->geom.width - 2 * c->bw
|| box.height != c->geom.height - 2 * c->bw))
arrange(c->mon);
/* mark a pending resize as completed */ /* mark a pending resize as completed */
if (c->resize && (c->resize <= c->surface.xdg->current.configure_serial if (c->resize && (c->resize <= c->surface.xdg->current.configure_serial))
|| (c->surface.xdg->current.geometry.width == c->surface.xdg->pending.geometry.width
&& c->surface.xdg->current.geometry.height == c->surface.xdg->pending.geometry.height)))
c->resize = 0; c->resize = 0;
} }
@ -914,22 +909,21 @@ createnotify(struct wl_listener *listener, void *data)
* If you want to do something tricky with popups you should check if * If you want to do something tricky with popups you should check if
* its parent is wlr_xdg_shell or wlr_layer_shell */ * its parent is wlr_xdg_shell or wlr_layer_shell */
struct wlr_xdg_surface *xdg_surface = data; struct wlr_xdg_surface *xdg_surface = data;
Client *c; Client *c = NULL;
LayerSurface *l = NULL;
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
struct wlr_box box; struct wlr_box box;
LayerSurface *l = toplevel_from_popup(xdg_surface->popup); int type = toplevel_from_wlr_surface(xdg_surface->surface, &c, &l);
if (!xdg_surface->popup->parent) if (!xdg_surface->popup->parent)
return; return;
xdg_surface->surface->data = wlr_scene_xdg_surface_create( xdg_surface->surface->data = wlr_scene_xdg_surface_create(
xdg_surface->popup->parent->data, xdg_surface); xdg_surface->popup->parent->data, xdg_surface);
/* Probably the check of `l` is useless, the only thing that can be NULL if ((!l || !l->mon) || (!c || !c->mon))
* is its monitor */
if (!l || !l->mon)
return; return;
box = l->type == LayerShell ? l->mon->m : l->mon->w; box = type == LayerShell ? l->mon->m : c->mon->w;
box.x -= l->geom.x; box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
box.y -= l->geom.y; box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box); wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box);
return; return;
} else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE) } else if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_NONE)
@ -961,6 +955,7 @@ createpointer(struct wlr_pointer *pointer)
libinput_device_config_tap_set_enabled(libinput_device, tap_to_click); libinput_device_config_tap_set_enabled(libinput_device, tap_to_click);
libinput_device_config_tap_set_drag_enabled(libinput_device, tap_and_drag); libinput_device_config_tap_set_drag_enabled(libinput_device, tap_and_drag);
libinput_device_config_tap_set_drag_lock_enabled(libinput_device, drag_lock); libinput_device_config_tap_set_drag_lock_enabled(libinput_device, drag_lock);
libinput_device_config_tap_set_button_map(libinput_device, button_map);
} }
if (libinput_device_config_scroll_has_natural_scroll(libinput_device)) if (libinput_device_config_scroll_has_natural_scroll(libinput_device))
@ -1017,7 +1012,7 @@ destroyidleinhibitor(struct wl_listener *listener, void *data)
{ {
/* `data` is the wlr_surface of the idle inhibitor being destroyed, /* `data` is the wlr_surface of the idle inhibitor being destroyed,
* at this point the idle inhibitor is still in the list of the manager */ * at this point the idle inhibitor is still in the list of the manager */
checkidleinhibitor(data); checkidleinhibitor(wlr_surface_get_root_surface(data));
} }
void void
@ -1103,15 +1098,12 @@ focusclient(Client *c, int lift)
/* 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. */
Client *w = client_from_wlr_surface(old); Client *w = NULL;
if (wlr_surface_is_layer_surface(old)) { LayerSurface *l = NULL;
struct wlr_layer_surface_v1 *wlr_layer_surface = int type = toplevel_from_wlr_surface(old, &w, &l);
wlr_layer_surface_v1_from_wlr_surface(old); if (type == LayerShell && l->scene->node.enabled
&& l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
if (wlr_layer_surface && ((LayerSurface *)wlr_layer_surface->data)->mapped return;
&& (wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP
|| wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY))
return;
} else if (w && w == exclusive_focus && client_wants_focus(w)) { } else if (w && w == exclusive_focus && client_wants_focus(w)) {
return; return;
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
@ -1368,7 +1360,6 @@ mapnotify(struct wl_listener *listener, void *data)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, bordercolor); c->border[i] = wlr_scene_rect_create(c->scene, 0, 0, bordercolor);
c->border[i]->node.data = c; c->border[i]->node.data = c;
wlr_scene_rect_set_color(c->border[i], bordercolor);
} }
/* Initialize client geometry with room for border */ /* Initialize client geometry with room for border */
@ -1395,8 +1386,6 @@ mapnotify(struct wl_listener *listener, void *data)
} }
printstatus(); printstatus();
c->mon->un_map = 1;
unset_fullscreen: unset_fullscreen:
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
wl_list_for_each(w, &clients, link) wl_list_for_each(w, &clients, link)
@ -1448,8 +1437,9 @@ void
motionnotify(uint32_t time) motionnotify(uint32_t time)
{ {
double sx = 0, sy = 0; double sx = 0, sy = 0;
Client *c = NULL; Client *c = NULL, *w = NULL;
LayerSurface *l; LayerSurface *l = NULL;
int type;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
struct wlr_drag_icon *icon; struct wlr_drag_icon *icon;
@ -1482,11 +1472,12 @@ motionnotify(uint32_t time)
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy); xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
if (cursor_mode == CurPressed && !seat->drag) { if (cursor_mode == CurPressed && !seat->drag) {
if ((l = toplevel_from_wlr_layer_surface( if ((type = toplevel_from_wlr_surface(
seat->pointer_state.focused_surface))) { seat->pointer_state.focused_surface, &w, &l)) >= 0) {
c = w;
surface = seat->pointer_state.focused_surface; surface = seat->pointer_state.focused_surface;
sx = cursor->x - l->geom.x; sx = cursor->x - (type == LayerShell ? l->geom.x : w->geom.x);
sy = cursor->y - l->geom.y; sy = cursor->y - (type == LayerShell ? l->geom.y : w->geom.y);
} }
} }
@ -1695,30 +1686,19 @@ rendermon(struct wl_listener *listener, void *data)
* generally at the output's refresh rate (e.g. 60Hz). */ * generally at the output's refresh rate (e.g. 60Hz). */
Monitor *m = wl_container_of(listener, m, frame); Monitor *m = wl_container_of(listener, m, frame);
Client *c; Client *c;
int skip = 0;
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
/* Render if no XDG clients have an outstanding resize and are visible on /* Render if no XDG clients have an outstanding resize and are visible on
* this monitor. */ * this monitor. */
/* Checking m->un_map for every client is not optimal but works */ wl_list_for_each(c, &clients, link)
wl_list_for_each(c, &clients, link) { if (client_is_rendered_on_mon(c, m) && (!c->isfloating && c->resize))
if ((c->resize && m->un_map) || (c->type == XDGShell goto skip;
&& (c->surface.xdg->pending.geometry.width != if (!wlr_scene_output_commit(m->scene_output))
c->surface.xdg->current.geometry.width
|| c->surface.xdg->pending.geometry.height !=
c->surface.xdg->current.geometry.height))) {
/* Lie */
wlr_surface_send_frame_done(client_surface(c), &now);
skip = 1;
}
}
if (!skip && !wlr_scene_output_commit(m->scene_output))
return; return;
skip:
/* Let clients know a frame has been rendered */ /* Let clients know a frame has been rendered */
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(m->scene_output, &now); wlr_scene_output_send_frame_done(m->scene_output, &now);
m->un_map = 0;
} }
void void
@ -2291,9 +2271,6 @@ unmapnotify(struct wl_listener *listener, void *data)
grabc = NULL; grabc = NULL;
} }
if (c->mon)
c->mon->un_map = 1;
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
if (c == exclusive_focus) if (c == exclusive_focus)
exclusive_focus = NULL; exclusive_focus = NULL;
@ -2389,8 +2366,9 @@ void
urgent(struct wl_listener *listener, void *data) urgent(struct wl_listener *listener, void *data)
{ {
struct wlr_xdg_activation_v1_request_activate_event *event = data; struct wlr_xdg_activation_v1_request_activate_event *event = data;
Client *c = client_from_wlr_surface(event->surface); Client *c = NULL;
if (c && c != selclient()) { int type = toplevel_from_wlr_surface(event->surface, &c, NULL);
if (type >= 0 && type != LayerShell && c != selclient()) {
c->isurgent = 1; c->isurgent = 1;
printstatus(); printstatus();
} }
@ -2575,7 +2553,7 @@ sigchld(int unused)
* XWayland process * XWayland process
*/ */
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
&& in.si_pid != xwayland->server->pid) && (!xwayland || in.si_pid != xwayland->server->pid))
waitpid(in.si_pid, NULL, 0); waitpid(in.si_pid, NULL, 0);
} }