mirror of
https://codeberg.org/dwl/dwl.git
synced 2026-06-21 14:42:44 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31d8a67eda | |||
| b04c73be3d | |||
| 8cdb997126 | |||
| 90a12c90a0 | |||
| e082292606 | |||
| deb48ff48b | |||
| c70db2d06a | |||
| e98719f552 | |||
| af12e777f2 | |||
| 8e03bce621 | |||
| 87fc3a58ab | |||
| 0eff78d6c2 | |||
| c6d97f1db7 | |||
| 829dec6598 | |||
| ff70337c16 | |||
| 7cc6c640e2 | |||
| 72e0a560d9 | |||
| 2aa391361c | |||
| 549335ae54 | |||
| 097b4a30f5 | |||
| c1578bc14d | |||
| 9b84940e37 | |||
| 79ad72413d | |||
| 74fce9d918 | |||
| 553ba5b7c8 | |||
| 4ae6d0f387 | |||
| 2ef5abfb72 | |||
| 8076b47cc6 | |||
| 3a77f02919 | |||
| d26ddfc7fd | |||
| 671a9b450b | |||
| 583f471cfe | |||
| 8bce3b1583 | |||
| c008bf2a7d | |||
| c990dbd441 | |||
| d969289baf | |||
| 50b6630f3d | |||
| 14641560b0 | |||
| 7b42232ad1 | |||
| a5a0674f6a | |||
| 4dfa45659a | |||
| b91017e713 | |||
| 70da04a714 | |||
| 2623a96ebf | |||
| 52e0d00942 | |||
| 7018b9b65c | |||
| 48ec914f43 | |||
| 40449fa64f | |||
| ecbc2c61db | |||
| 8870ba0bb8 | |||
| 5de68ba713 | |||
| 2f8736b986 | |||
| 3c11ad9aa6 | |||
| 06d9230a96 | |||
| 22bd75226b | |||
| 063736f898 | |||
| d5a741c9b4 | |||
| 5d8084daa7 | |||
| 07d56c6d7b | |||
| e0d310fd84 | |||
| 3a4b7d104f | |||
| d071a899f3 | |||
| a48ce99e6a |
@@ -1,64 +1,69 @@
|
||||
.POSIX:
|
||||
.SUFFIXES:
|
||||
|
||||
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_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
|
||||
# Wayland utils
|
||||
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 += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
|
||||
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
|
||||
# CFLAGS / LDFLAGS
|
||||
PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS)
|
||||
DWLCFLAGS = `pkg-config --cflags $(PKGS)` $(DWLCPPFLAGS) $(CFLAGS) $(XWAYLAND)
|
||||
LDLIBS = `pkg-config --libs $(PKGS)` $(LIBS)
|
||||
|
||||
all: dwl
|
||||
|
||||
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
|
||||
# build rules
|
||||
|
||||
# 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
|
||||
# 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:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
$(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:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
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:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
protocols/idle.xml $@
|
||||
|
||||
idle-protocol.c:
|
||||
$(WAYLAND_SCANNER) private-code \
|
||||
protocols/idle.xml $@
|
||||
|
||||
idle-protocol.o: idle-protocol.h
|
||||
|
||||
config.h: | config.def.h
|
||||
config.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 $<
|
||||
|
||||
@@ -37,7 +37,9 @@ Feature *non-goals* for the main codebase include:
|
||||
|
||||
## 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`.
|
||||
|
||||
@@ -71,6 +73,14 @@ If your startup command is a shell script, you can achieve the same inside the s
|
||||
|
||||
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
|
||||
|
||||
You can find a [list of Wayland applications on the sway wiki](https://github.com/swaywm/sway/wiki/i3-Migration-Guide).
|
||||
|
||||
@@ -26,20 +26,42 @@ client_surface(Client *c)
|
||||
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 */
|
||||
static inline void
|
||||
client_activate_surface(struct wlr_surface *s, int activated)
|
||||
{
|
||||
struct wlr_xdg_surface *surface;
|
||||
#ifdef XWAYLAND
|
||||
if (wlr_surface_is_xwayland_surface(s)) {
|
||||
wlr_xwayland_surface_activate(
|
||||
wlr_xwayland_surface_from_wlr_surface(s), activated);
|
||||
struct wlr_xwayland_surface *xsurface;
|
||||
if (wlr_surface_is_xwayland_surface(s)
|
||||
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(s))) {
|
||||
wlr_xwayland_surface_activate(xsurface, activated);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (wlr_surface_is_xdg_surface(s))
|
||||
wlr_xdg_toplevel_set_activated(
|
||||
wlr_xdg_surface_from_wlr_surface(s), activated);
|
||||
if (wlr_surface_is_xdg_surface(s)
|
||||
&& (surface = wlr_xdg_surface_from_wlr_surface(s))
|
||||
&& surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
wlr_xdg_toplevel_set_activated(surface, activated);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 *
|
||||
client_get_title(Client *c)
|
||||
{
|
||||
@@ -88,42 +136,48 @@ client_get_title(Client *c)
|
||||
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
|
||||
client_is_float_type(Client *c)
|
||||
{
|
||||
struct wlr_xdg_toplevel *toplevel;
|
||||
struct wlr_xdg_toplevel_state state;
|
||||
struct wlr_box min = {0}, max = {0};
|
||||
client_get_size_hints(c, &max, &min);
|
||||
|
||||
#ifdef XWAYLAND
|
||||
if (client_is_x11(c)) {
|
||||
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||
struct wlr_xwayland_surface_size_hints *size_hints;
|
||||
if (surface->modal)
|
||||
return 1;
|
||||
|
||||
for (size_t i = 0; i < surface->window_type_len; i++)
|
||||
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog] ||
|
||||
surface->window_type[i] == netatom[NetWMWindowTypeSplash] ||
|
||||
surface->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
|
||||
surface->window_type[i] == netatom[NetWMWindowTypeUtility])
|
||||
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeSplash]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeToolbar]
|
||||
|| surface->window_type[i] == netatom[NetWMWindowTypeUtility])
|
||||
return 1;
|
||||
|
||||
size_hints = surface->size_hints;
|
||||
if (size_hints && size_hints->min_width > 0 && size_hints->min_height > 0
|
||||
&& (size_hints->max_width == size_hints->min_width ||
|
||||
size_hints->max_height == size_hints->min_height))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
|
||||
&& (min.width == max.width || min.height == max.height))
|
||||
|| c->surface.xwayland->parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
toplevel = c->surface.xdg->toplevel;
|
||||
state = toplevel->current;
|
||||
return (state.min_width != 0 && state.min_height != 0
|
||||
&& (state.min_width == state.max_width
|
||||
|| state.min_height == state.max_height))
|
||||
|| toplevel->parent;
|
||||
return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
|
||||
&& (min.width == max.width || min.height == max.height))
|
||||
|| c->surface.xdg->toplevel->parent;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -204,34 +258,27 @@ client_surface_at(Client *c, double cx, double cy, double *sx, double *sy)
|
||||
}
|
||||
|
||||
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
|
||||
if (client_is_x11(c)) {
|
||||
struct wlr_xwayland_surface_size_hints *size_hints;
|
||||
size_hints = c->surface.xwayland->size_hints;
|
||||
*width = size_hints->min_width;
|
||||
*height = size_hints->min_height;
|
||||
return;
|
||||
}
|
||||
if (client_is_x11(c))
|
||||
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
|
||||
XCB_STACK_MODE_ABOVE);
|
||||
#endif
|
||||
toplevel = c->surface.xdg->toplevel;
|
||||
state = &toplevel->current;
|
||||
*width = state->min_width;
|
||||
*height = state->min_height;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline Client *
|
||||
client_from_popup(struct wlr_xdg_popup *popup)
|
||||
static inline void *
|
||||
toplevel_from_popup(struct wlr_xdg_popup *popup)
|
||||
{
|
||||
struct wlr_xdg_surface *surface = popup->base;
|
||||
|
||||
while (1) {
|
||||
switch (surface->role) {
|
||||
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||
if (!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;
|
||||
|
||||
surface = wlr_xdg_surface_from_wlr_surface(surface->popup->parent);
|
||||
|
||||
+53
-18
@@ -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 bordercolor[] = {0.5, 0.5, 0.5, 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 */
|
||||
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:
|
||||
.options = "ctrl:nocaps",
|
||||
*/
|
||||
.options = "",
|
||||
.options = NULL,
|
||||
};
|
||||
|
||||
static const int repeat_rate = 25;
|
||||
@@ -49,15 +51,48 @@ static const int repeat_delay = 600;
|
||||
|
||||
/* Trackpad */
|
||||
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 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 */
|
||||
#define MODKEY WLR_MODIFIER_ALT
|
||||
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.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 */
|
||||
#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_Return, zoom, {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_f, setlayout, {.v = &layouts[1]} },
|
||||
{ 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, XKB_KEY_e, togglefullscreen, {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_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
|
||||
TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
|
||||
TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5),
|
||||
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_comma, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_period, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
TAGKEYS( XKB_KEY_1, 0),
|
||||
TAGKEYS( XKB_KEY_2, 1),
|
||||
TAGKEYS( XKB_KEY_3, 2),
|
||||
TAGKEYS( XKB_KEY_4, 3),
|
||||
TAGKEYS( XKB_KEY_5, 4),
|
||||
TAGKEYS( XKB_KEY_6, 5),
|
||||
TAGKEYS( XKB_KEY_7, 6),
|
||||
TAGKEYS( XKB_KEY_8, 7),
|
||||
TAGKEYS( XKB_KEY_9, 8),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_q, quit, {0} },
|
||||
|
||||
/* 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} },
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
_VERSION = 0.3.1
|
||||
VERSION = `./generate-version.sh $(_VERSION)`
|
||||
|
||||
# paths
|
||||
PREFIX = /usr/local
|
||||
MANDIR = $(PREFIX)/share/man
|
||||
|
||||
# Default compile flags (overridable by environment)
|
||||
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement
|
||||
# Compile flags that can be used
|
||||
#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
|
||||
#CFLAGS += -DXWAYLAND
|
||||
#XWAYLAND = -DXWAYLAND
|
||||
#XLIBS = xcb
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
.Nd dwm for Wayland
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl s Ar command
|
||||
.Op Fl v
|
||||
.Op Fl s Ar startup command
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
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.
|
||||
.Pp
|
||||
When given the
|
||||
.Fl v
|
||||
option,
|
||||
.Nm
|
||||
writes its name and version to standard error and exits unsuccessfully.
|
||||
.Pp
|
||||
When given the
|
||||
.Fl s
|
||||
option,
|
||||
.Nm
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <limits.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
@@ -90,11 +91,14 @@ typedef struct {
|
||||
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct {
|
||||
/* Must be first */
|
||||
/* Must keep these three elements in this order */
|
||||
unsigned int type; /* XDGShell or X11* */
|
||||
struct wlr_box geom; /* layout-relative, includes border */
|
||||
Monitor *mon;
|
||||
struct wlr_scene_node *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
struct wlr_scene_node *scene_surface;
|
||||
struct wlr_scene_rect *fullscreen_bg; /* See setfullscreen() for info */
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
union {
|
||||
@@ -107,11 +111,11 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener set_title;
|
||||
struct wl_listener fullscreen;
|
||||
struct wlr_box geom, prev; /* layout-relative, includes border */
|
||||
Monitor *mon;
|
||||
struct wlr_box prev; /* layout-relative, includes border */
|
||||
#ifdef XWAYLAND
|
||||
struct wl_listener activate;
|
||||
struct wl_listener configure;
|
||||
struct wl_listener set_hints;
|
||||
#endif
|
||||
int bw;
|
||||
unsigned int tags;
|
||||
@@ -145,19 +149,19 @@ typedef struct {
|
||||
} Keyboard;
|
||||
|
||||
typedef struct {
|
||||
/* Must be first */
|
||||
/* Must keep these three elements in this order */
|
||||
unsigned int type; /* LayerShell */
|
||||
int mapped;
|
||||
struct wlr_box geom;
|
||||
Monitor *mon;
|
||||
struct wlr_scene_node *scene;
|
||||
struct wl_list link;
|
||||
int mapped;
|
||||
struct wlr_layer_surface_v1 *layer_surface;
|
||||
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener surface_commit;
|
||||
|
||||
struct wlr_box geo;
|
||||
} LayerSurface;
|
||||
|
||||
typedef struct {
|
||||
@@ -259,7 +263,7 @@ static void quit(const Arg *arg);
|
||||
static void quitsignal(int signo);
|
||||
static void rendermon(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 Client *selclient(void);
|
||||
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 toggletag(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 unmapnotify(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 */
|
||||
static const char broken[] = "broken";
|
||||
static pid_t child_pid = -1;
|
||||
static struct wlr_surface *exclusive_focus;
|
||||
static struct wl_display *dpy;
|
||||
static struct wlr_backend *backend;
|
||||
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 createnotifyx11(struct wl_listener *listener, void *data);
|
||||
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 struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
||||
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
|
||||
@@ -378,9 +384,15 @@ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
{
|
||||
/* set minimum possible */
|
||||
c->geom.width = MAX(1, c->geom.width);
|
||||
c->geom.height = MAX(1, c->geom.height);
|
||||
struct wlr_box min = {0}, max = {0};
|
||||
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)
|
||||
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
||||
@@ -486,7 +498,7 @@ arrange(Monitor *m)
|
||||
|
||||
if (m->lt[m->sellt]->arrange)
|
||||
m->lt[m->sellt]->arrange(m);
|
||||
/* TODO recheck pointer focus here... or in resize()? */
|
||||
motionnotify(0);
|
||||
}
|
||||
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
layersurface->geo = box;
|
||||
layersurface->geom = box;
|
||||
|
||||
if (state->exclusive_zone > 0)
|
||||
applyexclusive(usable_area, state->anchor, state->exclusive_zone,
|
||||
@@ -600,8 +612,12 @@ arrangelayers(Monitor *m)
|
||||
layersurface->layer_surface->mapped) {
|
||||
/* Deactivate the focused client. */
|
||||
focusclient(NULL, 0);
|
||||
wlr_seat_keyboard_notify_enter(seat, layersurface->layer_surface->surface,
|
||||
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
||||
exclusive_focus = layersurface->layer_surface->surface;
|
||||
if (kb)
|
||||
wlr_seat_keyboard_notify_enter(seat, exclusive_focus,
|
||||
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
||||
else
|
||||
wlr_seat_keyboard_notify_enter(seat, exclusive_focus, NULL, 0, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -641,7 +657,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
focusclient(c, 1);
|
||||
|
||||
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++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
|
||||
event->button == b->button && b->func) {
|
||||
@@ -682,7 +698,10 @@ cleanup(void)
|
||||
wlr_xwayland_destroy(xwayland);
|
||||
#endif
|
||||
wl_display_destroy_clients(dpy);
|
||||
|
||||
if (child_pid > 0) {
|
||||
kill(child_pid, SIGTERM);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
}
|
||||
wlr_backend_destroy(backend);
|
||||
wlr_xcursor_manager_destroy(cursor_mgr);
|
||||
wlr_cursor_destroy(cursor);
|
||||
@@ -735,11 +754,12 @@ closemon(Monitor *m)
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->isfloating && c->geom.x > m->m.width)
|
||||
resize(c, c->geom.x - m->w.width, c->geom.y,
|
||||
c->geom.width, c->geom.height, 0);
|
||||
resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
|
||||
.width = c->geom.width, .height = c->geom.height}, 0);
|
||||
if (c->mon == m)
|
||||
setmon(c, selmon, c->tags);
|
||||
}
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -748,14 +768,13 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
LayerSurface *layersurface = wl_container_of(listener, layersurface, surface_commit);
|
||||
struct wlr_layer_surface_v1 *wlr_layer_surface = layersurface->layer_surface;
|
||||
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,
|
||||
layers[wlr_layer_surface->current.layer]);
|
||||
|
||||
if (!wlr_output || !(m = wlr_output->data))
|
||||
return;
|
||||
|
||||
if (wlr_layer_surface->current.committed == 0
|
||||
&& layersurface->mapped == wlr_layer_surface->mapped)
|
||||
return;
|
||||
@@ -764,19 +783,27 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
|
||||
if (layers[wlr_layer_surface->current.layer] != layersurface->scene) {
|
||||
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);
|
||||
}
|
||||
arrangelayers(m);
|
||||
arrangelayers(layersurface->mon);
|
||||
}
|
||||
|
||||
void
|
||||
commitnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -823,7 +850,6 @@ createlayersurface(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_layer_surface_v1 *wlr_layer_surface = data;
|
||||
LayerSurface *layersurface;
|
||||
Monitor *m;
|
||||
struct wlr_layer_surface_v1_state old_state;
|
||||
|
||||
if (!wlr_layer_surface->output) {
|
||||
@@ -843,14 +869,14 @@ createlayersurface(struct wl_listener *listener, void *data)
|
||||
|
||||
layersurface->layer_surface = wlr_layer_surface;
|
||||
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 =
|
||||
wlr_scene_subsurface_tree_create(layers[wlr_layer_surface->pending.layer],
|
||||
wlr_layer_surface->surface);
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
wlr_layer_surface->current = wlr_layer_surface->pending;
|
||||
arrangelayers(m);
|
||||
arrangelayers(layersurface->mon);
|
||||
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) {
|
||||
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->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;
|
||||
box = c->mon->m;
|
||||
box = c->type == LayerShell ? c->mon->m : c->mon->w;
|
||||
box.x -= c->geom.x;
|
||||
box.y -= c->geom.y;
|
||||
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->bw = borderpx;
|
||||
|
||||
LISTEN(&xdg_surface->surface->events.commit, &c->commit, commitnotify);
|
||||
LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
|
||||
LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
|
||||
LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
|
||||
LISTEN(&xdg_surface->toplevel->events.set_title, &c->set_title, updatetitle);
|
||||
LISTEN(&xdg_surface->toplevel->events.request_fullscreen, &c->fullscreen,
|
||||
fullscreennotify);
|
||||
c->isfullscreen = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -975,17 +1004,39 @@ createpointer(struct wlr_input_device *device)
|
||||
struct libinput_device *libinput_device = (struct libinput_device*)
|
||||
wlr_libinput_get_device_handle(device);
|
||||
|
||||
if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device))
|
||||
libinput_device_config_tap_set_enabled(libinput_device, LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
if (libinput_device_config_tap_get_finger_count(libinput_device)) {
|
||||
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))
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1013,17 +1064,15 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
LayerSurface *layersurface = wl_container_of(listener, layersurface, destroy);
|
||||
|
||||
if (layersurface->layer_surface->mapped)
|
||||
unmaplayersurface(layersurface);
|
||||
wl_list_remove(&layersurface->link);
|
||||
wl_list_remove(&layersurface->destroy.link);
|
||||
wl_list_remove(&layersurface->map.link);
|
||||
wl_list_remove(&layersurface->unmap.link);
|
||||
wl_list_remove(&layersurface->surface_commit.link);
|
||||
wlr_scene_node_destroy(layersurface->scene);
|
||||
if (layersurface->layer_surface->output) {
|
||||
Monitor *m = layersurface->layer_surface->output->data;
|
||||
if (m)
|
||||
arrangelayers(m);
|
||||
if ((layersurface->mon = layersurface->layer_surface->output->data))
|
||||
arrangelayers(layersurface->mon);
|
||||
layersurface->layer_surface->output = NULL;
|
||||
}
|
||||
free(layersurface);
|
||||
@@ -1042,10 +1091,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->configure.link);
|
||||
wl_list_remove(&c->set_hints.link);
|
||||
wl_list_remove(&c->activate.link);
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
wl_list_remove(&c->commit.link);
|
||||
free(c);
|
||||
}
|
||||
|
||||
@@ -1079,6 +1128,9 @@ focusclient(Client *c, int lift)
|
||||
struct wlr_surface *old = seat->keyboard_state.focused_surface;
|
||||
struct wlr_keyboard *kb;
|
||||
int i;
|
||||
/* Do not focus clients if a layer surface is focused */
|
||||
if (exclusive_focus)
|
||||
return;
|
||||
|
||||
/* Raise client in stacking order if requested */
|
||||
if (c && lift)
|
||||
@@ -1093,6 +1145,7 @@ focusclient(Client *c, int lift)
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
selmon = c->mon;
|
||||
c->isurgent = 0;
|
||||
client_restack_surface(c);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
wlr_scene_rect_set_color(c->border[i], focuscolor);
|
||||
@@ -1116,8 +1169,7 @@ focusclient(Client *c, int lift)
|
||||
return;
|
||||
} else {
|
||||
Client *w;
|
||||
struct wlr_scene_node *node = old->data;
|
||||
if ((w = node->data))
|
||||
if ((w = client_from_wlr_surface(old)))
|
||||
for (i = 0; i < 4; i++)
|
||||
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 */
|
||||
kb = wlr_seat_get_keyboard(seat);
|
||||
wlr_seat_keyboard_notify_enter(seat, client_surface(c),
|
||||
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
||||
if (kb)
|
||||
wlr_seat_keyboard_notify_enter(seat, client_surface(c),
|
||||
kb->keycodes, kb->num_keycodes, &kb->modifiers);
|
||||
else
|
||||
wlr_seat_keyboard_notify_enter(seat, client_surface(c), NULL, 0, NULL);
|
||||
|
||||
/* Activate the new client */
|
||||
client_activate_surface(client_surface(c), 1);
|
||||
@@ -1271,8 +1326,10 @@ keypress(struct wl_listener *listener, void *data)
|
||||
uint32_t keycode = event->keycode + 8;
|
||||
/* Get a list of keysyms based on the keymap for this keyboard */
|
||||
const xkb_keysym_t *syms;
|
||||
int nsyms = xkb_state_key_get_syms(
|
||||
kb->device->keyboard->xkb_state, keycode, &syms);
|
||||
xkb_layout_index_t layout_index = xkb_state_key_get_layout(
|
||||
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;
|
||||
uint32_t mods = wlr_keyboard_get_modifiers(kb->device->keyboard);
|
||||
@@ -1324,8 +1381,9 @@ void
|
||||
maplayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
LayerSurface *layersurface = wl_container_of(listener, layersurface, map);
|
||||
layersurface->mon = layersurface->layer_surface->output->data;
|
||||
wlr_surface_send_enter(layersurface->layer_surface->surface,
|
||||
layersurface->layer_surface->output);
|
||||
layersurface->mon->wlr_output);
|
||||
motionnotify(0);
|
||||
}
|
||||
|
||||
@@ -1333,15 +1391,23 @@ void
|
||||
mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* Create scene tree for this client and its border */
|
||||
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_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)) {
|
||||
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]->node.data = c;
|
||||
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 */
|
||||
@@ -1370,7 +1435,14 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
|
||||
/* Set initial monitor, tags, floating status, and focus */
|
||||
applyrules(c);
|
||||
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);
|
||||
}
|
||||
printstatus();
|
||||
|
||||
if (c->isfullscreen)
|
||||
@@ -1387,8 +1459,9 @@ monocle(Monitor *m)
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
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
|
||||
@@ -1428,13 +1501,12 @@ motionnotify(uint32_t time)
|
||||
/* If we are currently grabbing the mouse, handle and return */
|
||||
if (cursor_mode == CurMove) {
|
||||
/* Move the grabbed client to the new position. */
|
||||
resize(grabc, cursor->x - grabcx, cursor->y - grabcy,
|
||||
grabc->geom.width, grabc->geom.height, 1);
|
||||
resize(grabc, (struct wlr_box){.x = cursor->x - grabcx, .y = cursor->y - grabcy,
|
||||
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
||||
return;
|
||||
} else if (cursor_mode == CurResize) {
|
||||
resize(grabc, grabc->geom.x, grabc->geom.y,
|
||||
cursor->x - grabc->geom.x,
|
||||
cursor->y - grabc->geom.y, 1);
|
||||
resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
.width = cursor->x - grabc->geom.x, .height = cursor->y - grabc->geom.y}, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1617,7 +1689,6 @@ printstatus(void)
|
||||
sel, urg);
|
||||
printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1678,15 +1749,10 @@ requeststartdrag(struct wl_listener *listener, void *data)
|
||||
}
|
||||
|
||||
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;
|
||||
client_min_size(c, &min_width, &min_height);
|
||||
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);
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
/* Update scene-graph, including borders */
|
||||
@@ -1708,8 +1774,6 @@ resize(Client *c, int x, int y, int w, int h, int interact)
|
||||
void
|
||||
run(char *startup_cmd)
|
||||
{
|
||||
pid_t startup_pid = -1;
|
||||
|
||||
/* Add a Unix socket to the Wayland display. */
|
||||
const char *socket = wl_display_add_socket_auto(dpy);
|
||||
if (!socket)
|
||||
@@ -1721,9 +1785,9 @@ run(char *startup_cmd)
|
||||
int piperw[2];
|
||||
if (pipe(piperw) < 0)
|
||||
die("startup: pipe:");
|
||||
if ((startup_pid = fork()) < 0)
|
||||
if ((child_pid = fork()) < 0)
|
||||
die("startup: fork:");
|
||||
if (startup_pid == 0) {
|
||||
if (child_pid == 0) {
|
||||
dup2(piperw[0], STDIN_FILENO);
|
||||
close(piperw[0]);
|
||||
close(piperw[1]);
|
||||
@@ -1759,11 +1823,6 @@ run(char *startup_cmd)
|
||||
* loop configuration to listen to libinput events, DRM events, generate
|
||||
* frame events at the refresh rate, and so on. */
|
||||
wl_display_run(dpy);
|
||||
|
||||
if (startup_cmd) {
|
||||
kill(startup_pid, SIGTERM);
|
||||
waitpid(startup_pid, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Client *
|
||||
@@ -1812,11 +1871,29 @@ setfullscreen(Client *c, int fullscreen)
|
||||
|
||||
if (fullscreen) {
|
||||
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 {
|
||||
/* restore previous size instead of arrange for floating windows since
|
||||
* 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);
|
||||
printstatus();
|
||||
@@ -1865,7 +1942,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags)
|
||||
}
|
||||
if (m) {
|
||||
/* 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);
|
||||
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||
arrange(m);
|
||||
@@ -1898,6 +1975,9 @@ setsel(struct wl_listener *listener, void *data)
|
||||
void
|
||||
setup(void)
|
||||
{
|
||||
/* Force line-buffered stdout */
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
/* The Wayland display is managed by libwayland. It handles accepting
|
||||
* clients from the Unix socket, manging Wayland globals, and so on. */
|
||||
dpy = wl_display_create();
|
||||
@@ -2075,10 +2155,12 @@ sigchld(int unused)
|
||||
* but the Xwayland implementation in wlroots currently prevents us from
|
||||
* setting our own disposition for SIGCHLD.
|
||||
*/
|
||||
pid_t pid;
|
||||
if (signal(SIGCHLD, sigchld) == SIG_ERR)
|
||||
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
|
||||
@@ -2129,7 +2211,7 @@ tagmon(const Arg *arg)
|
||||
void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int i, n = 0, h, mw, my, ty;
|
||||
unsigned int i, n = 0, mw, my, ty;
|
||||
Client *c;
|
||||
|
||||
wl_list_for_each(c, &clients, link)
|
||||
@@ -2147,12 +2229,12 @@ tile(Monitor *m)
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
|
||||
resize(c, m->w.x, m->w.y + my, mw, h, 0);
|
||||
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
.height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
my += c->geom.height;
|
||||
} else {
|
||||
h = (m->w.height - ty) / (n - i);
|
||||
resize(c, m->w.x + mw, m->w.y + ty, m->w.width - mw, h, 0);
|
||||
resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
.width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
|
||||
ty += c->geom.height;
|
||||
}
|
||||
i++;
|
||||
@@ -2206,22 +2288,20 @@ toggleview(const Arg *arg)
|
||||
}
|
||||
|
||||
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 ==
|
||||
seat->keyboard_state.focused_surface)
|
||||
focusclient(selclient(), 1);
|
||||
motionnotify(0);
|
||||
}
|
||||
|
||||
void
|
||||
unmaplayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
LayerSurface *layersurface = wl_container_of(listener, layersurface, unmap);
|
||||
unmaplayersurface(layersurface);
|
||||
}
|
||||
|
||||
void
|
||||
unmapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2243,6 +2323,7 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->link);
|
||||
setmon(c, NULL, 0);
|
||||
wl_list_remove(&c->flink);
|
||||
wl_list_remove(&c->commit.link);
|
||||
wlr_scene_node_destroy(c->scene);
|
||||
printstatus();
|
||||
}
|
||||
@@ -2297,11 +2378,7 @@ void
|
||||
urgent(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_xdg_activation_v1_request_activate_event *event = data;
|
||||
Client *c;
|
||||
|
||||
if (!wlr_surface_is_xdg_surface(event->surface))
|
||||
return;
|
||||
c = wlr_xdg_surface_from_wlr_surface(event->surface)->data;
|
||||
Client *c = client_from_wlr_surface(event->surface);
|
||||
if (c != selclient()) {
|
||||
c->isurgent = 1;
|
||||
printstatus();
|
||||
@@ -2344,11 +2421,11 @@ xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
struct wlr_surface *surface = NULL;
|
||||
Client *c = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
int i;
|
||||
const int *layer;
|
||||
int focus_order[] = { LyrOverlay, LyrTop, LyrFloat, LyrTile, LyrBottom, LyrBg };
|
||||
|
||||
for (i = 0; i < LENGTH(focus_order); i++) {
|
||||
if ((node = wlr_scene_node_at(layers[focus_order[i]], x, y, nx, ny))) {
|
||||
for (layer = focus_order; layer < END(focus_order); layer++) {
|
||||
if ((node = wlr_scene_node_at(layers[*layer], x, y, nx, ny))) {
|
||||
if (node->type == WLR_SCENE_NODE_SURFACE)
|
||||
surface = wlr_scene_surface_from_node(node)->surface;
|
||||
/* 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->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
|
||||
c->bw = borderpx;
|
||||
c->isfullscreen = 0;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
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_configure, &c->configure,
|
||||
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.destroy, &c->destroy, destroynotify);
|
||||
LISTEN(&xwayland_surface->events.request_fullscreen, &c->fullscreen,
|
||||
@@ -2462,6 +2539,16 @@ getatom(xcb_connection_t *xc, const char *name)
|
||||
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
|
||||
xwaylandready(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2500,9 +2587,11 @@ main(int argc, char *argv[])
|
||||
char *startup_cmd = NULL;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "s:h")) != -1) {
|
||||
while ((c = getopt(argc, argv, "s:hv")) != -1) {
|
||||
if (c == 's')
|
||||
startup_cmd = optarg;
|
||||
else if (c == 'v')
|
||||
die("dwl " VERSION);
|
||||
else
|
||||
goto usage;
|
||||
}
|
||||
@@ -2518,5 +2607,5 @@ main(int argc, char *argv[])
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
usage:
|
||||
die("Usage: %s [-s startup command]", argv[0]);
|
||||
die("Usage: %s [-v] [-s startup command]", argv[0]);
|
||||
}
|
||||
|
||||
Executable
+13
@@ -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
|
||||
Reference in New Issue
Block a user