This commit is contained in:
2026-07-12 08:16:17 +03:30
commit 72be1234e1
2027 changed files with 221388 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
### Description
Add a system tray next to the [bar](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar). Heed the warning, this is far from suckless ^^
![preview](systray.png)
**Superseded by [bar-systray](/dwl/dwl-patches/src/branch/main/patches/bar-systray).**
### Dependencies
- GTK4
- [bar.patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar) as mentioned.
- [gtk4-layer-shell](https://github.com/wmww/gtk4-layer-shell)
- [statusnotifier-systray-gtk4](https://codeberg.org/janetski/statusnotifier-systray-gtk4) built as a static library.
### Applying the patch
The patch applies on top of the bar patch. That needs to be applied first.
The patch creates subdirectories `lib` and `include`. After patching, but before `make`, install
`libstatusnotifier-systray-gtk4.a` and `snsystray.h` from statusnotifier-systray-gtk4 in the
directories. One possible way to do that:
1. Clone [https://codeberg.org/janetski/statusnotifier-systray-gtk4](https://codeberg.org/janetski/statusnotifier-systray-gtk4). Can clone to any location.
2. From statusnotifier-systray-gtk4 root:
1. `$ meson setup --default-library=static --prefix=/ -Dgir=false -Dvala=false -Ddocs=false build`
2. `$ meson compile -C build`
3. `$ DESTDIR=$DWLDIR meson install -C build`, where $DWLDIR is the path to dwl root.
3. Finally, from dwl root, run `make`.
### Download
- [git branch](/janetski/dwl/src/branch/0.7-systray)
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar-systray/bar-systray-0.7.patch)
### Authors
- [janetski](https://codeberg.org/janetski) ([.vetu](https://discordapp.com/users/355488216469471242) on discord)
@@ -0,0 +1,398 @@
From 71f7b97dca2d781668e826aae7e06544958534f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Janne=20Vetel=C3=A4inen?= <janne.vetelainen@elisanet.fi>
Date: Fri, 23 Aug 2024 18:39:17 +0300
Subject: [PATCH 1/1] Add a system tray next to the sewn's bar
---
Makefile | 8 +-
config.def.h | 2 +
dwl.c | 222 ++++++++++++++++++++++++++++++++++++++++++++-
include/.gitignore | 1 +
lib/.gitignore | 1 +
5 files changed, 225 insertions(+), 9 deletions(-)
create mode 100644 include/.gitignore
create mode 100644 lib/.gitignore
diff --git a/Makefile b/Makefile
index 9bc67db..853b04c 100644
--- a/Makefile
+++ b/Makefile
@@ -7,14 +7,14 @@ include config.mk
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L \
-DVERSION=\"$(VERSION)\" $(XWAYLAND)
DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \
- -Wno-unused-parameter -Wshadow -Wunused-macros -Werror=strict-prototypes \
+ -Wno-unused-parameter -Wshadow -Wunused-macros \
-Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types \
-Wfloat-conversion
# CFLAGS / LDFLAGS
-PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS)
-DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
-LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS)
+PKGS = wlroots-0.18 wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) gtk4 gtk4-layer-shell-0
+DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -Iinclude
+LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) -Llib -lstatusnotifier-systray-gtk4
all: dwl
dwl: dwl.o util.o
diff --git a/config.def.h b/config.def.h
index 5d1dc2b..bb9366f 100644
--- a/config.def.h
+++ b/config.def.h
@@ -11,6 +11,8 @@ static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = {"monospace:size=10"};
static const float rootcolor[] = COLOR(0x000000ff);
+static const int trayspacing = 4; /* Spacing between icons in system tray */
+static const int traymargins = 4; /* System tray inner margins */
/* 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 uint32_t colors[][3] = {
diff --git a/dwl.c b/dwl.c
index ece537a..24f550a 100644
--- a/dwl.c
+++ b/dwl.c
@@ -72,9 +72,22 @@
#include "util.h"
#include "drwl.h"
+#include <snsystray.h>
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gtk4-layer-shell.h>
+#include <pthread.h>
+
/* macros */
+#ifndef MAX
#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#endif /* MAX */
+#ifndef MIN
#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif /* MIN */
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
#define LENGTH(X) (sizeof X / sizeof X[0])
@@ -324,6 +337,15 @@ static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void gpureset(struct wl_listener *listener, void *data);
+static void gtkactivate(GtkApplication *app, void *data);
+static void gtkclosewindows(void *data, void *udata);
+static void gtkhandletogglebarmsg(void *data);
+static void gtkhandlewidthnotify(SnSystray *systray, GParamSpec *pspec, void *data);
+static void* gtkinit(void *data);
+static void gtkspawnstray(Monitor *m, GtkApplication *app);
+static void gtkterminate(void *data);
+static void gtktoggletray(void *data, void *udata);
+static GdkMonitor* gtkwlrtogdkmon(Monitor *wlrmon);
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
@@ -380,7 +402,7 @@ static void unlocksession(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 updatemons(struct wl_listener *listener, void *data);
-static void updatebar(Monitor *m);
+static void updatebar(Monitor *m, int traywidth);
static void updatetitle(struct wl_listener *listener, void *data);
static void urgent(struct wl_listener *listener, void *data);
static void view(const Arg *arg);
@@ -394,6 +416,8 @@ static void zoom(const Arg *arg);
/* variables */
static const char broken[] = "broken";
static pid_t child_pid = -1;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t gtkthread; /* Gtk functions are only allowed to be called from this thread */
static int locked;
static void *exclusive_focus;
static struct wl_display *dpy;
@@ -1187,7 +1211,7 @@ createmon(struct wl_listener *listener, void *data)
m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL);
m->scene_buffer->point_accepts_input = baracceptsinput;
- updatebar(m);
+ updatebar(m, 0);
wl_list_insert(&mons, &m->link);
drawbars();
@@ -1518,6 +1542,8 @@ drawbar(Monitor *m)
if (!(buf = bufmon(m)))
return;
+ pthread_mutex_lock(&mutex);
+
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drwl_setscheme(m->drw, colors[SchemeNorm]);
@@ -1566,6 +1592,7 @@ drawbar(Monitor *m)
m->m.y + (topbar ? 0 : m->m.height - m->b.real_height));
wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base);
wlr_buffer_unlock(&buf->base);
+ pthread_mutex_unlock(&mutex);
}
void
@@ -1710,6 +1737,174 @@ fullscreennotify(struct wl_listener *listener, void *data)
setfullscreen(c, client_wants_fullscreen(c));
}
+void
+gtkactivate(GtkApplication *app, void *data)
+{
+ GdkDisplay *display;
+ GtkCssProvider *cssp;
+ char csss[64];
+ Monitor *m;
+ uint32_t bgcolor;
+
+ bgcolor = colors[SchemeNorm][1] >> 8;
+ display = gdk_display_get_default();
+ cssp = gtk_css_provider_new();
+ sprintf(csss, "window{background-color:#%06x;}", bgcolor);
+ gtk_css_provider_load_from_string(cssp, csss);
+ gtk_style_context_add_provider_for_display(display,
+ GTK_STYLE_PROVIDER(cssp),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ wl_list_for_each(m, &mons, link)
+ gtkspawnstray(m, app);
+
+ g_object_unref(cssp);
+}
+
+void
+gtkclosewindows(void *data, void *udata)
+{
+ GtkWindow *window = GTK_WINDOW(data);
+
+ gtk_window_close(window);
+}
+
+void
+gtkhandletogglebarmsg(void *data)
+{
+ GtkApplication *app;
+ GList *windows;
+
+ app = GTK_APPLICATION(g_application_get_default());
+ windows = gtk_application_get_windows(app);
+ g_list_foreach(windows, gtktoggletray, data);
+}
+
+void
+gtkhandlewidthnotify(SnSystray *systray, GParamSpec *pspec, void *data)
+{
+ Monitor *m = (Monitor *)data;
+ int traywidth;
+
+ traywidth = sn_systray_get_width(systray);
+
+ updatebar(m, traywidth);
+ drawbar(m);
+}
+
+void*
+gtkinit(void *data)
+{
+ GtkApplication *app = gtk_application_new("org.dwl.systray",
+ G_APPLICATION_NON_UNIQUE);
+ g_signal_connect(app, "activate", G_CALLBACK(gtkactivate), NULL);
+ g_application_run(G_APPLICATION(app), 0, NULL);
+
+ g_object_unref(app);
+
+ return NULL;
+}
+
+void
+gtkspawnstray(Monitor *m, GtkApplication *app)
+{
+ GdkMonitor *gdkmon;
+ GtkWindow *window;
+ SnSystray *systray;
+ const char *conn;
+ gboolean anchors[4];
+ int iconsize, tray_init_width, tray_height;
+
+ gdkmon = gtkwlrtogdkmon(m);
+ if (gdkmon == NULL)
+ die("Failed to get gdkmon");
+
+ conn = gdk_monitor_get_connector(gdkmon);
+ iconsize = m->b.real_height - 2 * traymargins;
+ tray_height = m->b.real_height;
+ tray_init_width = m->b.real_height;
+
+ if (topbar) {
+ anchors[GTK_LAYER_SHELL_EDGE_LEFT] = false;
+ anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = true;
+ anchors[GTK_LAYER_SHELL_EDGE_TOP] = true;
+ anchors[GTK_LAYER_SHELL_EDGE_BOTTOM] = false;
+ } else {
+ anchors[GTK_LAYER_SHELL_EDGE_LEFT] = false;
+ anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = true;
+ anchors[GTK_LAYER_SHELL_EDGE_TOP] = false;
+ anchors[GTK_LAYER_SHELL_EDGE_BOTTOM] = true;
+ }
+
+ systray = sn_systray_new(iconsize,
+ traymargins,
+ trayspacing,
+ conn);
+ window = GTK_WINDOW(gtk_window_new());
+
+ gtk_window_set_default_size(window, tray_init_width, tray_height);
+ gtk_window_set_child(window, GTK_WIDGET(systray));
+ gtk_window_set_application(window, app);
+ gtk_layer_init_for_window(window);
+ gtk_layer_set_layer(window, GTK_LAYER_SHELL_LAYER_BOTTOM);
+ gtk_layer_set_exclusive_zone(window, -1);
+ gtk_layer_set_monitor(window, gdkmon);
+
+ for (int j = 0; j < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; j++) {
+ gtk_layer_set_anchor(window, j, anchors[j]);
+ }
+
+ updatebar(m, tray_init_width);
+ g_signal_connect(systray, "notify::curwidth", G_CALLBACK(gtkhandlewidthnotify), m);
+ gtk_window_present(window);
+}
+
+void
+gtkterminate(void *data)
+{
+ GtkApplication *app;
+ GList *windows;
+
+ app = GTK_APPLICATION(g_application_get_default());
+ windows = gtk_application_get_windows(app);
+ g_list_foreach(windows, gtkclosewindows, NULL);
+}
+
+GdkMonitor*
+gtkwlrtogdkmon(Monitor *wlrmon)
+{
+ GdkMonitor *gdkmon = NULL;
+
+ GListModel *gdkmons;
+ GdkDisplay *display;
+ const char *gdkname;
+ const char *wlrname;
+ unsigned int i;
+
+ wlrname = wlrmon->wlr_output->name;
+ display = gdk_display_get_default();
+ gdkmons = gdk_display_get_monitors(display);
+
+ for (i = 0; i < g_list_model_get_n_items(gdkmons); i++) {
+ GdkMonitor *mon = g_list_model_get_item(gdkmons, i);
+ gdkname = gdk_monitor_get_connector(mon);
+ if (strcmp(wlrname, gdkname) == 0)
+ gdkmon = mon;
+ }
+
+ return gdkmon;
+}
+
+void
+gtktoggletray(void *data, void *udata)
+{
+ GtkWidget *widget = GTK_WIDGET(data);
+ int *pbarvisible = (int *)udata;
+ int barvisible = GPOINTER_TO_INT(pbarvisible);
+
+ gtk_widget_set_visible(widget, barvisible);
+}
+
void
gpureset(struct wl_listener *listener, void *data)
{
@@ -2293,6 +2488,8 @@ powermgrsetmode(struct wl_listener *listener, void *data)
void
quit(const Arg *arg)
{
+ g_idle_add_once(gtkterminate, NULL);
+ pthread_join(gtkthread, NULL);
wl_display_terminate(dpy);
}
@@ -2836,6 +3033,9 @@ setup(void)
fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
}
#endif
+
+ // Gtk functions are only allowed to be called from this thread.
+ pthread_create(&gtkthread, NULL, &gtkinit, NULL);
}
void
@@ -2943,9 +3143,21 @@ tile(Monitor *m)
void
togglebar(const Arg *arg)
{
+ int barvisible;
+ int *pbarvisible;
+
wlr_scene_node_set_enabled(&selmon->scene_buffer->node,
!selmon->scene_buffer->node.enabled);
arrangelayers(selmon);
+
+ // Notify gtkthread
+ if (selmon->scene_buffer->node.enabled)
+ barvisible = 1;
+ else
+ barvisible = 0;
+
+ pbarvisible = GINT_TO_POINTER(barvisible);
+ g_idle_add_once(gtkhandletogglebarmsg, pbarvisible);
}
void
@@ -3140,7 +3352,7 @@ updatemons(struct wl_listener *listener, void *data)
if (stext[0] == '\0')
strncpy(stext, "dwl-"VERSION, sizeof(stext));
wl_list_for_each(m, &mons, link) {
- updatebar(m);
+ updatebar(m, 0);
drawbar(m);
}
@@ -3155,7 +3367,7 @@ updatemons(struct wl_listener *listener, void *data)
}
void
-updatebar(Monitor *m)
+updatebar(Monitor *m, int traywidth)
{
size_t i;
int rw, rh;
@@ -3163,7 +3375,7 @@ updatebar(Monitor *m)
wlr_output_transformed_resolution(m->wlr_output, &rw, &rh);
m->b.width = rw;
- m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale);
+ m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale) - traywidth;
wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0);
diff --git a/include/.gitignore b/include/.gitignore
new file mode 100644
index 0000000..424c745
--- /dev/null
+++ b/include/.gitignore
@@ -0,0 +1 @@
+*.h
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..10301e2
--- /dev/null
+++ b/lib/.gitignore
@@ -0,0 +1 @@
+*.a
--
2.46.0
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+13
View File
@@ -0,0 +1,13 @@
### Description
Show the master area to the right.
### Reason for deprecation
I created this patch for a user on Discord and I have never used it.
### Download
- [git branch](https://codeberg.org/sevz/dwl/src/branch/master-right)
- [main 2024-09-01](/dwl/dwl-patches/raw/branch/main/patches/master-right/master-right.patch)
- [master-right-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/master-right/master-right-0.7.patch)
### Authors
- [sevz](https://codeberg.org/sevz)
@@ -0,0 +1,35 @@
From f72236247e5e7cb23c3cac86b496cdd2c523f7ff Mon Sep 17 00:00:00 2001
From: Sevz17 <leohdz172@outlook.com>
Date: Fri, 25 Jun 2021 19:50:56 -0500
Subject: [PATCH] show master area to the right
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
---
dwl.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dwl.c b/dwl.c
index a2711f67..50b057a7 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2710,11 +2710,12 @@ tile(Monitor *m)
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
continue;
if (i < m->nmaster) {
- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
+ resize(c, (struct wlr_box){.x = m->w.x + m->w.width - mw,
+ .y = m->w.y + my, .width = mw,
.height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
my += c->geom.height;
} else {
- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
+ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ty,
.width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
ty += c->geom.height;
}
--
2.46.0
@@ -0,0 +1,35 @@
From 0afd0a98998dda20e4fe4f4d2b5fcdec49c448c3 Mon Sep 17 00:00:00 2001
From: Sevz17 <leohdz172@outlook.com>
Date: Fri, 25 Jun 2021 19:50:56 -0500
Subject: [PATCH] show master area to the right
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
---
dwl.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dwl.c b/dwl.c
index 9021e442..2bd354a3 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2670,11 +2670,12 @@ tile(Monitor *m)
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
continue;
if (i < m->nmaster) {
- resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
+ resize(c, (struct wlr_box){.x = m->w.x + m->w.width - mw,
+ .y = m->w.y + my, .width = mw,
.height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
my += c->geom.height;
} else {
- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
+ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ty,
.width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
ty += c->geom.height;
}
--
2.46.0
@@ -0,0 +1,15 @@
### Description
This patch adds 3 additional options to the `Key` struct, `on_press`, `on_repeat` and `on_release` which can be used to control which events a key binding should be triggered on.
NOTE: Due to concerns about patching difficulties this patch does NOT include any changes to `config.def.h`. After applying you will need to add the 3 additional initializers to each key binding that you would like to modify. Any key binding that is not updated will cause a build warning but should function as it does in vanilla.
2025-01-04 Moved to stale patches.
Outstanding issues with this patch: https://codeberg.org/dwl/dwl-patches/issues/98
Patch maintainer notes he is no longer maintaining dwl patches: https://codeberg.org/dwl/dwl-patches/pulls/102
### Download
- [git branch](https://codeberg.org/USERNAME/dwl/src/branch/press_repeat_release)
- [2024-03-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/press_repeat_release/press_repeat_release.patch)
### Authors
- [minego](https://codeberg.org/minego)
@@ -0,0 +1,108 @@
From aee1dc3e9ca4d8deec5432d0c64921af6e301ecd Mon Sep 17 00:00:00 2001
From: Micah N Gorrell <m@minego.net>
Date: Wed, 27 Mar 2024 15:59:50 -0600
Subject: [PATCH 1/2] onpress, onrepeat, onrelease
---
dwl.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/dwl.c b/dwl.c
index 5867b0c..43bbf0c 100644
--- a/dwl.c
+++ b/dwl.c
@@ -146,6 +146,10 @@ typedef struct {
xkb_keysym_t keysym;
void (*func)(const Arg *);
const Arg arg;
+
+ int on_press;
+ int on_repeat;
+ int on_release;
} Key;
typedef struct {
@@ -286,7 +290,7 @@ static void fullscreennotify(struct wl_listener *listener, void *data);
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
-static int keybinding(uint32_t mods, xkb_keysym_t sym);
+static int keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_release);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static int keyrepeat(void *data);
@@ -1428,7 +1432,7 @@ inputdevice(struct wl_listener *listener, void *data)
}
int
-keybinding(uint32_t mods, xkb_keysym_t sym)
+keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_release)
{
/*
* Here we handle compositor keybindings. This is when the compositor is
@@ -1439,8 +1443,10 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
for (k = keys; k < END(keys); k++) {
if (CLEANMASK(mods) == CLEANMASK(k->mod)
&& sym == k->keysym && k->func) {
- k->func(&k->arg);
- return 1;
+ if ((on_press && k->on_press) || (on_repeat && k->on_repeat) || (on_release && k->on_release)) {
+ k->func(&k->arg);
+ return 1;
+ }
}
}
return 0;
@@ -1470,7 +1476,7 @@ keypress(struct wl_listener *listener, void *data)
* attempt to process a compositor keybinding. */
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
for (i = 0; i < nsyms; i++)
- handled = keybinding(mods, syms[i]) || handled;
+ handled = keybinding(mods, syms[i], event->state == WL_KEYBOARD_KEY_STATE_PRESSED, 0, event->state == WL_KEYBOARD_KEY_STATE_RELEASED) || handled;
}
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
@@ -1518,7 +1524,7 @@ keyrepeat(void *data)
1000 / group->wlr_group->keyboard.repeat_info.rate);
for (i = 0; i < group->nsyms; i++)
- keybinding(group->mods, group->keysyms[i]);
+ keybinding(group->mods, group->keysyms[i], 0, 1, 0);
return 0;
}
--
2.44.0
From 1875bb171c9b0cd2fb03bb7e6c3fb400e33eeaf1 Mon Sep 17 00:00:00 2001
From: Micah N Gorrell <m@minego.net>
Date: Wed, 27 Mar 2024 16:26:52 -0600
Subject: [PATCH 2/2] Modified logic so that an unmodified keybinding with
default values for the new flags will behave as it does in vanilla, while
keybindings with customized flags will function as expected
---
dwl.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dwl.c b/dwl.c
index 43bbf0c..55e7a40 100644
--- a/dwl.c
+++ b/dwl.c
@@ -1443,7 +1443,11 @@ keybinding(uint32_t mods, xkb_keysym_t sym, int on_press, int on_repeat, int on_
for (k = keys; k < END(keys); k++) {
if (CLEANMASK(mods) == CLEANMASK(k->mod)
&& sym == k->keysym && k->func) {
- if ((on_press && k->on_press) || (on_repeat && k->on_repeat) || (on_release && k->on_release)) {
+ if ((k->on_press == 0 && k->on_repeat == 0 && k->on_release == 0) ||
+ (on_press && k->on_press) ||
+ (on_repeat && k->on_repeat) ||
+ (on_release && k->on_release)
+ ) {
k->func(&k->arg);
return 1;
}
--
2.44.0
+16
View File
@@ -0,0 +1,16 @@
### Description
This patch modifies the behavior when selecting tags so that selecting a tag will also enable any other tags that were previously visible.
For example:
1. Select tag 5, with mod+5
2. Toggle tag 8, with ctrl+mod+8
3. Select tag 1, with mod+1. Tags 5 and 8 should no longer be visible.
4. Select tag 5 again, with mod+5. Tag 8 should be visible since it was remembered.
5. Select tag 5 again, with mod_5. Selecting the already selected tag resets any remembered tags, so now tag 5 should be the only one visible.
### Download
- [git branch](https://codeberg.org/minego/dwl/src/branch/remembertags)
- [2024-03-27](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/remembertags/remembertags.patch)
### Authors
- [minego](https://codeberg.org/minego)
@@ -0,0 +1,105 @@
From fea6eb3cfc84ede8403c89a3230f5c658a6c7bd1 Mon Sep 17 00:00:00 2001
From: Micah N Gorrell <m@minego.net>
Date: Wed, 27 Mar 2024 13:05:09 -0600
Subject: [PATCH] remembertags
---
config.def.h | 8 ++++----
dwl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/config.def.h b/config.def.h
index 9009517..2312802 100644
--- a/config.def.h
+++ b/config.def.h
@@ -105,10 +105,10 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
#define MODKEY WLR_MODIFIER_ALT
#define TAGKEYS(KEY,SKEY,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, KEY, remembertagsview, {.i = 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} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
diff --git a/dwl.c b/dwl.c
index 5867b0c..31a81aa 100644
--- a/dwl.c
+++ b/dwl.c
@@ -205,6 +205,11 @@ struct Monitor {
int gamma_lut_changed;
int nmaster;
char ltsymbol[16];
+ unsigned int createtag[2]; /* Create windows on the last tag directly selected, not all selected */
+ struct {
+ unsigned int tagset;
+ Client *zoomed;
+ } remembered[31];
};
typedef struct {
@@ -308,6 +313,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface,
double sx, double sy, uint32_t time);
static void printstatus(void);
static void quit(const Arg *arg);
+static void remembertagsview(const Arg *arg);
static void rendermon(struct wl_listener *listener, void *data);
static void requestdecorationmode(struct wl_listener *listener, void *data);
static void requeststartdrag(struct wl_listener *listener, void *data);
@@ -1951,6 +1957,48 @@ quit(const Arg *arg)
wl_display_terminate(dpy);
}
+void
+remembertagsview(const Arg *arg) {
+ unsigned newtags = (1 << arg->i) & TAGMASK;
+ int oldtag;
+ int active;
+ unsigned int newcreate;
+
+ if (selmon == NULL) {
+ return;
+ }
+
+ oldtag = selmon->createtag[selmon->seltags];
+ active = (oldtag == arg->i);
+
+ if (oldtag < TAGCOUNT) {
+ selmon->remembered[oldtag].tagset = selmon->tagset[selmon->seltags];
+ }
+
+ selmon->seltags ^= 1; /*toggle tagset*/
+
+ if (-1 == arg->i) {
+ /* A specific tag was not specified */
+ active = 0;
+ newcreate = selmon->createtag[selmon->seltags];
+ } else {
+ newcreate = arg->i;
+ }
+
+ if (active) {
+ /* Select twice to isolate the tag */
+ selmon->tagset[selmon->seltags] = newtags;
+ } else if (arg->i < TAGCOUNT) {
+ /* Restore whatever was previously on this tag */
+ selmon->tagset[selmon->seltags] = newtags | selmon->remembered[newcreate].tagset;
+ }
+
+ selmon->createtag[selmon->seltags] = newcreate;
+ focusclient(focustop(selmon), 1);
+ arrange(selmon);
+ printstatus();
+}
+
void
rendermon(struct wl_listener *listener, void *data)
{
--
2.44.0
+10
View File
@@ -0,0 +1,10 @@
### Description
Add a tab bar or window title to the top or bottom of windows.
**This is the old version of the `tab` patch. Deprecated because the [new version](https://codeberg.org/dwl/dwl-patches/raw/branch-main/patches/tab) is significantly more efficient and well-written than this, and it better adheres to the suckless philosophy.**
### Download
- [2024-03-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tab/tab.patch)
### Authors
- [dev-gm](https://codeberg.org/dev-gm)
+461
View File
@@ -0,0 +1,461 @@
From b624206781513cdff1b9609fc5ac4b848094e1b4 Mon Sep 17 00:00:00 2001
From: Gavin M <github@gavinm.us>
Date: Fri, 15 Mar 2024 16:37:23 -0500
Subject: [PATCH] Tabbed patch
---
Makefile | 2 +-
config.def.h | 18 +++-
dwl.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 281 insertions(+), 15 deletions(-)
diff --git a/Makefile b/Makefile
index a67fdd3..182eb87 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unu
-Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types -Wfloat-conversion
# CFLAGS / LDFLAGS
-PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS)
+PKGS = wlroots wayland-server xkbcommon libinput cairo pangocairo $(XLIBS)
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
diff --git a/config.def.h b/config.def.h
index 9009517..1ca270f 100644
--- a/config.def.h
+++ b/config.def.h
@@ -7,6 +7,16 @@
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 unsigned int borderpx = 1; /* border pixel of windows */
+static const double title_border_width = 0.75;
+static const unsigned int title_padding = 11;
+static const int title_top = 0;
+static const LayoutType floating_title_type = LAYOUT_TYPE_LABEL;
+static const char title_font[] = "Dejavu Sans Mono 10.5";
+static const float title_font_color[] = COLOR(0xffffffff);
+static const float title_focus_bg[] = COLOR(0x3b3b3bff);
+static const float title_root_bg[] = COLOR(0x131313ff);
+static const float title_urgent_bg[] = COLOR(0x00ff00ff);
+static const float title_border_color[] = COLOR(0x3b3b3bff);
static const float rootcolor[] = COLOR(0x222222ff);
static const float bordercolor[] = COLOR(0x444444ff);
static const float focuscolor[] = COLOR(0x005577ff);
@@ -30,10 +40,10 @@ static const Rule rules[] = {
/* layout(s) */
static const Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile },
- { "><>", NULL }, /* no layout function means floating behavior */
- { "[M]", monocle },
+ /* symbol type render_only_top arrange function */
+ { "[]=", LAYOUT_TYPE_NONE, 0, tile },
+ { "><>", LAYOUT_TYPE_LABEL, 0, NULL }, /* no layout function means floating behavior */
+ { "[M]", LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS, 1, monocle },
};
/* monitors */
diff --git a/dwl.c b/dwl.c
index 5867b0c..e613d17 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2,6 +2,11 @@
* See LICENSE file for copyright and license details.
*/
#include <getopt.h>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+#include <pango/pango-font.h>
+#include <pango/pango-layout.h>
+#include <libdrm/drm_fourcc.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
#include <signal.h>
@@ -13,8 +18,10 @@
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/backend/libinput.h>
+#include <wlr/interfaces/wlr_buffer.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_cursor_shape_v1.h>
@@ -110,6 +117,7 @@ typedef struct {
struct wlr_scene_tree *scene;
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
struct wlr_scene_tree *scene_surface;
+ struct wlr_scene_buffer *titlebar;
struct wl_list link;
struct wl_list flink;
union {
@@ -137,7 +145,7 @@ typedef struct {
#endif
unsigned int bw;
uint32_t tags;
- int isfloating, isurgent, isfullscreen;
+ int isfloating, isurgent, isfullscreen, titleisinit, istabbed;
uint32_t resize; /* configure serial of a pending resize */
} Client;
@@ -179,8 +187,17 @@ typedef struct {
struct wl_listener surface_commit;
} LayerSurface;
+typedef enum {
+ LAYOUT_TYPE_NONE,
+ LAYOUT_TYPE_LABEL,
+ LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS,
+ LAYOUT_TYPE_TABS_ALWAYS
+} LayoutType;
+
typedef struct {
const char *symbol;
+ LayoutType type;
+ int render_top_only;
void (*arrange)(Monitor *);
} Layout;
@@ -282,6 +299,7 @@ static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static Client *focustop(Monitor *m);
+static Client *focustop_onlytiled(Monitor *m, int onlytiled);
static void fullscreennotify(struct wl_listener *listener, void *data);
static void handlesig(int signo);
static void incnmaster(const Arg *arg);
@@ -309,6 +327,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface,
static void printstatus(void);
static void quit(const Arg *arg);
static void rendermon(struct wl_listener *listener, void *data);
+static void rendertitlebar(Client *client);
static void requestdecorationmode(struct wl_listener *listener, void *data);
static void requeststartdrag(struct wl_listener *listener, void *data);
static void requestmonstate(struct wl_listener *listener, void *data);
@@ -349,6 +368,7 @@ static void xytonode(double x, double y, struct wlr_surface **psurface,
static void zoom(const Arg *arg);
/* variables */
+static int title_height;
static const char broken[] = "broken";
static pid_t child_pid = -1;
static int locked;
@@ -973,6 +993,7 @@ createnotify(struct wl_listener *listener, void *data)
c = xdg_surface->data = ecalloc(1, sizeof(*c));
c->surface.xdg = xdg_surface;
c->bw = borderpx;
+ c->titleisinit = c->istabbed = 0;
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
@@ -1360,6 +1381,22 @@ focustop(Monitor *m)
return NULL;
}
+Client *
+focustop_onlytiled(Monitor *m, int onlytiled)
+{
+ Client *c;
+ if (!m)
+ return NULL;
+ wl_list_for_each(c, &fstack, flink) {
+ if (VISIBLEON(c, m)) {
+ if ((onlytiled == 1 && c->isfloating) || (onlytiled == 2 && (!c->isfloating || !m->lt[m->sellt]->arrange)))
+ continue;
+ return c;
+ }
+ }
+ return NULL;
+}
+
void
fullscreennotify(struct wl_listener *listener, void *data)
{
@@ -2003,6 +2040,195 @@ skip:
wlr_output_state_finish(&pending);
}
+struct text_buffer {
+ struct wlr_buffer base;
+ void *data;
+ uint32_t format;
+ size_t stride;
+};
+
+static void text_buffer_destroy(struct wlr_buffer *wlr_buffer) {
+ struct text_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
+ free(buffer->data);
+ free(buffer);
+}
+
+static bool text_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
+ uint32_t flags, void **data, uint32_t *format, size_t *stride) {
+ struct text_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
+ if(data != NULL) {
+ *data = (void *)buffer->data;
+ }
+ if(format != NULL) {
+ *format = buffer->format;
+ }
+ if(stride != NULL) {
+ *stride = buffer->stride;
+ }
+ return true;
+}
+
+static void text_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
+ // This space is intentionally left blank
+}
+
+static const struct wlr_buffer_impl text_buffer_impl = {
+ .destroy = text_buffer_destroy,
+ .begin_data_ptr_access = text_buffer_begin_data_ptr_access,
+ .end_data_ptr_access = text_buffer_end_data_ptr_access,
+};
+
+static struct text_buffer *text_buffer_create(uint32_t width, uint32_t height, uint32_t stride) {
+ struct text_buffer *buffer = calloc(1, sizeof(*buffer));
+ if (buffer == NULL) {
+ return NULL;
+ }
+
+ wlr_buffer_init(&buffer->base, &text_buffer_impl, width, height);
+ buffer->format = DRM_FORMAT_ARGB8888;
+ buffer->stride = stride;
+
+ buffer->data = malloc(buffer->stride * height);
+ if (buffer->data == NULL) {
+ free(buffer);
+ return NULL;
+ }
+
+ return buffer;
+}
+
+void
+rendertitlebar(Client *c)
+{
+ struct wl_list *init_destroy, *cursor_destroy;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ cairo_t *cr;
+ PangoFontDescription *desc;
+ PangoLayout *layout;
+ LayoutType title_type;
+ Client *l, *sel;
+ unsigned int len, tabsize, i;
+ const char *title;
+ const float *color;
+ unsigned char *data;
+ int stride;
+ struct text_buffer *text_buffer;
+ void *data_ptr;
+
+ if (!c || !c->scene || !c->mon || !selmon || (!VISIBLEON(c, selmon) && c->mon == selmon))
+ return;
+
+ if (c->titleisinit) {
+ init_destroy = cursor_destroy = &c->titlebar->node.events.destroy.listener_list;
+ do {
+ cursor_destroy = cursor_destroy->next;
+ } while (cursor_destroy && cursor_destroy != init_destroy);
+ if (!cursor_destroy) {
+ return;
+ }
+ wlr_scene_node_destroy(&c->titlebar->node);
+ }
+ c->titleisinit = c->istabbed = 0;
+
+ sel = focustop_onlytiled(c->mon, c->isfloating + 1);
+
+ if (c->isfullscreen)
+ return;
+ title_type = c->isfloating ? floating_title_type : c->mon->lt[c->mon->sellt]->type;
+
+ if (title_type == LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS || title_type == LAYOUT_TYPE_TABS_ALWAYS) {
+ len = 0;
+ wl_list_for_each(l, &clients, link) {
+ if (VISIBLEON(l, c->mon) && l->isfloating == c->isfloating)
+ len++;
+ }
+ if (title_type == LAYOUT_TYPE_TABS_ONLY_MULTIPLE_CLIENTS && len <= 1)
+ return;
+ }
+
+ if (c->mon->lt[c->mon->sellt]->render_top_only == 1 && !c->isfloating && c != sel) {
+ c->istabbed = 1;
+ return;
+ } /*else if (c->mon->lt[c->mon->sellt]->render_top_only == 2 && c != sel) {
+ c->istabbed = 1;
+ return;
+ }*/
+
+ if (title_type == LAYOUT_TYPE_NONE)
+ return;
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, c->geom.width, title_height);
+ if ((status = cairo_surface_status(surface)) != CAIRO_STATUS_SUCCESS) {
+ wlr_log(WLR_ERROR, "cairo_image_surface_create failed: %s",
+ cairo_status_to_string(status));
+ return;
+ }
+ cr = cairo_create(surface);
+ desc = pango_font_description_from_string(title_font);
+ layout = pango_cairo_create_layout(cr);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
+
+ cairo_set_line_width(cr, title_border_width);
+
+ if (title_type == LAYOUT_TYPE_LABEL) {
+ cairo_rectangle(cr, 0, 0, c->geom.width, title_height);
+ cairo_set_source_rgba(cr, title_focus_bg[0], title_focus_bg[1], title_focus_bg[2], title_focus_bg[3]);
+ cairo_fill_preserve(cr);
+ cairo_set_source_rgba(cr, title_border_color[0], title_border_color[1], title_border_color[2], title_border_color[3]);
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, title_font_color[0], title_font_color[1], title_font_color[2], title_font_color[3]);
+ title = client_get_title(c);
+ pango_layout_set_text(layout, title ? title : " ", (c->geom.width - title_padding) * PANGO_SCALE);
+ cairo_move_to(cr, title_padding, 0);
+ pango_cairo_show_layout(cr, layout);
+ } else {
+ tabsize = c->geom.width / len;
+ i = 0;
+ wl_list_for_each(l, &clients, link) {
+ if (VISIBLEON(l, c->mon) && l->isfloating == c->isfloating) {
+ cairo_rectangle(cr, i * tabsize, 0, (i + 1) * tabsize, title_height);
+ color = (l == sel) ? title_focus_bg
+ : (c->isurgent ? title_urgent_bg : title_root_bg);
+ cairo_set_source_rgba(cr, color[0], color[1], color[2], color[3]);
+ cairo_fill_preserve(cr);
+ cairo_set_source_rgba(cr, title_border_color[0], title_border_color[1], title_border_color[2], title_border_color[3]);
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, title_font_color[0], title_font_color[1], title_font_color[2], title_font_color[3]);
+ title = client_get_title(l);
+ pango_layout_set_text(layout, title ? title : " ", (tabsize - title_padding) * PANGO_SCALE);
+ cairo_move_to(cr, (i * tabsize) + title_padding, 0);
+ pango_cairo_show_layout(cr, layout);
+ i++;
+ }
+ }
+ }
+
+ data = cairo_image_surface_get_data(surface);
+ stride = cairo_image_surface_get_stride(surface);
+ text_buffer = text_buffer_create(c->geom.width, title_height, stride);
+
+ if(!wlr_buffer_begin_data_ptr_access(&text_buffer->base,
+ WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data_ptr, NULL, NULL)) {
+ wlr_log(WLR_ERROR, "%s", "Failed to get pointer access to text buffer");
+ return;
+ }
+ memcpy(data_ptr, data, stride * title_height);
+ wlr_buffer_end_data_ptr_access(&text_buffer->base);
+ cairo_surface_destroy(surface);
+
+ c->titlebar = wlr_scene_buffer_create(c->scene, &text_buffer->base);
+ c->titleisinit = c->istabbed = 1;
+
+ wlr_scene_node_set_position(&c->titlebar->node, 0, !title_top ? c->geom.height - title_height : 0);
+ wlr_scene_node_raise_to_top(&c->titlebar->node);
+
+ pango_font_description_free(desc);
+ g_object_unref(layout);
+ cairo_destroy(cr);
+}
+
void
requestdecorationmode(struct wl_listener *listener, void *data)
{
@@ -2036,24 +2262,30 @@ resize(Client *c, struct wlr_box geo, int interact)
{
struct wlr_box *bbox = interact ? &sgeom : &c->mon->w;
struct wlr_box clip;
+ unsigned int th;
+ int draw_borders = 1;
client_set_bounds(c, geo.width, geo.height);
c->geom = geo;
+ c->bw = draw_borders ? borderpx : 0;
applybounds(c, bbox);
+ rendertitlebar(c);
+ th = c->istabbed ? title_height : c->bw;
+
/* Update scene-graph, including borders */
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
- wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
- wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
- wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
- wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
- wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
- wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
- wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
- wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
+ wlr_scene_node_set_position(&c->scene_surface->node, c->bw, title_top ? th : c->bw);
+ wlr_scene_rect_set_size(c->border[0], c->geom.width, (title_top && c->istabbed) ? 0 : c->bw);
+ wlr_scene_rect_set_size(c->border[1], c->geom.width, (!title_top && c->istabbed) ? 0 : c->bw);
+ wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - (c->bw + th));
+ wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - (c->bw + th));
+ wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - (title_top ? c->bw : th));
+ wlr_scene_node_set_position(&c->border[2]->node, 0, title_top ? th : c->bw);
+ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, title_top ? th : c->bw);
/* this is a no-op if size hasn't changed */
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
- c->geom.height - 2 * c->bw);
+ c->geom.height - (c->bw + th));
client_get_clip(c, &clip);
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
}
@@ -2274,6 +2506,11 @@ setup(void)
int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ PangoFontDescription *desc;
+ PangoLayout *layout;
+
sigemptyset(&sa.sa_mask);
for (i = 0; i < (int)LENGTH(sig); i++)
@@ -2506,6 +2743,24 @@ setup(void)
wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend));
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
+
+ cr = cairo_create(surface);
+
+ desc = pango_font_description_from_string(title_font);
+ /* Create Pango layout. */
+ layout = pango_cairo_create_layout(cr);
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, " ", -1);
+ /* Set width and height to text size */
+ pango_layout_get_pixel_size(layout, NULL, &title_height);
+
+ /* Cleanup */
+ pango_font_description_free (desc);
+ cairo_surface_destroy(surface);
+ g_object_unref (layout);
+ cairo_destroy(cr);
+
/* Make sure XWayland clients don't connect to the parent X server,
* e.g when running in the x11 backend or the wayland backend and the
* compositor has Xwayland support */
@@ -2978,6 +3233,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
c->surface.xwayland = xsurface;
c->type = X11;
c->bw = borderpx;
+ c->titleisinit = c->istabbed = 0;
/* Listen to the various events it can emit */
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
--
2.44.0
+14
View File
@@ -0,0 +1,14 @@
### Description
> This patch is no longer being maintained by me [wochap](https://codeberg.org/wochap), since I'm now using a different patch specific to my use case: https://codeberg.org/wochap/dwl/src/branch/v0.6-b/xkb-rules-switcher/xkb-rules-switcher.patch
Switch between multiple keyboard layouts at runtime.
### Download
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/togglekblayout)
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/togglekblayout/togglekblayout.patch)
### Authors
- [wochap](https://codeberg.org/wochap)
- [Stivvo](https://github.com/Stivvo)
@@ -0,0 +1,107 @@
From 1bb99c78da484ce6036dc997962ed2f4c0d11208 Mon Sep 17 00:00:00 2001
From: wochap <gean.marroquin@gmail.com>
Date: Thu, 19 Oct 2023 23:21:49 -0500
Subject: [PATCH 1/2] apply main...Stivvo:toggleKbLayout.patch
---
config.def.h | 6 ++++++
dwl.c | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/config.def.h b/config.def.h
index db0babc..caa09ea 100644
--- a/config.def.h
+++ b/config.def.h
@@ -57,6 +57,11 @@ static const struct xkb_rule_names xkb_rules = {
static const int repeat_rate = 25;
static const int repeat_delay = 600;
+/* gb will be set the first time togglekblayout is called, then us.. it is
+ * recommended to set the same layout in position 0 of kblayouts and in
+ * xkb_rules */
+static const char *kblayouts[] = {"us", "gb"};
+
/* Trackpad */
static const int tap_to_click = 1;
static const int tap_and_drag = 1;
@@ -141,6 +146,7 @@ static const Key keys[] = {
{ 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} },
+ { MODKEY, XKB_KEY_w, togglekblayout, {0} },
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
diff --git a/dwl.c b/dwl.c
index ef27a1d..25458e6 100644
--- a/dwl.c
+++ b/dwl.c
@@ -312,6 +312,7 @@ static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *m);
static void togglefloating(const Arg *arg);
+static void togglekblayout(const Arg *arg);
static void togglefullscreen(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
@@ -368,6 +369,7 @@ static struct wl_listener lock_listener = {.notify = locksession};
static struct wlr_seat *seat;
static struct wl_list keyboards;
+static unsigned int kblayout = 0; /* index of kblayouts */
static unsigned int cursor_mode;
static Client *grabc;
static int grabcx, grabcy; /* client-relative */
@@ -2454,6 +2456,24 @@ togglefullscreen(const Arg *arg)
setfullscreen(sel, !sel->isfullscreen);
}
+void
+togglekblayout(const Arg *arg)
+{
+ Keyboard *kb;
+ struct xkb_rule_names newrule = xkb_rules;
+
+ kblayout = (kblayout + 1) % LENGTH(kblayouts);
+ newrule.layout = kblayouts[kblayout];
+ wl_list_for_each(kb, &keyboards, link) {
+ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &newrule,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ wlr_keyboard_set_keymap(kb->device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
+ xkb_context_unref(context);
+ }
+}
+
void
toggletag(const Arg *arg)
{
--
2.42.0
From 3428168a686e2da8ba8a9dc1473350610afaef19 Mon Sep 17 00:00:00 2001
From: wochap <gean.marroquin@gmail.com>
Date: Thu, 19 Oct 2023 23:46:06 -0500
Subject: [PATCH 2/2] fix build
---
dwl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dwl.c b/dwl.c
index 25458e6..090280f 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2468,7 +2468,7 @@ togglekblayout(const Arg *arg)
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
struct xkb_keymap *keymap = xkb_map_new_from_names(context, &newrule,
XKB_KEYMAP_COMPILE_NO_FLAGS);
- wlr_keyboard_set_keymap(kb->device->keyboard, keymap);
+ wlr_keyboard_set_keymap(kb->wlr_keyboard, keymap);
xkb_keymap_unref(keymap);
xkb_context_unref(context);
}
--
2.42.0