63 Commits

Author SHA1 Message Date
Leonardo Hernández Hernández 31d8a67eda use level 0 keysyms
this allow do not have to change the keysym when WLR_MODIFIER_SHIFT is active
2022-07-23 17:48:59 -05:00
Leonardo Hernández Hernández b04c73be3d make sure we do not create a double fullscreen_bg
and also make sure we do not destroy it if it does not exist
Fixes: #274
2022-07-23 13:28:15 -05:00
Leonardo Hernández Hernández 8cdb997126 conform the xdg-protocol with fullscreen translucent clients
see `setfullscreen()` for more info
2022-07-23 02:17:00 -05:00
Leonardo Hernández Hernández 90a12c90a0 always set the same monitor and tags for child clients of a client
fixes #272
2022-07-19 20:13:56 -05:00
Leonardo Hernández Hernández e082292606 do not focus clients if a layer surface is focused 2022-07-19 12:24:24 -05:00
Dima Krasner deb48ff48b force line-buffered stdout if stdout is not a tty 2022-07-19 12:18:16 -05:00
Leonardo Hernández Hernández c70db2d06a Revert "only call wlr_seat_keyboard_notify_enter() if a keyboard is found"
This reverts commit 8e03bce621.
fixes #270
2022-07-19 11:52:42 -05:00
Leonardo Hernández Hernández e98719f552 remove a useless check
if `s->role_data == NULL`, wlr_*_surface_from_wlr_surface() will return NULL
and we are checking it
2022-07-15 00:48:28 -05:00
David-Valters af12e777f2 Update README.md 2022-07-13 20:19:43 -05:00
Leonardo Hernández Hernández 8e03bce621 only call wlr_seat_keyboard_notify_enter() if a keyboard is found 2022-07-07 00:21:51 -05:00
Leonardo Hernández Hernández 87fc3a58ab check pointer focus in arrange() 2022-07-06 23:48:53 -05:00
Leonardo Hernández Hernández 0eff78d6c2 include DWLCFLAGS into linking step 2022-07-06 23:41:42 -05:00
Leonardo Hernández Hernández c6d97f1db7 arrange client's monitor if size has change since last commit 2022-07-06 22:20:21 -05:00
Leonardo Hernández Hernández 829dec6598 resize now takes struct wlr_box as parameter 2022-07-06 22:18:46 -05:00
Leonardo Hernández Hernández ff70337c16 check current and pending geometry to set c->resize to zero
Fixes #260
2022-07-06 22:16:00 -05:00
Ben Jargowsky 7cc6c640e2 Checks for overflows for client max width and height 2022-06-29 00:35:06 +02:00
Leonardo Hernández Hernández 72e0a560d9 respect size hints 2022-06-24 19:19:20 -05:00
Leonardo Hernández Hernández 2aa391361c inline unmaplayersurface() into unmaplayersurfacenotify()
unmap signal is guaranted to be emitted before destroy signal
so is useless checking if it is mapped at destroy
2022-06-24 15:36:13 -05:00
Leonardo Hernández Hernández 549335ae54 avoid layer surface popups appearing below x{dg,wayland} clients 2022-06-24 14:46:08 -05:00
Leonardo Hernández Hernández 097b4a30f5 unconstrain layer shell popups from monitor size
unconstrain other popups from monitor usable area
2022-06-24 14:30:52 -05:00
Leonardo Hernández Hernández c1578bc14d use LayerSurface.mon when possible 2022-06-21 16:03:20 -05:00
Leonardo Hernández Hernández 9b84940e37 unconstrain layer shell popups
also unconstrain popups from monitor's usable area
2022-06-21 00:23:21 -05:00
Leonardo Hernández Hernández 79ad72413d don't set c->isfullscreen to zero
calloc initializes all fields to zero
2022-06-20 18:05:16 -05:00
Sevz 74fce9d918 Merge pull request #257 from fauxmight/bar_options
Add known dwl status bar options to README
2022-06-18 13:00:08 -05:00
A Frederick Christensen 553ba5b7c8 Add known dwl tag status bar options to README.md 2022-06-18 03:04:00 -05:00
Leonardo Hernández Hernández 4ae6d0f387 move ugglyness to client.h 2022-06-16 15:54:13 -05:00
Leonardo Hernández Hernández 2ef5abfb72 remove unneeded check in focusclient() 2022-06-16 15:36:27 -05:00
Sevz 8076b47cc6 Merge pull request #251 from gwnichol/fixinstall
Fix make install while files are in use
2022-06-14 15:43:09 -05:00
Sevz 3a77f02919 Merge pull request #247 from Humm42/xkboptions
initialize xkb_rules.options to a null pointer
2022-06-14 15:42:47 -05:00
Leonardo Hernández Hernández d26ddfc7fd kill child process in cleanup() 2022-06-14 15:31:39 -05:00
Grant Nichol 671a9b450b Fix make install while files are in use
When the dwl executable is in use, cp fails without the -f flag.

POSIX defines this flag with:
> If a file descriptor for a destination file cannot be obtained,
> as described in step 3.a.ii., attempt to unlink the destination
> file and proceed.
2022-06-12 15:58:38 -05:00
Leonardo Hernández Hernández 583f471cfe add some blank lines 2022-06-10 12:32:22 -05:00
Marco Siedentopf 8bce3b1583 add click method configuration option
Add the libinput configuration option to choose between Software Button Areas and Clickfinger
2022-06-10 12:27:40 -05:00
Leonardo Hernández Hernández c008bf2a7d add $(LIBS) to $(LDLIBS) 2022-06-10 12:21:23 -05:00
Dima Krasner c990dbd441 fix link failure with --as-needed 2022-06-10 19:26:45 +03:00
Leonardo Hernández Hernández d969289baf use LDFLAGS to build dwl target 2022-06-06 23:36:45 -05:00
Leonardo Hernández Hernández 50b6630f3d do not generate *-protocol.{c,o}
according with
https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/62fbf3f4ba1b2993e29dfb46f077e5806f7aac1c
they are unused and wlroots-based compositors don't need to do this
2022-06-06 22:54:40 -05:00
Leonardo Hernández Hernández 14641560b0 include xcb only when building with xwayland support 2022-06-06 22:53:36 -05:00
KawaiiAmber 7b42232ad1 convert makefile to be more portable 2022-06-06 22:53:36 -05:00
Leonardo Hernández Hernández a5a0674f6a improve client_from_wlr_surface() 2022-06-06 22:51:58 -05:00
Leonardo Hernández Hernández 4dfa45659a fix compiler error with gcc complaining about parentheses
dwl.c: In function ‘unmaplayersurface’:
dwl.c:2253:9: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
 2253 |         layersurface->layer_surface->mapped = layersurface->mapped = 0;
      |         ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [<builtin>: dwl.o] Error 1

clang not affected
2022-06-05 16:57:20 -05:00
Leonardo Hernández Hernández b91017e713 disable scene node at unmaplayersurface() 2022-06-05 15:27:40 -05:00
Lennart Jablonka 70da04a714 initialize xkb_rules.options to a null pointer
Initializing it to an empty string had broken configuring xkbcommon
through the environment (XKB_DEFAULT_OPTIONS).

