Compare commits

..

28 commits
main ... 0.7

Author SHA1 Message Date
389d476f5b fix monitor scaling 2024-12-13 05:38:32 -08:00
94a804e3d9 libdrm 2024-12-13 05:34:06 -08:00
aad4181ca7 nix footgun fix 2024-12-13 05:15:08 -08:00
132dc5ad5c fix overrideAttrs 2024-12-13 05:04:43 -08:00
e801bcbdb6 flake overlay 2024-12-13 04:57:04 -08:00
7e2bbdbfaf add flake dependencies 2024-12-13 04:52:16 -08:00
8eb6cc467c monitor rules 2024-12-13 04:48:08 -08:00
7d25c6650d start discord on 2 2024-12-13 04:48:08 -08:00
dc6f1cab59 bar patch 2024-12-13 04:48:08 -08:00
49888cdcbb kitty term 2024-12-13 01:25:09 -08:00
70a90ac7b5 super modkey 2024-12-13 01:25:05 -08:00
8cd12ccb2d remove unused flake stuff 2024-12-12 15:46:00 -08:00
1ea7c6d404 remove flake build artifacts 2024-12-12 15:44:57 -08:00
1957bc6e55 flake 2024-12-12 15:42:46 -08:00
57b7b87596 compile_commands 2024-12-12 15:42:35 -08:00
4c6e81631c shell.fish 2024-12-12 15:42:28 -08:00
Leonardo Hernández Hernández
cfc80c8f44
fix crash when a client is created while all outputs are disabled 2024-08-27 23:07:21 -06:00
Leonardo Hernández Hernández
0e0c97db56
changelog: add new 'unreleased' section 2024-08-27 23:07:13 -06:00
Leonardo Hernández Hernández
74e45c4014
bump version to 0.7 2024-08-06 12:03:27 -06:00
Leonardo Hernández Hernández
464dddc110
fix crash when a virtual pointer is destroyed
Fixes: https://codeberg.org/dwl/dwl/issues/680
(cherry picked from commit a634e3f527)
2024-08-06 12:03:27 -06:00
Leonardo Hernández Hernández
cb01023db6
fix crash when re-mapping a client
Fixes: ab5c554d09
(cherry picked from commit b5abbc37d8)
2024-08-01 22:35:10 -06:00
Lennart Jablonka
5bbb0ab404
dwl(1): use correct special characters for - and '
The hyphen-minus <-> and apostrophe-quote <'> are interpreted by troff
as hyphen and right single quotation mark.  See groff_char(7).

Fixes: 0db6f3c5b5 ("add dwl(1)")
(cherry picked from commit f2c5023a3a)
2024-08-01 22:34:51 -06:00
Lennart Jablonka
ed74960373
add myself to .mailmap
(cherry picked from commit 4bbbb4907e)
2024-08-01 22:34:51 -06:00
A Frederick Christensen
cc622d4dd5
Specify that the 0.7 branch builds against wlroots 0.18 2024-08-01 22:31:06 -06:00
A Frederick Christensen
3256ae0679
README.md Fix links formatting issue after re-flow text to 80 columns
(cherry picked from commit ea6a450121)
2024-08-01 22:29:29 -06:00
A Frederick Christensen
e3f1aab770
Documentation restructuring
Modified documentation to make clear the change in development (main) branch versus releases.

(cherry picked from commit ad30ca910b)
2024-08-01 22:29:29 -06:00
Leonardo Hernández Hernández
57153fd557
update README.md to mention the main branch now requires wlroots-git
Closes: https://codeberg.org/dwl/dwl/issues/646
(cherry picked from commit 452a314faa)
2024-08-01 22:29:29 -06:00
Leonardo Hernández Hernández
a9bcdff683
send scale on initial commit to layer surfaces
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
(cherry picked from commit cd216908a7)
2024-07-24 07:03:57 -05:00
15 changed files with 2159 additions and 212 deletions

View file

@ -1,3 +1 @@
Lennart Jablonka <humm@ljabl.com> <hummsmith42@gmail.com> Lennart Jablonka <humm@ljabl.com> <hummsmith42@gmail.com>
Leonardo Hernández Hernández <leohdz172@proton.me> <leohdz172@outlook.com>
Leonardo Hernández Hernández <leohdz172@proton.me> <leohdz172@protonmail.com>

