mirror of
https://codeberg.org/dwl/dwl.git
synced 2024-12-27 11:46:31 +00:00
Merge remote-tracking branch 'djpohly/main' into wlroots-next
This commit is contained in:
commit
e0cc5b046c
7 changed files with 436 additions and 272 deletions
97
Makefile
97
Makefile
|
@ -1,73 +1,68 @@
|
||||||
|
.POSIX:
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -pedantic -DVERSION=\"$(VERSION)\"
|
# 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 xcb-icccm 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
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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 dist 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 client.h config.def.h\
|
||||||
|
config.mk protocols dwl.1 dwl.c util.c util.h\
|
||||||
|
dwl-$(VERSION)
|
||||||
|
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 $<
|
||||||
|
|
14
README.md
14
README.md
|
@ -6,7 +6,7 @@ dwl is a compact, hackable compositor for Wayland based on [wlroots](https://git
|
||||||
|
|
||||||
- Easy to understand, hack on, and extend with patches
|
- Easy to understand, hack on, and extend with patches
|
||||||
- One C source file (or a very small number) configurable via `config.h`
|
- One C source file (or a very small number) configurable via `config.h`
|
||||||
- Limited to 2000 SLOC to promote hackability
|
- Limited to 2200 SLOC to promote hackability
|
||||||
- Tied to as few external dependencies as possible
|
- Tied to as few external dependencies as possible
|
||||||
|
|
||||||
dwl is not meant to provide every feature under the sun. Instead, like dwm, it sticks to features which are necessary, simple, and straightforward to implement given the base on which it is built. Implemented default features are:
|
dwl is not meant to provide every feature under the sun. Instead, like dwm, it sticks to features which are necessary, simple, and straightforward to implement given the base on which it is built. Implemented default features are:
|
||||||
|
@ -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).
|
||||||
|
|
134
client.h
134
client.h
|
@ -26,6 +26,28 @@ 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;
|
||||||
|
struct wlr_surface *parent;
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
|
@ -94,6 +116,31 @@ 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)) {
|
||||||
|
xcb_size_hints_t *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)
|
||||||
{
|
{
|
||||||
|
@ -104,42 +151,58 @@ 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->base->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;
|
||||||
xcb_size_hints_t *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
|
||||||
|
client_is_mapped(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->mapped;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -220,38 +283,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))
|
||||||
xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints;
|
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
|
||||||
if (size_hints) {
|
XCB_STACK_MODE_ABOVE);
|
||||||
*width = size_hints->min_width;
|
|
||||||
*height = size_hints->min_height;
|
|
||||||
} else {
|
|
||||||
*width = 0;
|
|
||||||
*height = 0;
|
|
||||||
}
|
|
||||||
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);
|
||||||
|
|
37
config.def.h
37
config.def.h
|
@ -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,7 +51,40 @@ 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
|
||||||
|
|
11
config.mk
11
config.mk
|
@ -1,12 +1,15 @@
|
||||||
_VERSION = 0.3.1
|
_VERSION = 0.3.1
|
||||||
VERSION = $(shell ./generate-version.sh $(_VERSION))
|
VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_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
|
||||||
|
|
378
dwl.c
378
dwl.c
|
@ -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>
|
||||||
|
@ -92,11 +93,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_tree *scene;
|
struct wlr_scene_tree *scene;
|
||||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||||
struct wlr_scene_tree *scene_surface;
|
struct wlr_scene_tree *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 {
|
||||||
|
@ -110,18 +114,16 @@ 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;
|
struct wl_listener set_hints;
|
||||||
#endif
|
#endif
|
||||||
int bw;
|
unsigned int bw;
|
||||||
unsigned int tags;
|
unsigned int tags;
|
||||||
int isfloating, isurgent;
|
int isfloating, isurgent, isfullscreen;
|
||||||
uint32_t resize; /* configure serial of a pending resize */
|
uint32_t resize; /* configure serial of a pending resize */
|
||||||
int isfullscreen;
|
|
||||||
} Client;
|
} Client;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -141,12 +143,14 @@ 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_tree *scene;
|
struct wlr_scene_tree *scene;
|
||||||
struct wlr_scene_layer_surface_v1 *scene_layer;
|
struct wlr_scene_layer_surface_v1 *scene_layer;
|
||||||
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;
|
||||||
|
@ -252,7 +256,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);
|
||||||
|
@ -273,7 +277,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);
|
||||||
|
@ -288,6 +291,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;
|
||||||
|
@ -372,9 +377,17 @@ 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 */
|
if (!c->isfullscreen) {
|
||||||
c->geom.width = MAX(1, c->geom.width);
|
struct wlr_box min = {0}, max = {0};
|
||||||
c->geom.height = MAX(1, c->geom.height);
|
client_get_size_hints(c, &max, &min);
|
||||||
|
/* 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;
|
||||||
|
@ -425,7 +438,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
|
||||||
|
@ -478,11 +491,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);
|
||||||
|
exclusive_focus = layersurface->layer_surface->surface;
|
||||||
if (kb)
|
if (kb)
|
||||||
wlr_seat_keyboard_notify_enter(seat, layersurface->layer_surface->surface,
|
wlr_seat_keyboard_notify_enter(seat, exclusive_focus,
|
||||||
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
||||||
else
|
else
|
||||||
wlr_seat_keyboard_notify_enter(seat, layersurface->layer_surface->surface, NULL, 0, NULL);
|
wlr_seat_keyboard_notify_enter(seat, exclusive_focus, NULL, 0, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,7 +577,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);
|
||||||
|
@ -615,8 +632,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -629,14 +646,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->node,
|
wlr_scene_node_reparent(&layersurface->scene->node,
|
||||||
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;
|
||||||
|
@ -645,19 +661,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 = {0};
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +728,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) {
|
||||||
|
@ -724,7 +747,7 @@ 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_layer = wlr_scene_layer_surface_v1_create(
|
layersurface->scene_layer = wlr_scene_layer_surface_v1_create(
|
||||||
layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
|
layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
|
||||||
|
@ -733,7 +756,7 @@ createlayersurface(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
layersurface->scene->node.data = layersurface;
|
layersurface->scene->node.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
|
||||||
|
@ -741,7 +764,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +775,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
* monitor) becomes available. */
|
* monitor) becomes available. */
|
||||||
struct wlr_output *wlr_output = data;
|
struct wlr_output *wlr_output = data;
|
||||||
const MonitorRule *r;
|
const MonitorRule *r;
|
||||||
|
Client *c;
|
||||||
Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
|
Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
|
||||||
m->wlr_output = wlr_output;
|
m->wlr_output = wlr_output;
|
||||||
|
|
||||||
|
@ -799,16 +823,6 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
*/
|
*/
|
||||||
m->scene_output = wlr_scene_output_create(scene, wlr_output);
|
m->scene_output = wlr_scene_output_create(scene, wlr_output);
|
||||||
wlr_output_layout_add_auto(output_layout, wlr_output);
|
wlr_output_layout_add_auto(output_layout, wlr_output);
|
||||||
|
|
||||||
/* If length == 1 we need update selmon.
|
|
||||||
* Maybe it will change in run(). */
|
|
||||||
if (wl_list_length(&mons) == 1) {
|
|
||||||
Client *c;
|
|
||||||
selmon = m;
|
|
||||||
/* If there is any client, set c->mon to this monitor */
|
|
||||||
wl_list_for_each(c, &clients, link)
|
|
||||||
setmon(c, m, c->tags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -824,13 +838,17 @@ 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 = 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
|
||||||
|
&& l->layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
|
||||||
|
wlr_scene_node_reparent(xdg_surface->surface->data, layers[LyrTop]);
|
||||||
|
if (!l || !l->mon)
|
||||||
return;
|
return;
|
||||||
box = c->mon->m;
|
box = l->type == LayerShell ? l->mon->m : l->mon->w;
|
||||||
box.x -= c->geom.x;
|
box.x -= l->geom.x;
|
||||||
box.y -= c->geom.y;
|
box.y -= l->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)
|
||||||
|
@ -841,7 +859,6 @@ 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);
|
||||||
|
@ -850,7 +867,6 @@ createnotify(struct wl_listener *listener, void *data)
|
||||||
fullscreennotify);
|
fullscreennotify);
|
||||||
LISTEN(&xdg_surface->toplevel->events.request_maximize, &c->maximize,
|
LISTEN(&xdg_surface->toplevel->events.request_maximize, &c->maximize,
|
||||||
maximizenotify);
|
maximizenotify);
|
||||||
c->isfullscreen = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -860,17 +876,39 @@ createpointer(struct wlr_pointer *pointer)
|
||||||
struct libinput_device *libinput_device = (struct libinput_device*)
|
struct libinput_device *libinput_device = (struct libinput_device*)
|
||||||
wlr_libinput_get_device_handle(&pointer->base);
|
wlr_libinput_get_device_handle(&pointer->base);
|
||||||
|
|
||||||
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, &pointer->base);
|
wlr_cursor_attach_input_device(cursor, &pointer->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,17 +936,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->node);
|
||||||
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);
|
||||||
|
@ -929,9 +965,8 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||||
wl_list_remove(&c->configure.link);
|
wl_list_remove(&c->configure.link);
|
||||||
wl_list_remove(&c->set_hints.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,6 +1000,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)
|
||||||
|
@ -979,6 +1017,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);
|
||||||
|
@ -1002,8 +1041,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 (old->role_data && (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);
|
||||||
|
|
||||||
|
@ -1020,15 +1058,6 @@ focusclient(Client *c, int lift)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XWAYLAND
|
|
||||||
/* This resolves an issue where the last spawned xwayland client
|
|
||||||
* receives all pointer activity.
|
|
||||||
*/
|
|
||||||
if (c->type == X11Managed)
|
|
||||||
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
|
|
||||||
XCB_STACK_MODE_ABOVE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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)
|
if (kb)
|
||||||
|
@ -1044,9 +1073,11 @@ focusclient(Client *c, int lift)
|
||||||
void
|
void
|
||||||
focusmon(const Arg *arg)
|
focusmon(const Arg *arg)
|
||||||
{
|
{
|
||||||
do
|
int i = 0, nmons = wl_list_length(&mons);
|
||||||
|
if (nmons)
|
||||||
|
do /* don't switch to disabled mons */
|
||||||
selmon = dirtomon(arg->i);
|
selmon = dirtomon(arg->i);
|
||||||
while (!selmon->wlr_output->enabled);
|
while (!selmon->wlr_output->enabled && i++ < nmons);
|
||||||
focusclient(focustop(selmon), 1);
|
focusclient(focustop(selmon), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1222,8 +1253,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1231,15 +1263,21 @@ 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]);
|
c->scene = wlr_scene_tree_create(layers[LyrTile]);
|
||||||
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->node.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->node.data = c->scene_surface->node.data = c;
|
||||||
|
|
||||||
if (client_is_unmanaged(c)) {
|
if (client_is_unmanaged(c)) {
|
||||||
client_get_geometry(c, &c->geom);
|
client_get_geometry(c, &c->geom);
|
||||||
|
@ -1254,7 +1292,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 */
|
||||||
|
@ -1268,7 +1305,15 @@ 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->node, layers[LyrFloat]);
|
||||||
|
/* TODO recheck if !p->mon is possible with wlroots 0.16.0 */
|
||||||
|
setmon(c, p->mon ? p->mon : selmon, p->tags);
|
||||||
|
} else {
|
||||||
applyrules(c);
|
applyrules(c);
|
||||||
|
}
|
||||||
printstatus();
|
printstatus();
|
||||||
|
|
||||||
if (c->isfullscreen)
|
if (c->isfullscreen)
|
||||||
|
@ -1297,7 +1342,7 @@ 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);
|
focusclient(focustop(m), 1);
|
||||||
}
|
}
|
||||||
|
@ -1339,13 +1384,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,11 +1468,27 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
||||||
struct wlr_output_configuration_head_v1 *config_head;
|
struct wlr_output_configuration_head_v1 *config_head;
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
|
/* First disable outputs we need to disable */
|
||||||
wl_list_for_each(config_head, &config->heads, link) {
|
wl_list_for_each(config_head, &config->heads, link) {
|
||||||
struct wlr_output *wlr_output = config_head->state.output;
|
struct wlr_output *wlr_output = config_head->state.output;
|
||||||
|
if (!wlr_output->enabled || config_head->state.enabled)
|
||||||
|
continue;
|
||||||
|
wlr_output_enable(wlr_output, 0);
|
||||||
|
if (test) {
|
||||||
|
ok &= wlr_output_test(wlr_output);
|
||||||
|
wlr_output_rollback(wlr_output);
|
||||||
|
} else {
|
||||||
|
ok &= wlr_output_commit(wlr_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wlr_output_enable(wlr_output, config_head->state.enabled);
|
/* Then enable outputs that need to */
|
||||||
if (config_head->state.enabled) {
|
wl_list_for_each(config_head, &config->heads, link) {
|
||||||
|
struct wlr_output *wlr_output = config_head->state.output;
|
||||||
|
if (!config_head->state.enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wlr_output_enable(wlr_output, 1);
|
||||||
if (config_head->state.mode)
|
if (config_head->state.mode)
|
||||||
wlr_output_set_mode(wlr_output, config_head->state.mode);
|
wlr_output_set_mode(wlr_output, config_head->state.mode);
|
||||||
else
|
else
|
||||||
|
@ -1441,17 +1501,31 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
||||||
config_head->state.x, config_head->state.y);
|
config_head->state.x, config_head->state.y);
|
||||||
wlr_output_set_transform(wlr_output, config_head->state.transform);
|
wlr_output_set_transform(wlr_output, config_head->state.transform);
|
||||||
wlr_output_set_scale(wlr_output, config_head->state.scale);
|
wlr_output_set_scale(wlr_output, config_head->state.scale);
|
||||||
|
|
||||||
|
if (test) {
|
||||||
|
ok &= wlr_output_test(wlr_output);
|
||||||
|
wlr_output_rollback(wlr_output);
|
||||||
|
} else {
|
||||||
|
int output_ok = 1;
|
||||||
|
/* If it's a custom mode to avoid an assertion failed in wlr_output_commit()
|
||||||
|
* we test if that mode does not fail rather than just call wlr_output_commit().
|
||||||
|
* We do not test normal modes because (at least in my hardware (@sevz17))
|
||||||
|
* wlr_output_test() fails even if that mode can actually be set */
|
||||||
|
if (!config_head->state.mode)
|
||||||
|
ok &= (output_ok = wlr_output_test(wlr_output)
|
||||||
|
&& wlr_output_commit(wlr_output));
|
||||||
|
else
|
||||||
|
ok &= wlr_output_commit(wlr_output);
|
||||||
|
|
||||||
|
/* In custom modes we call wlr_output_test(), it it fails
|
||||||
|
* we need to rollback, and normal modes seems to does not cause
|
||||||
|
* assertions failed in wlr_output_commit() which rollback
|
||||||
|
* the output on failure */
|
||||||
|
if (!output_ok)
|
||||||
|
wlr_output_rollback(wlr_output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ok = wlr_output_test(wlr_output)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wl_list_for_each(config_head, &config->heads, link) {
|
|
||||||
if (ok && !test)
|
|
||||||
wlr_output_commit(config_head->state.output);
|
|
||||||
else
|
|
||||||
wlr_output_rollback(config_head->state.output);
|
|
||||||
}
|
|
||||||
if (ok)
|
if (ok)
|
||||||
wlr_output_configuration_v1_send_succeeded(config);
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
else
|
else
|
||||||
|
@ -1528,7 +1602,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
|
||||||
|
@ -1577,16 +1650,23 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
resize(Client *c, int x, int y, int w, int h, int interact)
|
requeststartdrag(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct wlr_seat_request_start_drag_event *event = data;
|
||||||
|
|
||||||
|
if (wlr_seat_validate_pointer_grab_serial(seat, event->origin,
|
||||||
|
event->serial))
|
||||||
|
wlr_seat_start_pointer_drag(seat, event->drag, event->serial);
|
||||||
|
else
|
||||||
|
wlr_data_source_destroy(event->drag->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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_set_bounds(c, w, h);
|
client_set_bounds(c, geo.width, geo.height);
|
||||||
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 */
|
||||||
|
@ -1605,23 +1685,9 @@ resize(Client *c, int x, int y, int w, int h, int interact)
|
||||||
c->geom.height - 2 * c->bw);
|
c->geom.height - 2 * c->bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
requeststartdrag(struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
struct wlr_seat_request_start_drag_event *event = data;
|
|
||||||
|
|
||||||
if (wlr_seat_validate_pointer_grab_serial(seat, event->origin,
|
|
||||||
event->serial))
|
|
||||||
wlr_seat_start_pointer_drag(seat, event->drag, event->serial);
|
|
||||||
else
|
|
||||||
wlr_data_source_destroy(event->drag->source);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1633,9 +1699,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]);
|
||||||
|
@ -1671,11 +1737,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 *
|
||||||
|
@ -1724,11 +1785,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();
|
||||||
|
@ -1777,7 +1856,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);
|
||||||
|
@ -1810,6 +1889,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();
|
||||||
|
@ -2032,7 +2114,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)
|
||||||
|
@ -2050,12 +2132,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++;
|
||||||
|
@ -2109,22 +2191,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->node, 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)
|
||||||
{
|
{
|
||||||
|
@ -2146,6 +2226,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->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
@ -2162,6 +2243,7 @@ updatemons(struct wl_listener *listener, void *data)
|
||||||
*/
|
*/
|
||||||
struct wlr_output_configuration_v1 *config =
|
struct wlr_output_configuration_v1 *config =
|
||||||
wlr_output_configuration_v1_create();
|
wlr_output_configuration_v1_create();
|
||||||
|
Client *c;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
wlr_output_layout_get_box(output_layout, NULL, &sgeom);
|
wlr_output_layout_get_box(output_layout, NULL, &sgeom);
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
@ -2186,6 +2268,11 @@ updatemons(struct wl_listener *listener, void *data)
|
||||||
config_head->state.y = m->m.y;
|
config_head->state.y = m->m.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selmon && selmon->wlr_output->enabled)
|
||||||
|
wl_list_for_each(c, &clients, link)
|
||||||
|
if (!c->mon && client_is_mapped(c))
|
||||||
|
setmon(c, selmon, c->tags);
|
||||||
|
|
||||||
wlr_output_manager_v1_set_configuration(output_mgr, config);
|
wlr_output_manager_v1_set_configuration(output_mgr, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2201,12 +2288,8 @@ 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 (c && c != selclient()) {
|
||||||
if (!wlr_surface_is_xdg_surface(event->surface))
|
|
||||||
return;
|
|
||||||
c = wlr_xdg_surface_from_wlr_surface(event->surface)->data;
|
|
||||||
if (c != selclient()) {
|
|
||||||
c->isurgent = 1;
|
c->isurgent = 1;
|
||||||
printstatus();
|
printstatus();
|
||||||
}
|
}
|
||||||
|
@ -2339,7 +2422,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);
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#!/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
|
|
Loading…
Reference in a new issue