Fixes: ae31391115 ("initialize rules and xkb_rules")
2022-06-03 01:23:35 +02:00
Leonardo Hernández Hernández 2623a96ebf call client_set-size() if client has a resize 2022-05-27 00:19:17 -05:00
Leonardo Hernández Hernández 52e0d00942 check client_surface() returning NULL
now client_surface()->data is a pointer to the wlr_scene_tree of clients
which allows us to not call wlr_scene_node_lower_to_bottom() for every clients
2022-05-25 17:12:44 -05:00
Leonardo Hernández Hernández 7018b9b65c correct libinput function name for drag_lock 2022-05-25 15:01:38 -05:00
Leonardo Hernández Hernández 48ec914f43 destroy layersurface's scene node in destroylayersurfacenotify() 2022-05-25 14:49:32 -05:00
Leonardo Hernández Hernández 40449fa64f add a new function to get a client from a wlr_surface 2022-05-23 10:55:28 -05:00
Ben Jargowsky ecbc2c61db Add configuration options for touchpads 2022-05-23 00:01:47 +02:00
Leonardo Hernández Hernández 8870ba0bb8 implement urgency hints for xwayland clients 2022-05-17 14:38:18 -05:00
Leonardo Hernández Hernández 5de68ba713 sync manpage and help info
Signed-off-by: Leonardo Hernández Hernández <leohdz172@protonmail.com>
2022-05-17 13:26:57 -05:00
Ben Jargowsky 2f8736b986 Check if XWayland client size_hints are NULL 2022-05-15 23:09:21 +02:00
Leonardo Hernández Hernández 3c11ad9aa6 fix segfault when dragging chromium tabs 2022-05-14 00:29:35 -05:00
Ben Jargowsky 06d9230a96 Run focusclient when switching to monocle layout 2022-05-13 10:20:28 +02:00
Leonardo Hernández Hernández 22bd75226b remove trailing whitespaces 2022-05-10 11:42:40 -05:00
Leonardo Hernández Hernández 063736f898 add -v flag to the manpage
Thanks @Humm42
2022-05-10 11:39:33 -05:00
Leonardo Hernández Hernández d5a741c9b4 add dist target 2022-05-09 16:25:03 -05:00
Leonardo Hernández Hernández 5d8084daa7 add flag to print version and exit 2022-05-09 16:24:36 -05:00
Sevz 07d56c6d7b Merge pull request #230 from BenJarg/null-wlr_seat_get_keyboard
Handle 'wlr_seat_get_keyboard' possibly returning null.
2022-05-09 13:18:19 -05:00
Ben Jargowsky e0d310fd84 Handle 'wlr_seat_get_keyboard' possibly returning null. 2022-05-09 14:00:21 +02:00
Leonardo Hernández Hernández 3a4b7d104f restack xwayland surface on focusclient() 2022-04-29 17:45:02 -05:00
Ben Jargowsky d071a899f3 Run printstatus() when a monitor is removed 2022-04-25 13:50:53 -07:00
Leonardo Hernández Hernández a48ce99e6a use pointer math in xytonode() 2022-04-15 17:40:02 -05:00
8 changed files with 433 additions and 221 deletions
+47 -42
View File
@@ -1,64 +1,69 @@
.POSIX:
.SUFFIXES:
include config.mk include config.mk
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -pedantic # flags for compiling
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -DVERSION=\"$(VERSION)\"
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) # Wayland utils
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) WAYLAND_PROTOCOLS = `pkg-config --variable=pkgdatadir wayland-protocols`
WAYLAND_SCANNER = `pkg-config --variable=wayland_scanner wayland-scanner`
PKGS = wlroots wayland-server xcb xkbcommon libinput # CFLAGS / LDFLAGS
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p))) PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS)
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p))) DWLCFLAGS = `pkg-config --cflags $(PKGS)` $(DWLCPPFLAGS) $(CFLAGS) $(XWAYLAND)
LDLIBS = `pkg-config --libs $(PKGS)` $(LIBS)
all: dwl # build rules
clean:
rm -f dwl *.o *-protocol.h *-protocol.c
install: dwl
install -Dm755 dwl $(DESTDIR)$(PREFIX)/bin/dwl
install -Dm644 dwl.1 $(DESTDIR)$(MANDIR)/man1/dwl.1
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1
.PHONY: all clean install uninstall
# wayland-scanner is a tool which generates C headers and rigging for Wayland # wayland-scanner is a tool which generates C headers and rigging for Wayland
# protocols, which are specified in XML. wlroots requires you to rig these up # protocols, which are specified in XML. wlroots requires you to rig these up
# to your build system yourself and provide them in the include path. # to your build system yourself and provide them in the include path.
all: dwl
dwl: dwl.o util.o
$(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h
util.o: util.c util.h
# wayland scanner rules to generate .h / .c files
xdg-shell-protocol.h: xdg-shell-protocol.h:
$(WAYLAND_SCANNER) server-header \ $(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
xdg-shell-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
xdg-shell-protocol.o: xdg-shell-protocol.h
wlr-layer-shell-unstable-v1-protocol.h: wlr-layer-shell-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \ $(WAYLAND_SCANNER) server-header \
protocols/wlr-layer-shell-unstable-v1.xml $@ protocols/wlr-layer-shell-unstable-v1.xml $@
wlr-layer-shell-unstable-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/wlr-layer-shell-unstable-v1.xml $@
wlr-layer-shell-unstable-v1-protocol.o: wlr-layer-shell-unstable-v1-protocol.h
idle-protocol.h: idle-protocol.h:
$(WAYLAND_SCANNER) server-header \ $(WAYLAND_SCANNER) server-header \
protocols/idle.xml $@ protocols/idle.xml $@
idle-protocol.c: config.h:
$(WAYLAND_SCANNER) private-code \
protocols/idle.xml $@
idle-protocol.o: idle-protocol.h
config.h: | config.def.h
cp config.def.h $@ cp config.def.h $@
clean:
rm -f dwl *.o *-protocol.h
dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h util.h # distribution archive
dist: clean
mkdir -p dwl-$(VERSION)
cp -R LICENSE* Makefile README.md generate-version.sh client.h\
config.def.h config.mk protocols dwl.1 dwl.c util.c util.h\
dwl-$(VERSION)
echo "echo $(VERSION)" > dwl-$(VERSION)/generate-version.sh
tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION)
rm -rf dwl-$(VERSION)
dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o util.o # install rules
install: dwl
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f dwl $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl
mkdir -p $(DESTDIR)$(MANDIR)/man1
cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1
chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1
.SUFFIXES: .c .o
.c.o:
$(CC) $(CPPFLAGS) $(DWLCFLAGS) -c $<
+11 -1
View File
@@ -37,7 +37,9 @@ Feature *non-goals* for the main codebase include:
## Building dwl ## Building dwl
dwl has only two dependencies: wlroots and wayland-protocols. Simply install these (and their `-devel` versions if your distro has separate development packages) and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next). dwl has only two dependencies: `wlroots` and `wayland-protocols`.
Simply install these (and their `-devel` versions if your distro has separate development packages) and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next).
To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`. To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`.
@@ -71,6 +73,14 @@ If your startup command is a shell script, you can achieve the same inside the s
exec <&- exec <&-
Existing dwl-specific status bars and dwl-specific scripts for other status bars include:
- [somebar](https://sr.ht/~raphi/somebar/) status bar designed for dwl
- [dtaobarv2.sh](https://cdn.discordapp.com/attachments/792078050024095745/862428883423723560/dtaobarv2.sh) for use with [dtao](https://github.com/djpohly/dtao) (See "Pinned Messages" on the "customizations" channel of the [dwl Discord server](https://discord.gg/jJxZnrGPWN) for details.)
- [dwlbar.sh](https://cdn.discordapp.com/attachments/792078050024095745/810926218529472592/dwlbar.sh) for use with [waybar](https://github.com/Alexays/Waybar) (See "Pinned Messages" on the "customizations" channel of the [dwl Discord server](https://discord.gg/jJxZnrGPWN) for details.)
- [waybar-dwl](https://codeberg.org/fauxmight/waybar-dwl.git) for use with [waybar](https://github.com/Alexays/Waybar)
- [dwl-tags.sh](https://codeberg.org/novakane/yambar/src/branch/master/examples/scripts/dwl-tags.sh) for use with [yambar](https://codeberg.org/dnkl/yambar)
- [waybar-dwl.sh](https://gitee.com/guyuming76/personal/tree/dwl/gentoo/waybar-dwl) for use with [waybar](https://github.com/Alexays/Waybar) (ACCESS TO THIS SCRIPT REQUIRES gitee.com LOGIN!)
## Replacements for X applications ## Replacements for X applications
You can find a [list of Wayland applications on the sway wiki](https://github.com/swaywm/sway/wiki/i3-Migration-Guide). You can find a [list of Wayland applications on the sway wiki](https://github.com/swaywm/sway/wiki/i3-Migration-Guide).
+90 -43
View File
@@ -26,20 +26,42 @@ client_surface(Client *c)
return c->surface.xdg->surface; return c->surface.xdg->surface;
} }
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;
return NULL;
}
/* 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)
{ {
struct wlr_xdg_surface *surface;
#ifdef XWAYLAND #ifdef XWAYLAND
if (wlr_surface_is_xwayland_surface(s)) { struct wlr_xwayland_surface *xsurface;
wlr_xwayland_surface_activate( if (wlr_surface_is_xwayland_surface(s)
wlr_xwayland_surface_from_wlr_surface(s), activated); && (xsurface = wlr_xwayland_surface_from_wlr_surface(s))) {
wlr_xwayland_surface_activate(xsurface, activated);
return; return;
} }
#endif #endif
if (wlr_surface_is_xdg_surface(s)) if (wlr_surface_is_xdg_surface(s)
wlr_xdg_toplevel_set_activated( && (surface = wlr_xdg_surface_from_wlr_surface(s))
wlr_xdg_surface_from_wlr_surface(s), activated); && surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
wlr_xdg_toplevel_set_activated(surface, activated);
} }
static inline void static inline void
@@ -78,6 +100,32 @@ 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 void
client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min)
{
struct wlr_xdg_toplevel *toplevel;
struct wlr_xdg_toplevel_state *state;
#ifdef XWAYLAND
if (client_is_x11(c)) {
struct wlr_xwayland_surface_size_hints *size_hints;
size_hints = c->surface.xwayland->size_hints;
if (size_hints) {
max->width = size_hints->max_width;
max->height = size_hints->max_height;
min->width = size_hints->min_width;
min->height = size_hints->min_height;
}
return;
}
#endif
toplevel = c->surface.xdg->toplevel;
state = &toplevel->current;
max->width = state->max_width;
max->height = state->max_height;
min->width = state->min_width;
min->height = state->min_height;
}
static inline const char * static inline const char *
client_get_title(Client *c) client_get_title(Client *c)
{ {
@@ -88,42 +136,48 @@ client_get_title(Client *c)
return c->surface.xdg->toplevel->title; return c->surface.xdg->toplevel->title;
} }
static inline Client *
client_get_parent(Client *c)
{
Client *p;
#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->surface);
return NULL;
}
static inline int static inline int
client_is_float_type(Client *c) client_is_float_type(Client *c)
{ {
struct wlr_xdg_toplevel *toplevel; struct wlr_box min = {0}, max = {0};
struct wlr_xdg_toplevel_state state; client_get_size_hints(c, &max, &min);
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c)) {
struct wlr_xwayland_surface *surface = c->surface.xwayland; struct wlr_xwayland_surface *surface = c->surface.xwayland;
struct wlr_xwayland_surface_size_hints *size_hints;
if (surface->modal) if (surface->modal)
return 1; return 1;
for (size_t i = 0; i < surface->window_type_len; i++) for (size_t i = 0; i < surface->window_type_len; i++)
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] || if (surface->window_type[i] == netatom[NetWMWindowTypeDialog]
surface->window_type[i] == netatom[NetWMWindowTypeSplash] || || surface->window_type[i] == netatom[NetWMWindowTypeSplash]
surface->window_type[i] == netatom[NetWMWindowTypeToolbar] || || surface->window_type[i] == netatom[NetWMWindowTypeToolbar]
surface->window_type[i] == netatom[NetWMWindowTypeUtility]) || surface->window_type[i] == netatom[NetWMWindowTypeUtility])
return 1; return 1;
size_hints = surface->size_hints; return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
if (size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 && (min.width == max.width || min.height == max.height))
&& (size_hints->max_width == size_hints->min_width || || c->surface.xwayland->parent;
size_hints->max_height == size_hints->min_height))
return 1;
return 0;
} }
#endif #endif
toplevel = c->surface.xdg->toplevel; return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
state = toplevel->current; && (min.width == max.width || min.height == max.height))
return (state.min_width != 0 && state.min_height != 0 || c->surface.xdg->toplevel->parent;
&& (state.min_width == state.max_width
|| state.min_height == state.max_height))
|| toplevel->parent;
} }
static inline int static inline int
@@ -204,34 +258,27 @@ client_surface_at(Client *c, double cx, double cy, double *sx, double *sy)
} }
static inline void static inline void
client_min_size(Client *c, int *width, int *height) client_restack_surface(Client *c)
{ {
struct wlr_xdg_toplevel *toplevel;
struct wlr_xdg_toplevel_state *state;
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c))
struct wlr_xwayland_surface_size_hints *size_hints; wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
size_hints = c->surface.xwayland->size_hints; XCB_STACK_MODE_ABOVE);
*width = size_hints->min_width;
*height = size_hints->min_height;
return;
}
#endif #endif
toplevel = c->surface.xdg->toplevel; return;
state = &toplevel->current;
*width = state->min_width;
*height = state->min_height;
} }
static inline Client * static inline void *
client_from_popup(struct wlr_xdg_popup *popup) toplevel_from_popup(struct wlr_xdg_popup *popup)
{ {
struct wlr_xdg_surface *surface = popup->base; struct wlr_xdg_surface *surface = popup->base;
while (1) { while (1) {
switch (surface->role) { switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_POPUP: case WLR_XDG_SURFACE_ROLE_POPUP:
if (!wlr_surface_is_xdg_surface(surface->popup->parent)) 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; return NULL;
surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent); surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent);
+53 -18
View File
@@ -5,6 +5,8 @@ static const int lockfullscreen = 1; /* 1 will force focus on the fullscree
static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0}; static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0};
static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0}; static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0};
static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
/* tagging */ /* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
@@ -41,7 +43,7 @@ static const struct xkb_rule_names xkb_rules = {
/* example: /* example:
.options = "ctrl:nocaps", .options = "ctrl:nocaps",
*/ */
.options = "", .options = NULL,
}; };
static const int repeat_rate = 25; static const int repeat_rate = 25;
@@ -49,15 +51,48 @@ static const int repeat_delay = 600;
/* Trackpad */ /* Trackpad */
static const int tap_to_click = 1; static const int tap_to_click = 1;
static const int tap_and_drag = 1;
static const int drag_lock = 1;
static const int natural_scrolling = 0; static const int natural_scrolling = 0;
static const int disable_while_typing = 1;
static const int left_handed = 0;
static const int middle_button_emulation = 0;
/* You can choose between:
LIBINPUT_CONFIG_SCROLL_NO_SCROLL
LIBINPUT_CONFIG_SCROLL_2FG
LIBINPUT_CONFIG_SCROLL_EDGE
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
*/
static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
/* You can choose between:
LIBINPUT_CONFIG_CLICK_METHOD_NONE
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
*/
static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
/* You can choose between:
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE
*/
static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
/* You can choose between:
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
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;
/* If you want to use the windows key change this to WLR_MODIFIER_LOGO */ /* If you want to use the windows key change this to WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT #define MODKEY WLR_MODIFIER_ALT
#define TAGKEYS(KEY,SKEY,TAG) \ #define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,toggletag, {.ui = 1 << TAG} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */ /* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
@@ -79,7 +114,7 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} }, { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} },
{ MODKEY, XKB_KEY_Return, zoom, {0} }, { MODKEY, XKB_KEY_Return, zoom, {0} },
{ MODKEY, XKB_KEY_Tab, view, {0} }, { MODKEY, XKB_KEY_Tab, view, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, killclient, {0} },
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
@@ -87,21 +122,21 @@ static const Key keys[] = {
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} }, { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} }, { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_0, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_comma, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_period, tagmon, {.i = WLR_DIRECTION_RIGHT} },
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), TAGKEYS( XKB_KEY_1, 0),
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), TAGKEYS( XKB_KEY_2, 1),
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), TAGKEYS( XKB_KEY_3, 2),
TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), TAGKEYS( XKB_KEY_4, 3),
TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), TAGKEYS( XKB_KEY_5, 4),
TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), TAGKEYS( XKB_KEY_6, 5),
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), TAGKEYS( XKB_KEY_7, 6),
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), TAGKEYS( XKB_KEY_8, 7),
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), TAGKEYS( XKB_KEY_9, 8),
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
+9 -3
View File
@@ -1,9 +1,15 @@
_VERSION = 0.3.1
VERSION = `./generate-version.sh $(_VERSION)`
# paths # paths
PREFIX = /usr/local PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man MANDIR = $(PREFIX)/share/man
# Default compile flags (overridable by environment) # Compile flags that can be used
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement #CFLAGS = -pedantic -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement
XWAYLAND =
XLIBS =
# Uncomment to build XWayland support # Uncomment to build XWayland support
#CFLAGS += -DXWAYLAND #XWAYLAND = -DXWAYLAND
#XLIBS = xcb
+8 -1
View File
@@ -6,7 +6,8 @@
.Nd dwm for Wayland .Nd dwm for Wayland
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl s Ar command .Op Fl v
.Op Fl s Ar startup command
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
is a Wayland compositor based on wlroots. is a Wayland compositor based on wlroots.
@@ -15,6 +16,12 @@ It is intended to fill the same space in the Wayland world that
does for X11. does for X11.
.Pp .Pp
When given the When given the
.Fl v
option,
.Nm
writes its name and version to standard error and exits unsuccessfully.
.Pp
When given the
.Fl s .Fl s
option, option,
.Nm .Nm
+198 -109
View File
@@ -4,6 +4,7 @@
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#include <getopt.h> #include <getopt.h>
#include <libinput.h> #include <libinput.h>
#include <limits.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@@ -90,11 +91,14 @@ typedef struct {
typedef struct Monitor Monitor; typedef struct Monitor Monitor;
typedef struct { typedef struct {
/* Must be first */ /* Must keep these three elements in this order */
unsigned int type; /* XDGShell or X11* */ unsigned int type; /* XDGShell or X11* */
struct wlr_box geom; /* layout-relative, includes border */
Monitor *mon;
struct wlr_scene_node *scene; struct wlr_scene_node *scene;
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
struct wlr_scene_node *scene_surface; struct wlr_scene_node *scene_surface;
struct wlr_scene_rect *fullscreen_bg; /* See setfullscreen() for info */
struct wl_list link; struct wl_list link;
struct wl_list flink; struct wl_list flink;
union { union {
@@ -107,11 +111,11 @@ typedef struct {
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener set_title; struct wl_listener set_title;
struct wl_listener fullscreen; struct wl_listener fullscreen;
struct wlr_box geom, prev; /* layout-relative, includes border */ struct wlr_box prev; /* layout-relative, includes border */
Monitor *mon;
#ifdef XWAYLAND #ifdef XWAYLAND
struct wl_listener activate; struct wl_listener activate;
struct wl_listener configure; struct wl_listener configure;
struct wl_listener set_hints;
#endif #endif
int bw; int bw;
unsigned int tags; unsigned int tags;
@@ -145,19 +149,19 @@ typedef struct {
} Keyboard; } Keyboard;
typedef struct { typedef struct {
/* Must be first */ /* Must keep these three elements in this order */
unsigned int type; /* LayerShell */ unsigned int type; /* LayerShell */
int mapped; struct wlr_box geom;
Monitor *mon;
struct wlr_scene_node *scene; struct wlr_scene_node *scene;
struct wl_list link; struct wl_list link;
int mapped;
struct wlr_layer_surface_v1 *layer_surface; struct wlr_layer_surface_v1 *layer_surface;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener surface_commit; struct wl_listener surface_commit;
struct wlr_box geo;
} LayerSurface; } LayerSurface;
typedef struct { typedef struct {
@@ -259,7 +263,7 @@ static void quit(const Arg *arg);
static void quitsignal(int signo); static void quitsignal(int signo);
static void rendermon(struct wl_listener *listener, void *data); static void rendermon(struct wl_listener *listener, void *data);
static void requeststartdrag(struct wl_listener *listener, void *data); static void requeststartdrag(struct wl_listener *listener, void *data);
static void resize(Client *c, int x, int y, int w, int h, int interact); static void resize(Client *c, struct wlr_box geo, int interact);
static void run(char *startup_cmd); static void run(char *startup_cmd);
static Client *selclient(void); static Client *selclient(void);
static void setcursor(struct wl_listener *listener, void *data); static void setcursor(struct wl_listener *listener, void *data);
@@ -281,7 +285,6 @@ static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg); static void togglefullscreen(const Arg *arg);
static void toggletag(const Arg *arg); static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg); static void toggleview(const Arg *arg);
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 updatemons(struct wl_listener *listener, void *data); static void updatemons(struct wl_listener *listener, void *data);
@@ -296,6 +299,8 @@ static void zoom(const Arg *arg);
/* variables */ /* variables */
static const char broken[] = "broken"; static const char broken[] = "broken";
static pid_t child_pid = -1;
static struct wlr_surface *exclusive_focus;
static struct wl_display *dpy; static struct wl_display *dpy;
static struct wlr_backend *backend; static struct wlr_backend *backend;
static struct wlr_scene *scene; static struct wlr_scene *scene;
@@ -358,6 +363,7 @@ static void activatex11(struct wl_listener *listener, void *data);
static void configurex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data);
static void createnotifyx11(struct wl_listener *listener, void *data); static void createnotifyx11(struct wl_listener *listener, void *data);
static Atom getatom(xcb_connection_t *xc, const char *name); static Atom getatom(xcb_connection_t *xc, const char *name);
static void sethints(struct wl_listener *listener, void *data);
static void xwaylandready(struct wl_listener *listener, void *data); static void xwaylandready(struct wl_listener *listener, void *data);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wl_listener xwayland_ready = {.notify = xwaylandready};
@@ -378,9 +384,15 @@ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
void void
applybounds(Client *c, struct wlr_box *bbox) applybounds(Client *c, struct wlr_box *bbox)
{ {
/* set minimum possible */ struct wlr_box min = {0}, max = {0};
c->geom.width = MAX(1, c->geom.width); client_get_size_hints(c, &max, &min);
c->geom.height = MAX(1, c->geom.height); /* try to set size hints */
c->geom.width = MAX(min.width + (2 * c->bw), c->geom.width);
c->geom.height = MAX(min.height + (2 * c->bw), c->geom.height);
if (max.width > 0 && !(2 * c->bw > INT_MAX - max.width)) // Checks for overflow
c->geom.width = MIN(max.width + (2 * c->bw), c->geom.width);
if (max.height > 0 && !(2 * c->bw > INT_MAX - max.height)) // Checks for overflow
c->geom.height = MIN(max.height + (2 * c->bw), c->geom.height);
if (c->geom.x >= bbox->x + bbox->width) if (c->geom.x >= bbox->x + bbox->width)
c->geom.x = bbox->x + bbox->width - c->geom.width; c->geom.x = bbox->x + bbox->width - c->geom.width;
@@ -486,7 +498,7 @@ arrange(Monitor *m)
if (m->lt[m->sellt]->arrange) if (m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m); m->lt[m->sellt]->arrange(m);
/* TODO recheck pointer focus here... or in resize()? */ motionnotify(0);
} }
void void
@@ -556,7 +568,7 @@ arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int
wlr_layer_surface_v1_destroy(wlr_layer_surface); wlr_layer_surface_v1_destroy(wlr_layer_surface);
continue; continue;
} }
layersurface->geo = box; layersurface->geom = box;
if (state->exclusive_zone > 0) if (state->exclusive_zone > 0)
applyexclusive(usable_area, state->anchor, state->exclusive_zone, applyexclusive(usable_area, state->anchor, state->exclusive_zone,
@@ -600,8 +612,12 @@ arrangelayers(Monitor *m)
layersurface->layer_surface->mapped) { layersurface->layer_surface->mapped) {
/* Deactivate the focused client. */ /* Deactivate the focused client. */
focusclient(NULL, 0); focusclient(NULL, 0);
wlr_seat_keyboard_notify_enter(seat, layersurface->layer_surface->surface, exclusive_focus = layersurface->layer_surface->surface;
if (kb)
wlr_seat_keyboard_notify_enter(seat, exclusive_focus,
kb->keycodes, kb->num_keycodes, &kb->modifiers); kb->keycodes, kb->num_keycodes, &kb->modifiers);
else
wlr_seat_keyboard_notify_enter(seat, exclusive_focus, NULL, 0, NULL);
return; return;
} }
} }
@@ -641,7 +657,7 @@ buttonpress(struct wl_listener *listener, void *data)
focusclient(c, 1); focusclient(c, 1);
keyboard = wlr_seat_get_keyboard(seat); keyboard = wlr_seat_get_keyboard(seat);
mods = wlr_keyboard_get_modifiers(keyboard); mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
for (b = buttons; b < END(buttons); b++) { for (b = buttons; b < END(buttons); b++) {
if (CLEANMASK(mods) == CLEANMASK(b->mod) && if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
event->button == b->button && b->func) { event->button == b->button && b->func) {
@@ -682,7 +698,10 @@ cleanup(void)
wlr_xwayland_destroy(xwayland); wlr_xwayland_destroy(xwayland);
#endif #endif
wl_display_destroy_clients(dpy); wl_display_destroy_clients(dpy);
if (child_pid > 0) {
kill(child_pid, SIGTERM);
waitpid(child_pid, NULL, 0);
}
wlr_backend_destroy(backend); wlr_backend_destroy(backend);
wlr_xcursor_manager_destroy(cursor_mgr); wlr_xcursor_manager_destroy(cursor_mgr);
wlr_cursor_destroy(cursor); wlr_cursor_destroy(cursor);
@@ -735,11 +754,12 @@ closemon(Monitor *m)
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (c->isfloating && c->geom.x > m->m.width) if (c->isfloating && c->geom.x > m->m.width)
resize(c, c->geom.x - m->w.width, c->geom.y, resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
c->geom.width, c->geom.height, 0); .width = c->geom.width, .height = c->geom.height}, 0);
if (c->mon == m) if (c->mon == m)
setmon(c, selmon, c->tags); setmon(c, selmon, c->tags);
} }
printstatus();
} }
void void
@@ -748,14 +768,13 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit); LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit);
struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface; struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface;
struct wlr_output *wlr_output = wlr_layer_surface->output; struct wlr_output *wlr_output = wlr_layer_surface->output;
Monitor *m;
if (!wlr_output || !(layersurface->mon = wlr_output->data))
return;
wlr_scene_node_reparent(layersurface->scene, wlr_scene_node_reparent(layersurface->scene,
layers[wlr_layer_surface->current.layer]); layers[wlr_layer_surface->current.layer]);
if (!wlr_output || !(m = wlr_output->data))
return;
if (wlr_layer_surface->current.committed == 0 if (wlr_layer_surface->current.committed == 0
&& layersurface->mapped == wlr_layer_surface->mapped) && layersurface->mapped == wlr_layer_surface->mapped)
return; return;
@@ -764,19 +783,27 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
if (layers[wlr_layer_surface->current.layer] != layersurface->scene) { if (layers[wlr_layer_surface->current.layer] != layersurface->scene) {
wl_list_remove(&layersurface->link); wl_list_remove(&layersurface->link);
wl_list_insert(&m->layers[wlr_layer_surface->current.layer], wl_list_insert(&layersurface->mon->layers[wlr_layer_surface->current.layer],
&layersurface->link); &layersurface->link);
} }
arrangelayers(m); arrangelayers(layersurface->mon);
} }
void void
commitnotify(struct wl_listener *listener, void *data) commitnotify(struct wl_listener *listener, void *data)
{ {
Client *c = wl_container_of(listener, c, commit); Client *c = wl_container_of(listener, c, commit);
struct wlr_box 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;
} }
@@ -823,7 +850,6 @@ createlayersurface(struct wl_listener *listener, void *data)
{ {
struct wlr_layer_surface_v1 *wlr_layer_surface = data; struct wlr_layer_surface_v1 *wlr_layer_surface = data;
LayerSurface *layersurface; LayerSurface *layersurface;
Monitor *m;
struct wlr_layer_surface_v1_state old_state; struct wlr_layer_surface_v1_state old_state;
if (!wlr_layer_surface->output) { if (!wlr_layer_surface->output) {
@@ -843,14 +869,14 @@ createlayersurface(struct wl_listener *listener, void *data)
layersurface->layer_surface = wlr_layer_surface; layersurface->layer_surface = wlr_layer_surface;
wlr_layer_surface->data = layersurface; wlr_layer_surface->data = layersurface;
m = wlr_layer_surface->output->data; layersurface->mon = wlr_layer_surface->output->data;
layersurface->scene = wlr_layer_surface->surface->data = layersurface->scene = wlr_layer_surface->surface->data =
wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer], wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer],
wlr_layer_surface->surface); wlr_layer_surface->surface);
layersurface->scene->data = layersurface; layersurface->scene->data = layersurface;
wl_list_insert(&m->layers[wlr_layer_surface->pending.layer], wl_list_insert(&layersurface->mon->layers[wlr_layer_surface->pending.layer],
&layersurface->link); &layersurface->link);
/* Temporarily set the layer's current state to pending /* Temporarily set the layer's current state to pending
@@ -858,7 +884,7 @@ createlayersurface(struct wl_listener *listener, void *data)
*/ */
old_state = wlr_layer_surface->current; old_state = wlr_layer_surface->current;
wlr_layer_surface->current = wlr_layer_surface->pending; wlr_layer_surface->current = wlr_layer_surface->pending;
arrangelayers(m); arrangelayers(layersurface->mon);
wlr_layer_surface->current = old_state; wlr_layer_surface->current = old_state;
} }
@@ -941,11 +967,16 @@ createnotify(struct wl_listener *listener, void *data)
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;
void *toplevel = toplevel_from_popup(xdg_surface->popup);
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);
if (!(c = client_from_popup(xdg_surface->popup)) || !c->mon) if (wlr_surface_is_layer_surface(xdg_surface->popup->parent) && (l = toplevel)
&& l->layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
wlr_scene_node_reparent(xdg_surface->surface->data, layers[LyrTop]);
if (!(c = toplevel) || !c->mon)
return; return;
box = c->mon->m; box = c->type == LayerShell ? c->mon->m : c->mon->w;
box.x -= c->geom.x; box.x -= c->geom.x;
box.y -= c->geom.y; box.y -= c->geom.y;
wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box); wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &box);
@@ -958,14 +989,12 @@ createnotify(struct wl_listener *listener, void *data)
c->surface.xdg = xdg_surface; c->surface.xdg = xdg_surface;
c->bw = borderpx; c->bw = borderpx;
LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
LISTEN(&xdg_surface->events.map, &c->map, mapnotify); LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify); LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify); LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle); LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen, LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
fullscreennotify); fullscreennotify);
c->isfullscreen = 0;
} }
void void
@@ -975,17 +1004,39 @@ createpointer(struct wlr_input_device *device)
struct libinput_device *libinput_device = (struct libinput_device*) struct libinput_device *libinput_device = (struct libinput_device*)
wlr_libinput_get_device_handle(device); wlr_libinput_get_device_handle(device);
if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device)) if (libinput_device_config_tap_get_finger_count(libinput_device)) {
libinput_device_config_tap_set_enabled(libinput_device, LIBINPUT_CONFIG_TAP_ENABLED); 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_lock_enabled(libinput_device, drag_lock);
}
if (libinput_device_config_scroll_has_natural_scroll(libinput_device)) if (libinput_device_config_scroll_has_natural_scroll(libinput_device))
libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling); libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling);
if (libinput_device_config_dwt_is_available(libinput_device))
libinput_device_config_dwt_set_enabled(libinput_device, disable_while_typing);
if (libinput_device_config_left_handed_is_available(libinput_device))
libinput_device_config_left_handed_set(libinput_device, left_handed);
if (libinput_device_config_middle_emulation_is_available(libinput_device))
libinput_device_config_middle_emulation_set_enabled(libinput_device, middle_button_emulation);
if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
libinput_device_config_scroll_set_method (libinput_device, scroll_method);
if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
libinput_device_config_click_set_method (libinput_device, click_method);
if (libinput_device_config_send_events_get_modes(libinput_device))
libinput_device_config_send_events_set_mode(libinput_device, send_events_mode);
if (libinput_device_config_accel_is_available(libinput_device)) {
libinput_device_config_accel_set_profile(libinput_device, accel_profile);
libinput_device_config_accel_set_speed(libinput_device, accel_speed);
}
} }
/* We don't do anything special with pointers. All of our pointer handling
* is proxied through wlr_cursor. On another compositor, you might take this
* opportunity to do libinput configuration on the device to set
* acceleration, etc. */
wlr_cursor_attach_input_device(cursor, device); wlr_cursor_attach_input_device(cursor, device);
} }
@@ -1013,17 +1064,15 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data)
{ {
LayerSurface *layersurface = wl_container_of(listener, layersurface, destroy); LayerSurface *layersurface = wl_container_of(listener, layersurface, destroy);
if (layersurface->layer_surface->mapped)
unmaplayersurface(layersurface);
wl_list_remove(&layersurface->link); wl_list_remove(&layersurface->link);
wl_list_remove(&layersurface->destroy.link); wl_list_remove(&layersurface->destroy.link);
wl_list_remove(&layersurface->map.link); wl_list_remove(&layersurface->map.link);
wl_list_remove(&layersurface->unmap.link); wl_list_remove(&layersurface->unmap.link);
wl_list_remove(&layersurface->surface_commit.link); wl_list_remove(&layersurface->surface_commit.link);
wlr_scene_node_destroy(layersurface->scene);
if (layersurface->layer_surface->output) { if (layersurface->layer_surface->output) {
Monitor *m = layersurface->layer_surface->output->data; if ((layersurface->mon = layersurface->layer_surface->output->data))
if (m) arrangelayers(layersurface->mon);
arrangelayers(m);
layersurface->layer_surface->output = NULL; layersurface->layer_surface->output = NULL;
} }
free(layersurface); free(layersurface);
@@ -1042,10 +1091,10 @@ destroynotify(struct wl_listener *listener, void *data)
#ifdef XWAYLAND #ifdef XWAYLAND
if (c->type != XDGShell) { if (c->type != XDGShell) {
wl_list_remove(&c->configure.link); wl_list_remove(&c->configure.link);
wl_list_remove(&c->set_hints.link);
wl_list_remove(&c->activate.link); wl_list_remove(&c->activate.link);
} else }
#endif #endif
wl_list_remove(&c->commit.link);
free(c); free(c);
} }
@@ -1079,6 +1128,9 @@ focusclient(Client *c, int lift)
struct wlr_surface *old = seat->keyboard_state.focused_surface; struct wlr_surface *old = seat->keyboard_state.focused_surface;
struct wlr_keyboard *kb; struct wlr_keyboard *kb;
int i; int i;
/* Do not focus clients if a layer surface is focused */
if (exclusive_focus)
return;
/* Raise client in stacking order if requested */ /* Raise client in stacking order if requested */
if (c && lift) if (c && lift)
@@ -1093,6 +1145,7 @@ focusclient(Client *c, int lift)
wl_list_insert(&fstack, &c->flink); wl_list_insert(&fstack, &c->flink);
selmon = c->mon; selmon = c->mon;
c->isurgent = 0; c->isurgent = 0;
client_restack_surface(c);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
wlr_scene_rect_set_color(c->border[i], focuscolor); wlr_scene_rect_set_color(c->border[i], focuscolor);
@@ -1116,8 +1169,7 @@ focusclient(Client *c, int lift)
return; return;
} else { } else {
Client *w; Client *w;
struct wlr_scene_node *node = old->data; if ((w = client_from_wlr_surface(old)))
if ((w = node->data))
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
wlr_scene_rect_set_color(w->border[i], bordercolor); wlr_scene_rect_set_color(w->border[i], bordercolor);
@@ -1136,8 +1188,11 @@ focusclient(Client *c, int lift)
/* Have a client, so focus its top-level wlr_surface */ /* Have a client, so focus its top-level wlr_surface */
kb = wlr_seat_get_keyboard(seat); kb = wlr_seat_get_keyboard(seat);
if (kb)
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);
else
wlr_seat_keyboard_notify_enter(seat, client_surface(c), NULL, 0, NULL);
/* Activate the new client */ /* Activate the new client */
client_activate_surface(client_surface(c), 1); client_activate_surface(client_surface(c), 1);
@@ -1271,8 +1326,10 @@ keypress(struct wl_listener *listener, void *data)
uint32_t keycode = event->keycode + 8; uint32_t keycode = event->keycode + 8;
/* Get a list of keysyms based on the keymap for this keyboard */ /* Get a list of keysyms based on the keymap for this keyboard */
const xkb_keysym_t *syms; const xkb_keysym_t *syms;
int nsyms = xkb_state_key_get_syms( xkb_layout_index_t layout_index = xkb_state_key_get_layout(
kb->device->keyboard->xkb_state, keycode, &syms); kb->device->keyboard->xkb_state, keycode);
int nsyms = xkb_keymap_key_get_syms_by_level(kb->device->keyboard->keymap,
keycode, layout_index, 0, &syms);
int handled = 0; int handled = 0;
uint32_t mods = wlr_keyboard_get_modifiers(kb->device->keyboard); uint32_t mods = wlr_keyboard_get_modifiers(kb->device->keyboard);
@@ -1324,8 +1381,9 @@ void
maplayersurfacenotify(struct wl_listener *listener, void *data) maplayersurfacenotify(struct wl_listener *listener, void *data)
{ {
LayerSurface *layersurface = wl_container_of(listener, layersurface, map); LayerSurface *layersurface = wl_container_of(listener, layersurface, map);
layersurface->mon = layersurface->layer_surface->output->data;
wlr_surface_send_enter(layersurface->layer_surface->surface, wlr_surface_send_enter(layersurface->layer_surface->surface,
layersurface->layer_surface->output); layersurface->mon->wlr_output);
motionnotify(0); motionnotify(0);
} }
@@ -1333,15 +1391,23 @@ void
mapnotify(struct wl_listener *listener, void *data) mapnotify(struct wl_listener *listener, void *data)
{ {
/* Called when the surface is mapped, or ready to display on-screen. */ /* Called when the surface is mapped, or ready to display on-screen. */
Client *c = wl_container_of(listener, c, map); Client *p, *c = wl_container_of(listener, c, map);
int i; int i;
/* Create scene tree for this client and its border */ /* Create scene tree for this client and its border */
c->scene = &wlr_scene_tree_create(layers[LyrTile])->node; c->scene = &wlr_scene_tree_create(layers[LyrTile])->node;
c->scene_surface = client_surface(c)->data = c->type == XDGShell c->scene_surface = c->type == XDGShell
? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
: wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); : wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
c->scene_surface->data = c; if (client_surface(c)) {
client_surface(c)->data = c->scene;
/* Ideally we should do this in createnotify{,x11} but at that moment
* wlr_xwayland_surface doesn't have wlr_surface yet
*/
LISTEN(&client_surface(c)->events.commit, &c->commit, commitnotify);
}
c->scene->data = c->scene_surface->data = c;
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
client_get_geometry(c, &c->geom); client_get_geometry(c, &c->geom);
@@ -1356,7 +1422,6 @@ mapnotify(struct wl_listener *listener, void *data)
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); wlr_scene_rect_set_color(c->border[i], bordercolor);
wlr_scene_node_lower_to_bottom(&c->border[i]->node);
} }
/* Initialize client geometry with room for border */ /* Initialize client geometry with room for border */
@@ -1370,7 +1435,14 @@ mapnotify(struct wl_listener *listener, void *data)
wl_list_insert(&fstack, &c->flink); wl_list_insert(&fstack, &c->flink);
/* Set initial monitor, tags, floating status, and focus */ /* Set initial monitor, tags, floating status, and focus */
if ((p = client_get_parent(c))) {
/* Set the same monitor and tags than its parent */
c->isfloating = 1;
wlr_scene_node_reparent(c->scene, layers[LyrFloat]);
setmon(c, p->mon, p->tags);
} else {
applyrules(c); applyrules(c);
}
printstatus(); printstatus();
if (c->isfullscreen) if (c->isfullscreen)
@@ -1387,8 +1459,9 @@ monocle(Monitor *m)
wl_list_for_each(c, &clients, link) { wl_list_for_each(c, &clients, link) {
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
continue; continue;
resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0); resize(c, m->w, 0);
} }
focusclient(focustop(m), 1);
} }
void void
@@ -1428,13 +1501,12 @@ motionnotify(uint32_t time)
/* If we are currently grabbing the mouse, handle and return */ /* If we are currently grabbing the mouse, handle and return */
if (cursor_mode == CurMove) { if (cursor_mode == CurMove) {
/* Move the grabbed client to the new position. */ /* Move the grabbed client to the new position. */
resize(grabc, cursor->x - grabcx, cursor->y - grabcy, resize(grabc, (struct wlr_box){.x = cursor->x - grabcx, .y = cursor->y - grabcy,
grabc->geom.width, grabc->geom.height, 1); .width = grabc->geom.width, .height = grabc->geom.height}, 1);
return; return;
} else if (cursor_mode == CurResize) { } else if (cursor_mode == CurResize) {
resize(grabc, grabc->geom.x, grabc->geom.y, resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
cursor->x - grabc->geom.x, .width = cursor->x - grabc->geom.x, .height = cursor->y - grabc->geom.y}, 1);
cursor->y - grabc->geom.y, 1);
return; return;
} }
@@ -1617,7 +1689,6 @@ printstatus(void)
sel, urg); sel, urg);
printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol);
} }
fflush(stdout);
} }
void void
@@ -1678,15 +1749,10 @@ requeststartdrag(struct wl_listener *listener, void *data)
} }
void void
resize(Client *c, int x, int y, int w, int h, int interact) resize(Client *c, struct wlr_box geo, int interact)
{ {
int min_width = 0, min_height = 0;
struct wlr_box *bbox = interact ? &sgeom : &c->mon->w; struct wlr_box *bbox = interact ? &sgeom : &c->mon->w;
client_min_size(c, &min_width, &min_height); c->geom = geo;
c->geom.x = x;
c->geom.y = y;
c->geom.width = MAX(min_width + 2 * c->bw, w);
c->geom.height = MAX(min_height + 2 * c->bw, h);
applybounds(c, bbox); applybounds(c, bbox);
/* Update scene-graph, including borders */ /* Update scene-graph, including borders */
@@ -1708,8 +1774,6 @@ resize(Client *c, int x, int y, int w, int h, int interact)
void void
run(char *startup_cmd) run(char *startup_cmd)
{ {
pid_t startup_pid = -1;
/* Add a Unix socket to the Wayland display. */ /* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(dpy); const char *socket = wl_display_add_socket_auto(dpy);
if (!socket) if (!socket)
@@ -1721,9 +1785,9 @@ run(char *startup_cmd)
int piperw[2]; int piperw[2];
if (pipe(piperw) < 0) if (pipe(piperw) < 0)
die("startup: pipe:"); die("startup: pipe:");
if ((startup_pid = fork()) < 0) if ((child_pid = fork()) < 0)
die("startup: fork:"); die("startup: fork:");
if (startup_pid == 0) { if (child_pid == 0) {
dup2(piperw[0], STDIN_FILENO); dup2(piperw[0], STDIN_FILENO);
close(piperw[0]); close(piperw[0]);
close(piperw[1]); close(piperw[1]);
@@ -1759,11 +1823,6 @@ run(char *startup_cmd)
* loop configuration to listen to libinput events, DRM events, generate * loop configuration to listen to libinput events, DRM events, generate
* frame events at the refresh rate, and so on. */ * frame events at the refresh rate, and so on. */
wl_display_run(dpy); wl_display_run(dpy);
if (startup_cmd) {
kill(startup_pid, SIGTERM);
waitpid(startup_pid, NULL, 0);
}
} }
Client * Client *
@@ -1812,11 +1871,29 @@ setfullscreen(Client *c, int fullscreen)
if (fullscreen) { if (fullscreen) {
c->prev = c->geom; c->prev = c->geom;
resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0); resize(c, c->mon->m, 0);
/* The xdg-protocol specifies:
*
* If the fullscreened surface is not opaque, the compositor must make
* sure that other screen content not part of the same surface tree (made
* up of subsurfaces, popups or similarly coupled surfaces) are not
* visible below the fullscreened surface.
*
* For brevity we set a black background for all clients
*/
if (!c->fullscreen_bg) {
c->fullscreen_bg = wlr_scene_rect_create(c->scene,
c->geom.width, c->geom.height, fullscreen_bg);
wlr_scene_node_lower_to_bottom(&c->fullscreen_bg->node);
}
} else { } else {
/* restore previous size instead of arrange for floating windows since /* restore previous size instead of arrange for floating windows since
* client positions are set by the user and cannot be recalculated */ * client positions are set by the user and cannot be recalculated */
resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0); resize(c, c->prev, 0);
if (c->fullscreen_bg) {
wlr_scene_node_destroy(&c->fullscreen_bg->node);
c->fullscreen_bg = NULL;
}
} }
arrange(c->mon); arrange(c->mon);
printstatus(); printstatus();
@@ -1865,7 +1942,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags)
} }
if (m) { if (m) {
/* Make sure window actually overlaps with the monitor */ /* Make sure window actually overlaps with the monitor */
resize(c, c->geom.x, c->geom.y, c->geom.width, c->geom.height, 0); resize(c, c->geom, 0);
wlr_surface_send_enter(client_surface(c), m->wlr_output); wlr_surface_send_enter(client_surface(c), m->wlr_output);
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
arrange(m); arrange(m);
@@ -1898,6 +1975,9 @@ setsel(struct wl_listener *listener, void *data)
void void
setup(void) setup(void)
{ {
/* Force line-buffered stdout */
setvbuf(stdout, NULL, _IOLBF, 0);
/* The Wayland display is managed by libwayland. It handles accepting /* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */ * clients from the Unix socket, manging Wayland globals, and so on. */
dpy = wl_display_create(); dpy = wl_display_create();
@@ -2075,10 +2155,12 @@ sigchld(int unused)
* but the Xwayland implementation in wlroots currently prevents us from * but the Xwayland implementation in wlroots currently prevents us from
* setting our own disposition for SIGCHLD. * setting our own disposition for SIGCHLD.
*/ */
pid_t pid;
if (signal(SIGCHLD, sigchld) == SIG_ERR) if (signal(SIGCHLD, sigchld) == SIG_ERR)
die("can't install SIGCHLD handler:"); die("can't install SIGCHLD handler:");
while (0 < waitpid(-1, NULL, WNOHANG)) while (0 < (pid = waitpid(-1, NULL, WNOHANG)))
; if (pid == child_pid)
child_pid = -1;
} }
void void
@@ -2129,7 +2211,7 @@ tagmon(const Arg *arg)
void void
tile(Monitor *m) tile(Monitor *m)
{ {
unsigned int i, n = 0, h, mw, my, ty; unsigned int i, n = 0, mw, my, ty;
Client *c; Client *c;
wl_list_for_each(c, &clients, link) wl_list_for_each(c, &clients, link)
@@ -2147,12 +2229,12 @@ tile(Monitor *m)
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
continue; continue;
if (i < m->nmaster) { if (i < m->nmaster) {
h = (m->w.height - my) / (MIN(n, m->nmaster) - i); resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
resize(c, m->w.x, m->w.y + my, mw, h, 0); .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
my += c->geom.height; my += c->geom.height;
} else { } else {
h = (m->w.height - ty) / (n - i); resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
resize(c, m->w.x + mw, m->w.y + ty, m->w.width - mw, h, 0); .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
ty += c->geom.height; ty += c->geom.height;
} }
i++; i++;
@@ -2206,22 +2288,20 @@ toggleview(const Arg *arg)
} }
void void
unmaplayersurface(LayerSurface *layersurface) unmaplayersurfacenotify(struct wl_listener *listener, void *data)
{ {
layersurface->layer_surface->mapped = 0; LayerSurface *layersurface = wl_container_of(listener, layersurface, unmap);
layersurface->layer_surface->mapped = (layersurface->mapped = 0);
wlr_scene_node_set_enabled(layersurface->scene, 0);
if (layersurface->layer_surface->surface == exclusive_focus)
exclusive_focus = NULL;
if (layersurface->layer_surface->surface == if (layersurface->layer_surface->surface ==
seat->keyboard_state.focused_surface) seat->keyboard_state.focused_surface)
focusclient(selclient(), 1); focusclient(selclient(), 1);
motionnotify(0); motionnotify(0);
} }
void
unmaplayersurfacenotify(struct wl_listener *listener, void *data)
{
LayerSurface *layersurface = wl_container_of(listener, layersurface, unmap);
unmaplayersurface(layersurface);
}
void void
unmapnotify(struct wl_listener *listener, void *data) unmapnotify(struct wl_listener *listener, void *data)
{ {
@@ -2243,6 +2323,7 @@ unmapnotify(struct wl_listener *listener, void *data)
wl_list_remove(&c->link); wl_list_remove(&c->link);
setmon(c, NULL, 0); setmon(c, NULL, 0);
wl_list_remove(&c->flink); wl_list_remove(&c->flink);
wl_list_remove(&c->commit.link);
wlr_scene_node_destroy(c->scene); wlr_scene_node_destroy(c->scene);
printstatus(); printstatus();
} }
@@ -2297,11 +2378,7 @@ 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 *c = client_from_wlr_surface(event->surface);
if (!wlr_surface_is_xdg_surface(event->surface))
return;
c = wlr_xdg_surface_from_wlr_surface(event->surface)->data;
if (c != selclient()) { if (c != selclient()) {
c->isurgent = 1; c->isurgent = 1;
printstatus(); printstatus();
@@ -2344,11 +2421,11 @@ xytonode(double x, double y, struct wlr_surface **psurface,
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
Client *c = NULL; Client *c = NULL;
LayerSurface *l = NULL; LayerSurface *l = NULL;
int i; const int *layer;
int focus_order[] = { LyrOverlay, LyrTop, LyrFloat, LyrTile, LyrBottom, LyrBg }; int focus_order[] = { LyrOverlay, LyrTop, LyrFloat, LyrTile, LyrBottom, LyrBg };
for (i = 0; i < LENGTH(focus_order); i++) { for (layer = focus_order; layer < END(focus_order); layer++) {
if ((node = wlr_scene_node_at(layers[focus_order[i]], x, y, nx, ny))) { if ((node = wlr_scene_node_at(layers[*layer], x, y, nx, ny))) {
if (node->type == WLR_SCENE_NODE_SURFACE) if (node->type == WLR_SCENE_NODE_SURFACE)
surface = wlr_scene_surface_from_node(node)->surface; surface = wlr_scene_surface_from_node(node)->surface;
/* Walk the tree to find a node that knows the client */ /* Walk the tree to find a node that knows the client */
@@ -2435,7 +2512,6 @@ createnotifyx11(struct wl_listener *listener, void *data)
c->surface.xwayland = xwayland_surface; c->surface.xwayland = xwayland_surface;
c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed; c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
c->bw = borderpx; c->bw = borderpx;
c->isfullscreen = 0;
/* Listen to the various events it can emit */ /* Listen to the various events it can emit */
LISTEN(&xwayland_surface->events.map, &c->map, mapnotify); LISTEN(&xwayland_surface->events.map, &c->map, mapnotify);
@@ -2443,6 +2519,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
LISTEN(&xwayland_surface->events.request_activate, &c->activate, activatex11); LISTEN(&xwayland_surface->events.request_activate, &c->activate, activatex11);
LISTEN(&xwayland_surface->events.request_configure, &c->configure, LISTEN(&xwayland_surface->events.request_configure, &c->configure,
configurex11); configurex11);
LISTEN(&xwayland_surface->events.set_hints, &c->set_hints, sethints);
LISTEN(&xwayland_surface->events.set_title, &c->set_title, updatetitle); LISTEN(&xwayland_surface->events.set_title, &c->set_title, updatetitle);
LISTEN(&xwayland_surface->events.destroy, &c->destroy, destroynotify); LISTEN(&xwayland_surface->events.destroy, &c->destroy, destroynotify);
LISTEN(&xwayland_surface->events.request_fullscreen, &c->fullscreen, LISTEN(&xwayland_surface->events.request_fullscreen, &c->fullscreen,
@@ -2462,6 +2539,16 @@ getatom(xcb_connection_t *xc, const char *name)
return atom; return atom;
} }
void
sethints(struct wl_listener *listener, void *data)
{
Client *c = wl_container_of(listener, c, set_hints);
if (c != selclient()) {
c->isurgent = c->surface.xwayland->hints_urgency;
printstatus();
}
}
void void
xwaylandready(struct wl_listener *listener, void *data) xwaylandready(struct wl_listener *listener, void *data)
{ {
@@ -2500,9 +2587,11 @@ main(int argc, char *argv[])
char *startup_cmd = NULL; char *startup_cmd = NULL;
int c; int c;
while ((c = getopt(argc, argv, "s:h")) != -1) { while ((c = getopt(argc, argv, "s:hv")) != -1) {
if (c == 's') if (c == 's')
startup_cmd = optarg; startup_cmd = optarg;
else if (c == 'v')
die("dwl " VERSION);
else else
goto usage; goto usage;
} }
@@ -2518,5 +2607,5 @@ main(int argc, char *argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
usage: usage:
die("Usage: %s [-s startup command]", argv[0]); die("Usage: %s [-v] [-s startup command]", argv[0]);
} }
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
if git tag --contains HEAD | grep -q $1; then
echo $1
else
branch="$(git rev-parse --abbrev-ref HEAD)"
commit="$(git rev-parse --short HEAD)"
if [ "${branch}" != "main" ]; then
echo $1-$branch-$commit
else
echo $1-$commit
fi
fi