View file

@ -8,15 +8,6 @@
## Unreleased ## Unreleased
### Added ### Added
* Support for the linux-drm-syncobj-v1 protocol ([wlroots!4715][wlroots!4715], [#685][685])
* Allow the use of non-system wlroots library ([#646][646])
[wlroots!4715]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4715
[685]: https://codeberg.org/dwl/dwl/pulls/685
[646]: https://codeberg.org/dwl/dwl/pulls/646
### Changed ### Changed
### Deprecated ### Deprecated
### Removed ### Removed
@ -30,7 +21,7 @@
## 0.7 ## 0.7
This version is just 0.6 with wlroots 0.18 compatibility. See also [0.6](#0.6) release notes. 0.7 builds against wlroots 0.18.x.
### Added ### Added
@ -41,9 +32,15 @@ This version is just 0.6 with wlroots 0.18 compatibility.
[601]: https://codeberg.org/dwl/dwl/issues/601 [601]: https://codeberg.org/dwl/dwl/issues/601
### Fixed
* Crash when re-mapping unmapped clients.
### Contributors ### Contributors
Guido Cella Guido Cella
Lennart Jablonka
## 0.6 ## 0.6

View file

@ -6,15 +6,15 @@ include config.mk
# flags for compiling # flags for compiling
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \ DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \
-DVERSION=\"$(VERSION)\" $(XWAYLAND) -DVERSION=\"$(VERSION)\" $(XWAYLAND)
DWLDEVCFLAGS = -g -Wpedantic -Wall -Wextra -Wdeclaration-after-statement \ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \
-Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \ -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \
-Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \ -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \
-Wfloat-conversion -Wfloat-conversion
# CFLAGS / LDFLAGS # CFLAGS / LDFLAGS
PKGS = wayland-server xkbcommon libinput $(XLIBS) PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS)
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS)
all: dwl all: dwl
dwl: dwl.o util.o dwl: dwl.o util.o
@ -50,6 +50,7 @@ config.h:
cp config.def.h $@ cp config.def.h $@
clean: clean:
rm -f dwl *.o *-protocol.h rm -f dwl *.o *-protocol.h
rm -f result result-man
dist: clean dist: clean
mkdir -p dwl-$(VERSION) mkdir -p dwl-$(VERSION)
@ -61,7 +62,6 @@ dist: clean
install: dwl install: dwl
mkdir -p $(DESTDIR)$(PREFIX)/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
rm -f $(DESTDIR)$(PREFIX)/bin/dwl
cp -f dwl $(DESTDIR)$(PREFIX)/bin cp -f dwl $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl
mkdir -p $(DESTDIR)$(MANDIR)/man1 mkdir -p $(DESTDIR)$(MANDIR)/man1

View file

@ -1,7 +1,7 @@
# dwl - dwm for Wayland # dwl - dwm for Wayland
Join us on our IRC channel: [#dwl on Libera Chat] Join us on our IRC channel: [#dwl on Libera Chat]
Or on the community-maintained [Discord server]. Or on our [Discord server].
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is
intended to fill the same space in the Wayland world that dwm does in X11, intended to fill the same space in the Wayland world that dwm does in X11,
@ -14,6 +14,8 @@ philosophy. Like dwm, dwl is:
## Getting Started: ## Getting Started:
### **dwl branch 0.7 and releases based upon 0.7 build against [wlroots] 0.18**
### Latest semi-stable [release] ### Latest semi-stable [release]
This is probably where you want to start. This builds against the dependent This is probably where you want to start. This builds against the dependent
packages' versions currently shipping in major distributions. If your packages' versions currently shipping in major distributions. If your

View file

@ -126,14 +126,15 @@ client_get_appid(Client *c)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->class ? c->surface.xwayland->class : "broken"; return c->surface.xwayland->class;
#endif #endif
return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id : "broken"; return c->surface.xdg->toplevel->app_id;
} }
static inline void static inline void
client_get_clip(Client *c, struct wlr_box *clip) client_get_clip(Client *c, struct wlr_box *clip)
{ {
struct wlr_box xdg_geom = {0};
*clip = (struct wlr_box){ *clip = (struct wlr_box){
.x = 0, .x = 0,
.y = 0, .y = 0,
@ -146,8 +147,9 @@ client_get_clip(Client *c, struct wlr_box *clip)
return; return;
#endif #endif
clip->x = c->surface.xdg->geometry.x; wlr_xdg_surface_get_geometry(c->surface.xdg, &xdg_geom);
clip->y = c->surface.xdg->geometry.y; clip->x = xdg_geom.x;
clip->y = xdg_geom.y;
} }
static inline void static inline void
@ -162,7 +164,7 @@ client_get_geometry(Client *c, struct wlr_box *geom)
return; return;
} }
#endif #endif
*geom = c->surface.xdg->geometry; wlr_xdg_surface_get_geometry(c->surface.xdg, geom);
} }
static inline Client * static inline Client *
@ -198,9 +200,9 @@ client_get_title(Client *c)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) if (client_is_x11(c))
return c->surface.xwayland->title ? c->surface.xwayland->title : "broken"; return c->surface.xwayland->title;
#endif #endif
return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title : "broken"; return c->surface.xdg->toplevel->title;
} }
static inline int static inline int
@ -299,6 +301,17 @@ client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL);
} }
static inline void
client_restack_surface(Client *c)
{
#ifdef XWAYLAND
if (client_is_x11(c))
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
XCB_STACK_MODE_ABOVE);
#endif
return;
}
static inline void static inline void
client_send_close(Client *c) client_send_close(Client *c)
{ {
@ -331,13 +344,6 @@ client_set_fullscreen(Client *c, int fullscreen)
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
} }
static inline void
client_set_scale(struct wlr_surface *s, float scale)
{
wlr_fractional_scale_v1_notify_scale(s, scale);
wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale));
}
static inline uint32_t static inline uint32_t
client_set_size(Client *c, uint32_t width, uint32_t height) client_set_size(Client *c, uint32_t width, uint32_t height)
{ {
@ -358,11 +364,8 @@ static inline void
client_set_tiled(Client *c, uint32_t edges) client_set_tiled(Client *c, uint32_t edges)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
if (client_is_x11(c)) { if (client_is_x11(c))
wlr_xwayland_surface_set_maximized(c->surface.xwayland,
edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE);
return; return;
}
#endif #endif
if (wl_resource_get_version(c->surface.xdg->toplevel->resource) if (wl_resource_get_version(c->surface.xdg->toplevel->resource)
>= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) {
@ -388,8 +391,8 @@ client_wants_focus(Client *c)
{ {
#ifdef XWAYLAND #ifdef XWAYLAND
return client_is_unmanaged(c) return client_is_unmanaged(c)
&& wlr_xwayland_surface_override_redirect_wants_focus(c->surface.xwayland) && wlr_xwayland_or_surface_wants_focus(c->surface.xwayland)
&& wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE; && wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE;
#endif #endif
return 0; return 0;
} }

1
compile_commands.json Normal file
View file

@ -0,0 +1 @@
[]

View file

@ -7,15 +7,21 @@
static const int sloppyfocus = 1; /* focus follows mouse */ static const int sloppyfocus = 1; /* focus follows mouse */
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int borderpx = 1; /* border pixel of windows */
static const float rootcolor[] = COLOR(0x222222ff); static const int showbar = 1; /* 0 means no bar */
static const float bordercolor[] = COLOR(0x444444ff); static const int topbar = 1; /* 0 means bottom bar */
static const float focuscolor[] = COLOR(0x005577ff); static const char *fonts[] = {"monospace:size=10"};
static const float urgentcolor[] = COLOR(0xff0000ff); static const float rootcolor[] = COLOR(0x000000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
static uint32_t colors[][3] = {
/* fg bg border */
[SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff },
[SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff },
[SchemeUrg] = { 0, 0, 0x770000ff },
};
/* tagging - TAGCOUNT must be no greater than 31 */ /* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9) static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
/* logging */ /* logging */
static int log_level = WLR_ERROR; static int log_level = WLR_ERROR;
@ -25,7 +31,7 @@ static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */ /* app_id title tags mask isfloating monitor */
/* examples: */ /* examples: */
{ "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
{ "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ { "discord", NULL, 1 << 1, 0, 1 }, /* Start on ONLY tag "9" */
}; };
/* layout(s) */ /* layout(s) */
@ -47,6 +53,8 @@ static const MonitorRule monrules[] = {
/* example of a HiDPI laptop monitor: /* example of a HiDPI laptop monitor:
{ "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, { "eDP-1", 0.5f, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
*/ */
{ "HDMI-A-1", 0.5f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 },
{ "DP-1", 0.5f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 1920, 0 },
/* defaults */ /* defaults */
{ NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
}; };
@ -107,7 +115,7 @@ LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
#define MODKEY WLR_MODIFIER_ALT #define MODKEY WLR_MODIFIER_LOGO
#define TAGKEYS(KEY,SKEY,TAG) \ #define TAGKEYS(KEY,SKEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
@ -119,7 +127,7 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */ /* commands */
static const char *termcmd[] = { "foot", NULL }; static const char *termcmd[] = { "kitty", NULL };
static const char *menucmd[] = { "wmenu-run", NULL }; static const char *menucmd[] = { "wmenu-run", NULL };
static const Key keys[] = { static const Key keys[] = {
@ -127,6 +135,7 @@ static const Key keys[] = {
/* modifier key function argument */ /* modifier key function argument */
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
{ MODKEY, XKB_KEY_b, togglebar, {0} },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
@ -170,7 +179,15 @@ static const Key keys[] = {
}; };
static const Button buttons[] = { static const Button buttons[] = {
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} },
{ MODKEY, BTN_MIDDLE, togglefloating, {0} }, { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} },
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, { ClkTitle, 0, BTN_MIDDLE, zoom, {0} },
{ ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} },
{ ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
{ ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} },
{ ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
{ ClkTagBar, 0, BTN_LEFT, view, {0} },
{ ClkTagBar, 0, BTN_RIGHT, toggleview, {0} },
{ ClkTagBar, MODKEY, BTN_LEFT, tag, {0} },
{ ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} },
}; };

View file

@ -1,4 +1,4 @@
_VERSION = 0.8-dev _VERSION = 0.7
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config
@ -8,29 +8,10 @@ PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man MANDIR = $(PREFIX)/share/man
DATADIR = $(PREFIX)/share DATADIR = $(PREFIX)/share
WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`
WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
# Allow using an alternative wlroots installations
# This has to have all the includes required by wlroots, e.g:
# Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/include
# Set -rpath to avoid using the wrong library.
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19
# Assuming you ran "meson setup --prefix ${PWD}/0.19 build && ninja -C build install"
#WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \
# -I$(PWD)/wlroots/0.19/include/wlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19
XWAYLAND = XWAYLAND =
XLIBS = XLIBS =
# Uncomment to build XWayland support # Uncomment to build XWayland support
#XWAYLAND = -DXWAYLAND #XWAYLAND = -DXWAYLAND
#XLIBS = xcb xcb-icccm #XLIBS = xcb xcb-icccm
# dwl itself only uses C99 features, but wlroots' headers use anonymous unions (C11). CC = gcc
# To avoid warnings about them, we do not use -std=c99 and instead of using the
# gmake default 'CC=c99', we use cc.
CC = cc

311
drwl.h Normal file
View file

@ -0,0 +1,311 @@
/*
* drwl - https://codeberg.org/sewn/drwl
*
* Copyright (c) 2023-2024 sewn <sewn@disroot.org>
* Copyright (c) 2024 notchoc <notchoc@disroot.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The UTF-8 Decoder included is from Bjoern Hoehrmann:
* Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
* See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
*/
#pragma once
#include <stdlib.h>
#include <fcft/fcft.h>
#include <pixman-1/pixman.h>
enum { ColFg, ColBg, ColBorder }; /* colorscheme index */
typedef struct fcft_font Fnt;
typedef pixman_image_t Img;
typedef struct {
Img *image;
Fnt *font;
uint32_t *scheme;
} Drwl;
#define UTF8_ACCEPT 0
#define UTF8_REJECT 12
#define UTF8_INVALID 0xFFFD
static const uint8_t utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12,
};
static inline uint32_t
utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte)
{
uint32_t type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state + type];
return *state;
}
static int
drwl_init(void)
{
fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3);
return fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_ERROR);
}
static Drwl *
drwl_create(void)
{
Drwl *drwl;
if (!(drwl = calloc(1, sizeof(Drwl))))
return NULL;
return drwl;
}
static void
drwl_setfont(Drwl *drwl, Fnt *font)
{
if (drwl)
drwl->font = font;
}
static void
drwl_setimage(Drwl *drwl, Img *image)
{
if (drwl)
drwl->image = image;
}
static Fnt *
drwl_font_create(Drwl *drwl, size_t count,
const char *names[static count], const char *attributes)
{
Fnt *font = fcft_from_name(count, names, attributes);
if (drwl)
drwl_setfont(drwl, font);
return font;
}
static void
drwl_font_destroy(Fnt *font)
{
fcft_destroy(font);
}
static inline pixman_color_t
convert_color(uint32_t clr)
{
return (pixman_color_t){
((clr >> 24) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF,
((clr >> 16) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF,
((clr >> 8) & 0xFF) * 0x101 * (clr & 0xFF) / 0xFF,
(clr & 0xFF) * 0x101
};
}
static void
drwl_setscheme(Drwl *drwl, uint32_t *scm)
{
if (drwl)
drwl->scheme = scm;
}
static Img *
drwl_image_create(Drwl *drwl, unsigned int w, unsigned int h, uint32_t *bits)
{
Img *image;
pixman_region32_t clip;
image = pixman_image_create_bits_no_clear(
PIXMAN_a8r8g8b8, w, h, bits, w * 4);
if (!image)
return NULL;
pixman_region32_init_rect(&clip, 0, 0, w, h);
pixman_image_set_clip_region32(image, &clip);
pixman_region32_fini(&clip);
if (drwl)
drwl_setimage(drwl, image);
return image;
}
static void
drwl_rect(Drwl *drwl,
int x, int y, unsigned int w, unsigned int h,
int filled, int invert)
{
pixman_color_t clr;
if (!drwl || !drwl->scheme || !drwl->image)
return;
clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]);
if (filled)
pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 1,
&(pixman_rectangle16_t){x, y, w, h});
else
pixman_image_fill_rectangles(PIXMAN_OP_SRC, drwl->image, &clr, 4,
(pixman_rectangle16_t[4]){
{ x, y, w, 1 },
{ x, y + h - 1, w, 1 },
{ x, y, 1, h },
{ x + w - 1, y, 1, h }});
}
static int
drwl_text(Drwl *drwl,
int x, int y, unsigned int w, unsigned int h,
unsigned int lpad, const char *text, int invert)
{
int ty;
int render = x || y || w || h;
long x_kern;
uint32_t cp = 0, last_cp = 0, state;
pixman_color_t clr;
pixman_image_t *fg_pix = NULL;
int noellipsis = 0;
const struct fcft_glyph *glyph, *eg = NULL;
int fcft_subpixel_mode = FCFT_SUBPIXEL_DEFAULT;
if (!drwl || (render && (!drwl->scheme || !w || !drwl->image)) || !text || !drwl->font)
return 0;
if (!render) {
w = invert ? invert : ~invert;
} else {
clr = convert_color(drwl->scheme[invert ? ColBg : ColFg]);
fg_pix = pixman_image_create_solid_fill(&clr);
drwl_rect(drwl, x, y, w, h, 1, !invert);
x += lpad;
w -= lpad;
}
if (render && (drwl->scheme[ColBg] & 0xFF) != 0xFF)
fcft_subpixel_mode = FCFT_SUBPIXEL_NONE;
if (render)
eg = fcft_rasterize_char_utf32(drwl->font, 0x2026 /* … */, fcft_subpixel_mode);
for (const char *p = text, *pp; pp = p, *p; p++) {
for (state = UTF8_ACCEPT; *p &&
utf8decode(&state, &cp, *p) > UTF8_REJECT; p++)
;
if (!*p || state == UTF8_REJECT) {
cp = UTF8_INVALID;
if (p > pp)
p--;
}
glyph = fcft_rasterize_char_utf32(drwl->font, cp, fcft_subpixel_mode);
if (!glyph)
continue;
x_kern = 0;
if (last_cp)
fcft_kerning(drwl->font, last_cp, cp, &x_kern, NULL);
last_cp = cp;
ty = y + (h - drwl->font->height) / 2 + drwl->font->ascent;
if (render && !noellipsis && x_kern + glyph->advance.x + eg->advance.x > w &&
*(p + 1) != '\0') {
/* cannot fit ellipsis after current codepoint */
if (drwl_text(drwl, 0, 0, 0, 0, 0, pp, 0) + x_kern <= w) {
noellipsis = 1;
} else {
w -= eg->advance.x;
pixman_image_composite32(
PIXMAN_OP_OVER, fg_pix, eg->pix, drwl->image, 0, 0, 0, 0,
x + eg->x, ty - eg->y, eg->width, eg->height);
}
}
if ((x_kern + glyph->advance.x) > w)
break;
x += x_kern;
if (render && pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8)
/* pre-rendered glyphs (eg. emoji) */
pixman_image_composite32(
PIXMAN_OP_OVER, glyph->pix, NULL, drwl->image, 0, 0, 0, 0,
x + glyph->x, ty - glyph->y, glyph->width, glyph->height);
else if (render)
pixman_image_composite32(
PIXMAN_OP_OVER, fg_pix, glyph->pix, drwl->image, 0, 0, 0, 0,
x + glyph->x, ty - glyph->y, glyph->width, glyph->height);
x += glyph->advance.x;
w -= glyph->advance.x;
}
if (render)
pixman_image_unref(fg_pix);
return x + (render ? w : 0);
}
static unsigned int
drwl_font_getwidth(Drwl *drwl, const char *text)
{
if (!drwl || !drwl->font || !text)
return 0;
return drwl_text(drwl, 0, 0, 0, 0, 0, text, 0);
}
static void
drwl_image_destroy(Img *image)
{
pixman_image_unref(image);
}
static void
drwl_destroy(Drwl *drwl)
{
if (drwl->font)
drwl_font_destroy(drwl->font);
if (drwl->image)
drwl_image_destroy(drwl->image);
free(drwl);
}
static void
drwl_fini(void)
{
fcft_fini();
}

578
dwl.c

File diff suppressed because it is too large Load diff

58
flake.lock Normal file
View file

@ -0,0 +1,58 @@
{
"nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1733759999,
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1733096140,
"narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

28
flake.nix Normal file
View file

@ -0,0 +1,28 @@
{
description = "dwm for Wayland (requires dwl 0.7)";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
};
outputs = inputs@{ flake-parts, nixpkgs, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [
flake-parts.flakeModules.easyOverlay
];
systems = nixpkgs.lib.platforms.unix;
perSystem = { config, self', inputs', pkgs, system, ... }: {
overlayAttrs = {
zdwl = config.packages.default;
};
packages.default = pkgs.dwl.overrideAttrs (old: {
buildInputs = old.buildInputs ++ (with pkgs; [
fcft
libdrm.dev
]);
src = ./.;
});
};
};
}

1245
patches/bar-0.7.patch Normal file

File diff suppressed because it is too large Load diff

2
shell.fish Executable file
View file

@ -0,0 +1,2 @@
nix-shell -p bear --command fish
nix develop nixpkgs#dwl --command fish

10
util.c
View file

@ -38,14 +38,14 @@ ecalloc(size_t nmemb, size_t size)
int int
fd_set_nonblock(int fd) { fd_set_nonblock(int fd) {
int flags = fcntl(fd, F_GETFL); int flags = fcntl(fd, F_GETFL);
if (flags < 0) { if (flags < 0) {
perror("fcntl(F_GETFL):"); perror("fcntl(F_GETFL):");
return -1; return -1;
} }
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl(F_SETFL):"); perror("fcntl(F_SETFL):");
return -1; return -1;
} }
return 0; return 0;
} }