+
+ +
+
+
+
+ + + + + +
+
+ +
+
+ + + + + + +
+
+ +
+ + + + + + + + +
+
+ + + 36 + +
+
+ + +
+
+ + + 132 + +
+
+ + + + + + +
+ + Fork + + + + 93 + +
+ + + + + + +
+ +
+ + + +
+ + + +
+ + + Code + + + + + + Issues + + 14 + + + + + + + + + Pull requests + + 5 + + + + + + + + + + + + + Wiki + + + + + + + + Activity + + + + + + + + + + +
+ +
+
+
+ +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + dwl-patches/patches/btrtile/btrtile-v0.8-gaps.patch + + +
+
+ + + +
+
+ + + + + + + +
+ + +
+
+ + + + + julmajustus + + + + + + + + + + + + + 03de6e2ada
+ + + + + + + + +
+
+ + + + + btrtile: Spring update pt2 + + +
- Simplified the resizing logic to avoid full arrange calls from
+motionnotify
+- Minor intend fixes
+ +
+ + +
+ + +
+ 2026-05-21 00:54:00 +03:00 +
+ + +
+ + +

+
+ +
+ + +
+ 929 lines +
+ + + +
+ 27 KiB +
+ + + +
+ Diff +
+ + + + + +
+ + +
+
+ + +
+ + Raw + + Permalink + + + Blame + + History + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
From 1520d1f200ef0fb381683c1bcd58e553b52ac289 Mon Sep 17 00:00:00 2001 +
From: julmajustus <julmajustus@tutanota.com> +
Date: Thu, 21 May 2026 00:42:07 +0300 +
Subject: [PATCH] btrtile: Spring update pt2 +
+
- Simplified the resizing logic to avoid full arrange calls from +
motionnotify +
- Minor intend fixes +
--- +
btrtile.c | 583 +++++++++++++++++++++++++++++++++++++++++++++++++++ +
config.def.h | 12 ++ +
dwl.c | 152 +++++++++++--- +
3 files changed, 720 insertions(+), 27 deletions(-) +
create mode 100644 btrtile.c +
+
diff --git a/btrtile.c b/btrtile.c +
new file mode 100644 +
index 0000000..f05a30f +
--- /dev/null +
+++ b/btrtile.c +
@@ -0,0 +1,583 @@ +
+/* ************************************************************************** */ +
+/* @@@ @@@@@@@@ */ +
+/* @@@ @@@@@@@@@@ */ +
+/* @@! @@! @@@@ */ +
+/* !@! !@! @!@!@ */ +
+/* btrtile.c @!! @!@ @! !@! */ +
+/* !!! !@!!! !!! */ +
+/* By: julmajustus <julmajustus@tutanota.com> !!: !!:! !!! */ +
+/* ::! :!: !:! */ +
+/* Created: 2024/12/15 00:26:07 by julmajustus :: ::::::: :: */ +
+/* Updated: 2026/05/20 22:38:02 by julmajustus : : : : : : */ +
+/* */ +
+/* ************************************************************************** */ +
+ +
+typedef struct LayoutNode { +
+ unsigned int is_client_node; +
+ unsigned int is_split_vertically; +
+ float split_ratio; +
+ struct LayoutNode *left; +
+ struct LayoutNode *right; +
+ struct LayoutNode *split_node; +
+ Client *client; +
+} LayoutNode; +
+ +
+static void apply_layout(Monitor *m, LayoutNode *node, +
+ struct wlr_box area, unsigned int is_root); +
+static void btrtile(Monitor *m); +
+static LayoutNode *create_client_node(Client *c); +
+static LayoutNode *create_split_node(unsigned int is_split_vertically, +
+ LayoutNode *left, LayoutNode *right); +
+static void destroy_node(LayoutNode *node); +
+static void destroy_tree(Monitor *m); +
+static LayoutNode *find_client_node(LayoutNode *node, Client *c); +
+static LayoutNode *find_suitable_split(Monitor *m, LayoutNode *start, +
+ unsigned int need_vertical, int focused_on_left); +
+static void init_tree(Monitor *m); +
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client); +
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c); +
+static void remove_client(Monitor *m, Client *c); +
+static void setratio_h(const Arg *arg); +
+static void setratio_v(const Arg *arg); +
+static void swapclients(const Arg *arg); +
+static unsigned int visible_count(LayoutNode *node, Monitor *m); +
+static Client *xytoclient(double x, double y); +
+ +
+static double resize_last_update_x, resize_last_update_y; +
+static uint32_t last_resize_time = 0; +
+ +
+void +
+apply_layout(Monitor *m, LayoutNode *node, +
+ struct wlr_box area, unsigned int is_root) +
+{ +
+ Client *c; +
+ float ratio; +
+ unsigned int left_count, right_count, mid, e = m->gaps; +
+ struct wlr_box left_area, right_area; +
+ +
+ if (!node) +
+ return; +
+ +
+ if (is_root && e) { +
+ area.x += gappx; +
+ area.y += gappx; +
+ area.width -= 2 * gappx; +
+ area.height -= 2 * gappx; +
+ } +
+ +
+ /* If this node is a client node, check if it is visible. */ +
+ if (node->is_client_node) { +
+ c = node->client; +
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen) +
+ return; +
+ if (area.x == c->old_geom.x && area.y == c->old_geom.y && +
+ area.width == c->old_geom.width && area.height == c->old_geom.height) +
+ return; +
+ resize(c, area, 0); +
+ c->old_geom = area; +
+ return; +
+ } +
+ +
+ /* For a split node, we see how many visible children are on each side: */ +
+ left_count = visible_count(node->left, m); +
+ right_count = visible_count(node->right, m); +
+ +
+ if (left_count == 0 && right_count == 0) { +
+ return; +
+ } else if (left_count > 0 && right_count == 0) { +
+ apply_layout(m, node->left, area, 0); +
+ return; +
+ } else if (left_count == 0 && right_count > 0) { +
+ apply_layout(m, node->right, area, 0); +
+ return; +
+ } +
+ +
+ /* If we’re here, we have visible clients in both subtrees. */ +
+ ratio = node->split_ratio; +
+ if (ratio < 0.05f) +
+ ratio = 0.05f; +
+ if (ratio > 0.95f) +
+ ratio = 0.95f; +
+ +
+ memset(&left_area, 0, sizeof(left_area)); +
+ memset(&right_area, 0, sizeof(right_area)); +
+ +
+ if (node->is_split_vertically) { +
+ mid = (unsigned int)(area.width * ratio); +
+ left_area.x = area.x; +
+ left_area.y = area.y; +
+ left_area.width = mid; +
+ left_area.height = area.height; +
+ +
+ right_area.x = area.x + mid; +
+ right_area.y = area.y; +
+ right_area.width = area.width - mid; +
+ right_area.height = area.height; +
+ +
+ if (e) { +
+ left_area.width -= gappx / 2; +
+ right_area.x += gappx / 2; +
+ right_area.width -= gappx / 2; +
+ } +
+ } else { +
+ /* horizontal split */ +
+ mid = (unsigned int)(area.height * ratio); +
+ left_area.x = area.x; +
+ left_area.y = area.y; +
+ left_area.width = area.width; +
+ left_area.height = mid; +
+ +
+ right_area.x = area.x; +
+ right_area.y = area.y + mid; +
+ right_area.width = area.width; +
+ right_area.height= area.height - mid; +
+ +
+ if (e) { +
+ left_area.height -= gappx / 2; +
+ right_area.y += gappx / 2; +
+ right_area.height -= gappx / 2; +
+ } +
+ } +
+ +
+ apply_layout(m, node->left, left_area, 0); +
+ apply_layout(m, node->right, right_area, 0); +
+} +
+ +
+void +
+btrtile(Monitor *m) +
+{ +
+ Client *c, *focused = NULL; +
+ int n = 0; +
+ LayoutNode *found; +
+ struct wlr_box full_area; +
+ +
+ if (!m) +
+ return; +
+ +
+ /* Remove non tiled clients from tree. */ +
+ wl_list_for_each(c, &clients, link) { +
+ if (c->mon == m && !c->isfloating && !c->isfullscreen) { +
+ } else { +
+ remove_client(m, c); +
+ } +
+ } +
+ +
+ /* If no client is found under cursor, fallback to focustop(m) */ +
+ if (!(focused = xytoclient(cursor->x, cursor->y))) +
+ focused = focustop(m); +
+ +
+ /* Insert visible clients that are not part of the tree. */ +
+ wl_list_for_each(c, &clients, link) { +
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && c->mon == m) { +
+ found = find_client_node(m->root, c); +
+ if (!found) { +
+ insert_client(m, focused, c); +
+ } +
+ n++; +
+ } +
+ } +
+ +
+ if (n == 0) +
+ return; +
+ +
+ full_area = m->w; +
+ apply_layout(m, m->root, full_area, 1); +
+} +
+ +
+LayoutNode * +
+create_client_node(Client *c) +
+{ +
+ LayoutNode *node = calloc(1, sizeof(LayoutNode)); +
+ +
+ if (!node) +
+ return NULL; +
+ node->is_client_node = 1; +
+ node->split_ratio = 0.5f; +
+ node->client = c; +
+ return node; +
+} +
+ +
+LayoutNode * +
+create_split_node(unsigned int is_split_vertically, +
+ LayoutNode *left, LayoutNode *right) +
+{ +
+ LayoutNode *node = calloc(1, sizeof(LayoutNode)); +
+ +
+ if (!node) +
+ return NULL; +
+ node->is_client_node = 0; +
+ node->split_ratio = 0.5f; +
+ node->is_split_vertically = is_split_vertically; +
+ node->left = left; +
+ node->right = right; +
+ if (left) +
+ left->split_node = node; +
+ if (right) +
+ right->split_node = node; +
+ return node; +
+} +
+ +
+void +
+destroy_node(LayoutNode *node) +
+{ +
+ if (!node) +
+ return; +
+ if (!node->is_client_node) { +
+ destroy_node(node->left); +
+ destroy_node(node->right); +
+ } +
+ free(node); +
+} +
+ +
+void +
+destroy_tree(Monitor *m) +
+{ +
+ if (!m || !m->root) +
+ return; +
+ destroy_node(m->root); +
+ m->root = NULL; +
+} +
+ +
+LayoutNode * +
+find_client_node(LayoutNode *node, Client *c) +
+{ +
+ LayoutNode *res; +
+ +
+ if (!node || !c) +
+ return NULL; +
+ if (node->is_client_node) { +
+ return (node->client == c) ? node : NULL; +
+ } +
+ res = find_client_node(node->left, c); +
+ return res ? res : find_client_node(node->right, c); +
+} +
+ +
+LayoutNode * +
+find_suitable_split(Monitor *m, LayoutNode *start_node, +
+ unsigned int need_vertical, int focused_on_left) +
+{ +
+ LayoutNode *n = start_node, *child = NULL; +
+ +
+ if (!m) +
+ return NULL; +
+ +
+ if (n && n->is_client_node) { +
+ child = n; +
+ n = n->split_node; +
+ } +
+ +
+ while (n) { +
+ if (!n->is_client_node && n->is_split_vertically == need_vertical +
+ && visible_count(n->left, m) > 0 +
+ && visible_count(n->right, m) > 0) { +
+ if ((focused_on_left && n->left == child) || +
+ (!focused_on_left && n->right == child)) +
+ return n; +
+ } +
+ child = n; +
+ n = n->split_node; +
+ } +
+ return NULL; +
+} +
+void +
+init_tree(Monitor *m) +
+{ +
+ if (m) +
+ m->root = NULL; +
+} +
+ +
+void +
+insert_client(Monitor *m, Client *focused_client, Client *new_client) +
+{ +
+ Client *old_client; +
+ LayoutNode **root = &m->root, *old_root, +
+ *focused_node, *new_client_node, *old_client_node; +
+ unsigned int wider, mid_x, mid_y; +
+ +
+ /* If no root , new client becomes the root. */ +
+ if (!*root) { +
+ *root = create_client_node(new_client); +
+ return; +
+ } +
+ +
+ /* Find the focused_client node, +
+ * if not found split the root. */ +
+ focused_node = focused_client ? +
+ find_client_node(*root, focused_client) : NULL; +
+ if (!focused_node) { +
+ old_root = *root; +
+ new_client_node = create_client_node(new_client); +
+ *root = create_split_node(1, old_root, new_client_node); +
+ return; +
+ } +
+ +
+ /* Turn focused node from a client node into a split node, +
+ * and attach old_client + new_client. */ +
+ old_client = focused_node->client; +
+ old_client_node = create_client_node(old_client); +
+ new_client_node = create_client_node(new_client); +
+ +
+ /* Decide split direction. */ +
+ wider = (focused_client->geom.width >= focused_client->geom.height); +
+ focused_node->is_client_node = 0; +
+ focused_node->client = NULL; +
+ focused_node->is_split_vertically = (wider ? 1 : 0); +
+ +
+ /* Pick new_client side depending on the cursor position. */ +
+ mid_x = focused_client->geom.x + focused_client->geom.width / 2; +
+ mid_y = focused_client->geom.y + focused_client->geom.height / 2; +
+ +
+ if (wider) { +
+ /* vertical split => left vs right */ +
+ if (cursor->x <= mid_x) { +
+ focused_node->left = new_client_node; +
+ focused_node->right = old_client_node; +
+ } else { +
+ focused_node->left = old_client_node; +
+ focused_node->right = new_client_node; +
+ } +
+ } else { +
+ /* horizontal split => top vs bottom */ +
+ if (cursor->y <= mid_y) { +
+ focused_node->left = new_client_node; +
+ focused_node->right = old_client_node; +
+ } else { +
+ focused_node->left = old_client_node; +
+ focused_node->right = new_client_node; +
+ } +
+ } +
+ old_client_node->split_node = focused_node; +
+ new_client_node->split_node = focused_node; +
+ focused_node->split_ratio = 0.5f; +
+} +
+ +
+LayoutNode * +
+remove_client_node(LayoutNode *node, Client *c) +
+{ +
+ LayoutNode *tmp; +
+ if (!node) +
+ return NULL; +
+ if (node->is_client_node) { +
+ /* If this client_node is the client we're removing, +
+ * return NULL to remove it */ +
+ if (node->client == c) { +
+ free(node); +
+ return NULL; +
+ } +
+ return node; +
+ } +
+ +
+ node->left = remove_client_node(node->left, c); +
+ node->right = remove_client_node(node->right, c); +
+ +
+ /* If one of the client node is NULL after removal and the other is not, +
+ * we "lift" the other client node up to replace this split node. */ +
+ if (!node->left && node->right) { +
+ tmp = node->right; +
+ +
+ /* Save pointer to split node */ +
+ if (tmp) +
+ tmp->split_node = node->split_node; +
+ +
+ free(node); +
+ return tmp; +
+ } +
+ +
+ if (!node->right && node->left) { +
+ tmp = node->left; +
+ +
+ /* Save pointer to split node */ +
+ if (tmp) +
+ tmp->split_node = node->split_node; +
+ +
+ free(node); +
+ return tmp; +
+ } +
+ +
+ /* If both children exist or both are NULL (empty tree), +
+ * return node as is. */ +
+ return node; +
+} +
+ +
+void +
+remove_client(Monitor *m, Client *c) +
+{ +
+ if (!m->root || !c) +
+ return; +
+ m->root = remove_client_node(m->root, c); +
+} +
+ +
+static void +
+setratio(unsigned int need_vertical, const Arg *arg) +
+{ +
+ Client *sel; +
+ LayoutNode *client_node, *split_node; +
+ float new_ratio; +
+ int focused_on_left; +
+ +
+ if (!selmon || !selmon->lt[selmon->sellt]->arrange) +
+ return; +
+ +
+ sel = focustop(selmon); +
+ if (!sel) +
+ return; +
+ +
+ client_node = find_client_node(selmon->root, sel); +
+ if (!client_node) +
+ return; +
+ +
+ focused_on_left = (arg->f >= 0.0f); +
+ +
+ split_node = find_suitable_split(selmon, client_node, need_vertical, focused_on_left); +
+ +
+ if (!split_node) +
+ split_node = find_suitable_split(selmon, client_node, need_vertical, !focused_on_left); +
+ if (!split_node) +
+ return; +
+ +
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f; +
+ if (new_ratio < 0.05f) +
+ new_ratio = 0.05f; +
+ if (new_ratio > 0.95f) +
+ new_ratio = 0.95f; +
+ split_node->split_ratio = new_ratio; +
+ +
+ apply_layout(selmon, selmon->root, selmon->w, 1); +
+ /* Skip the arrange when called from motionnotify; that path calls +
+ * arrange itself after rate-limiting. */ +
+} +
+ +
+void +
+setratio_h(const Arg *arg) +
+{ +
+ setratio(1, arg); +
+} +
+ +
+void +
+setratio_v(const Arg *arg) +
+{ +
+ setratio(0, arg); +
+} +
+ +
+void swapclients(const Arg *arg) { +
+ Client *c, *tmp, *target = NULL, *sel = focustop(selmon); +
+ LayoutNode *sel_node, *target_node; +
+ int closest_dist = INT_MAX, dist, sel_center_x, sel_center_y, +
+ cand_center_x, cand_center_y; +
+ +
+ if (!sel || sel->isfullscreen || +
+ !selmon->root || !selmon->lt[selmon->sellt]->arrange) +
+ return; +
+ +
+ +
+ /* Get the center coordinates of the selected client */ +
+ sel_center_x = sel->geom.x + sel->geom.width / 2; +
+ sel_center_y = sel->geom.y + sel->geom.height / 2; +
+ +
+ wl_list_for_each(c, &clients, link) { +
+ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen || c == sel) +
+ continue; +
+ +
+ /* Get the center of candidate client */ +
+ cand_center_x = c->geom.x + c->geom.width / 2; +
+ cand_center_y = c->geom.y + c->geom.height / 2; +
+ +
+ /* Check that the candidate lies in the requested direction. */ +
+ switch (arg->ui) { +
+ case 0: +
+ if (cand_center_x >= sel_center_x) +
+ continue; +
+ break; +
+ case 1: +
+ if (cand_center_x <= sel_center_x) +
+ continue; +
+ break; +
+ case 2: +
+ if (cand_center_y >= sel_center_y) +
+ continue; +
+ break; +
+ case 3: +
+ if (cand_center_y <= sel_center_y) +
+ continue; +
+ break; +
+ default: +
+ continue; +
+ } +
+ +
+ /* Get distance between the centers */ +
+ dist = abs(sel_center_x - cand_center_x) + abs(sel_center_y - cand_center_y); +
+ if (dist < closest_dist) { +
+ closest_dist = dist; +
+ target = c; +
+ } +
+ } +
+ +
+ /* If target is found, swap the two clients’ positions in the layout tree */ +
+ if (target) { +
+ sel_node = find_client_node(selmon->root, sel); +
+ target_node = find_client_node(selmon->root, target); +
+ if (sel_node && target_node) { +
+ tmp = sel_node->client; +
+ sel_node->client = target_node->client; +
+ target_node->client = tmp; +
+ arrange(selmon); +
+ } +
+ } +
+} +
+ +
+unsigned int +
+visible_count(LayoutNode *node, Monitor *m) +
+{ +
+ Client *c; +
+ +
+ if (!node) +
+ return 0; +
+ /* Check if this client is visible. */ +
+ if (node->is_client_node) { +
+ c = node->client; +
+ if (c && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) +
+ return 1; +
+ return 0; +
+ } +
+ /* Else it’s a split node. */ +
+ return visible_count(node->left, m) + visible_count(node->right, m); +
+} +
+ +
+Client * +
+xytoclient(double x, double y) { +
+ Monitor *m = xytomon(x, y); +
+ Client *c, *closest = NULL; +
+ double dist, mindist = INT_MAX, dx, dy; +
+ +
+ wl_list_for_each_reverse(c, &clients, link) { +
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && +
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) && +
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){ +
+ return c; +
+ } +
+ } +
+ +
+ /* If no client was found at cursor position fallback to closest. */ +
+ wl_list_for_each_reverse(c, &clients, link) { +
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) { +
+ dx = 0, dy = 0; +
+ +
+ if (x < c->geom.x) +
+ dx = c->geom.x - x; +
+ else if (x > (c->geom.x + c->geom.width)) +
+ dx = x - (c->geom.x + c->geom.width); +
+ +
+ if (y < c->geom.y) +
+ dy = c->geom.y - y; +
+ else if (y > (c->geom.y + c->geom.height)) +
+ dy = y - (c->geom.y + c->geom.height); +
+ +
+ dist = dx * dx + dy * dy; +
+ if (dist < mindist) { +
+ mindist = dist; +
+ closest = c; +
+ } +
+ } +
+ } +
+ return closest; +
+} +
diff --git a/config.def.h b/config.def.h +
index 8a6eda0..bc04e3f 100644 +
--- a/config.def.h +
+++ b/config.def.h +
@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff); +
static const float urgentcolor[] = COLOR(0xff0000ff); +
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ +
static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */ +
+static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */ +
+static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */ +
+
+enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN }; +
/* tagging - TAGCOUNT must be no greater than 31 */ +
#define TAGCOUNT (9) +
+
@@ -30,6 +33,7 @@ static const Rule rules[] = { +
/* layout(s) */ +
static const Layout layouts[] = { +
/* symbol arrange function */ +
+ { "|w|", btrtile }, +
{ "[]=", tile }, +
{ "><>", NULL }, /* no layout function means floating behavior */ +
{ "[M]", monocle }, +
@@ -144,6 +148,14 @@ 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|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} }, +
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} }, +
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} }, +
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} }, +
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} }, +
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} }, +
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} }, +
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} }, +
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 44f3ad9..a121efc 100644 +
--- a/dwl.c +
+++ b/dwl.c +
@@ -1,6 +1,7 @@ +
/* +
* See LICENSE file for copyright and license details. +
*/ +
+#include <limits.h> +
#include <getopt.h> +
#include <libinput.h> +
#include <linux/input-event-codes.h> +
@@ -100,6 +101,7 @@ typedef struct { +
const Arg arg; +
} Button; +
+
+typedef struct LayoutNode LayoutNode; +
typedef struct Monitor Monitor; +
typedef struct { +
/* Must keep this field first */ +
@@ -137,8 +139,9 @@ typedef struct { +
#endif +
unsigned int bw; +
uint32_t tags; +
- int isfloating, isurgent, isfullscreen; +
+ int isfloating, isurgent, isfullscreen, was_tiled; +
uint32_t resize; /* configure serial of a pending resize */ +
+ struct wlr_box old_geom; +
} Client; +
+
typedef struct { +
@@ -205,6 +208,7 @@ struct Monitor { +
int nmaster; +
char ltsymbol[16]; +
int asleep; +
+ LayoutNode *root; +
}; +
+
typedef struct { +
@@ -247,6 +251,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, +
struct wlr_box *usable_area, int exclusive); +
static void arrangelayers(Monitor *m); +
static void axisnotify(struct wl_listener *listener, void *data); +
+static void btrtile(Monitor *m); +
static void buttonpress(struct wl_listener *listener, void *data); +
static void chvt(const Arg *arg); +
static void checkidleinhibitor(struct wlr_surface *exclude); +
@@ -329,6 +334,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); +
static void setpsel(struct wl_listener *listener, void *data); +
static void setsel(struct wl_listener *listener, void *data); +
static void setup(void); +
+static void setratio_h(const Arg *arg); +
+static void setratio_v(const Arg *arg); +
+static void swapclients(const Arg *arg); +
static void spawn(const Arg *arg); +
static void startdrag(struct wl_listener *listener, void *data); +
static void tag(const Arg *arg); +
@@ -454,6 +462,7 @@ static struct wlr_xwayland *xwayland; +
+
/* attempt to encapsulate suck into one file */ +
#include "client.h" +
+#include "btrtile.c" +
+
/* function implementations */ +
void +
@@ -624,7 +633,7 @@ buttonpress(struct wl_listener *listener, void *data) +
struct wlr_pointer_button_event *event = data; +
struct wlr_keyboard *keyboard; +
uint32_t mods; +
- Client *c; +
+ Client *c, *target = NULL; +
const Button *b; +
+
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); +
@@ -645,7 +654,7 @@ buttonpress(struct wl_listener *listener, void *data) +
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) { +
+ event->button == b->button && b->func) { +
b->func(&b->arg); +
return; +
} +
@@ -655,6 +664,21 @@ buttonpress(struct wl_listener *listener, void *data) +
/* If you released any buttons, we exit interactive move/resize mode. */ +
/* TODO: should reset to the pointer focus's current setcursor */ +
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { +
+ c = grabc; +
+ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) { +
+ if (cursor_mode == CurMove && c->isfloating) { +
+ target = xytoclient(cursor->x, cursor->y); +
+ +
+ if (target && !target->isfloating && !target->isfullscreen) +
+ insert_client(selmon, target, c); +
+ else +
+ selmon->root = create_client_node(c); +
+ +
+ setfloating(c, 0); +
+ apply_layout(selmon, selmon->root, selmon->w, 1); +
+ } +
+ } +
+ /* Default behaviour */ +
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); +
cursor_mode = CurNormal; +
/* Drop the window off on its new monitor */ +
@@ -746,6 +770,7 @@ cleanupmon(struct wl_listener *listener, void *data) +
wlr_output_layout_remove(output_layout, m->wlr_output); +
wlr_scene_output_destroy(m->scene_output); +
+
+ destroy_tree(m); +
closemon(m); +
wlr_scene_node_destroy(&m->fullscreen_bg->node); +
free(m); +
@@ -1090,6 +1115,7 @@ createmon(struct wl_listener *listener, void *data) +
+
wl_list_insert(&mons, &m->link); +
printstatus(); +
+ init_tree(m); +
+
/* The xdg-protocol specifies: +
* +
@@ -1329,9 +1355,17 @@ destroynotify(struct wl_listener *listener, void *data) +
{ +
/* Called when the xdg_toplevel is destroyed. */ +
Client *c = wl_container_of(listener, c, destroy); +
+ Monitor *mon; +
wl_list_remove(&c->destroy.link); +
wl_list_remove(&c->set_title.link); +
wl_list_remove(&c->fullscreen.link); +
+ /* We check if the destroyed client was part of any tiled_list, to catch +
+ * client removals even if they would not be currently managed by btrtile */ +
+ wl_list_for_each(mon, &mons, link) { +
+ if (mon->root) { +
+ remove_client(mon, c); +
+ } +
+ } +
#ifdef XWAYLAND +
if (c->type != XDGShell) { +
wl_list_remove(&c->activate.link); +
@@ -1862,7 +1896,8 @@ void +
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, +
double dx_unaccel, double dy_unaccel) +
{ +
- double sx = 0, sy = 0, sx_confined, sy_confined; +
+ int tiled = 0; +
+ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total; +
Client *c = NULL, *w = NULL; +
LayerSurface *l = NULL; +
struct wlr_surface *surface = NULL; +
@@ -1916,18 +1951,55 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d +
/* Update drag icon's position */ +
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y)); +
+
- /* If we are currently grabbing the mouse, handle and return */ +
+ /* Skip if internal call */ +
+ if (time == 0) +
+ goto focus; +
+ +
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen; +
if (cursor_mode == CurMove) { +
/* Move the grabbed client to the new position. */ +
- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy, +
- .width = grabc->geom.width, .height = grabc->geom.height}, 1); +
- return; +
+ if (grabc && grabc->isfloating) { +
+ resize(grabc, (struct wlr_box){ +
+ .x = (int)round(cursor->x) - grabcx, +
+ .y = (int)round(cursor->y) - grabcy, +
+ .width = grabc->geom.width, +
+ .height = grabc->geom.height +
+ }, 1); +
+ return; +
+ } +
} else if (cursor_mode == CurResize) { +
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y, +
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1); +
- return; +
+ if (tiled) { +
+ dx_total = cursor->x - resize_last_update_x; +
+ dy_total = cursor->y - resize_last_update_y; +
+ +
+ if (time - last_resize_time >= resize_interval_ms) { +
+ Arg a = {0}; +
+ if (fabs(dx_total) > fabs(dy_total)) { +
+ a.f = (float)(dx_total * resize_factor); +
+ setratio_h(&a); +
+ } else { +
+ a.f = (float)(dy_total * resize_factor); +
+ setratio_v(&a); +
+ } +
+ +
+ last_resize_time = time; +
+ resize_last_update_x = cursor->x; +
+ resize_last_update_y = cursor->y; +
+ } +
+ +
+ } else if (grabc && grabc->isfloating) { +
+ /* Floating resize as original */ +
+ resize(grabc, (struct wlr_box){ +
+ .x = grabc->geom.x, +
+ .y = grabc->geom.y, +
+ .width = (int)round(cursor->x) - grabc->geom.x, +
+ .height = (int)round(cursor->y) - grabc->geom.y +
+ }, 1); +
+ return; +
+ } +
} +
+
+focus: +
/* If there's no client surface under the cursor, set the cursor image to a +
* default. This is what makes the cursor image appear when you move it +
* off of a client or over its border. */ +
@@ -1961,22 +2033,40 @@ moveresize(const Arg *arg) +
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) +
return; +
+
- /* Float the window and tell motionnotify to grab it */ +
- setfloating(grabc, 1); +
- switch (cursor_mode = arg->ui) { +
- case CurMove: +
- grabcx = (int)round(cursor->x) - grabc->geom.x; +
- grabcy = (int)round(cursor->y) - grabc->geom.y; +
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "all-scroll"); +
- break; +
- case CurResize: +
- /* Doesn't work for X11 output - the next absolute motion event +
- * returns the cursor to where it started */ +
- wlr_cursor_warp_closest(cursor, NULL, +
- grabc->geom.x + grabc->geom.width, +
- grabc->geom.y + grabc->geom.height); +
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +
- break; +
+ cursor_mode = arg->ui; +
+ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen); +
+ +
+ if (grabc->was_tiled) { +
+ switch (cursor_mode) { +
+ case CurMove: +
+ setfloating(grabc, 1); +
+ grabcx = (int)round(cursor->x) - grabc->geom.x; +
+ grabcy = (int)round(cursor->y) - grabc->geom.y; +
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +
+ break; +
+ case CurResize: +
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +
+ resize_last_update_x = cursor->x; +
+ resize_last_update_y = cursor->y; +
+ break; +
+ } +
+ } else { +
+ /* Default floating logic */ +
+ /* Float the window and tell motionnotify to grab it */ +
+ setfloating(grabc, 1); +
+ switch (cursor_mode) { +
+ case CurMove: +
+ grabcx = (int)round(cursor->x) - grabc->geom.x; +
+ grabcy = (int)round(cursor->y) - grabc->geom.y; +
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +
+ break; +
+ case CurResize: +
+ wlr_cursor_warp_closest(cursor, NULL, +
+ grabc->geom.x + grabc->geom.width, +
+ grabc->geom.y + grabc->geom.height); +
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize"); +
+ break; +
+ } +
} +
} +
+
@@ -2826,6 +2916,14 @@ unmapnotify(struct wl_listener *listener, void *data) +
focusclient(focustop(selmon), 1); +
} +
} else { +
+ /* btrtile remove clients for each monitor */ +
+ Monitor *mon; +
+ wl_list_for_each(mon, &mons, link) { +
+ if (mon->root) { +
+ remove_client(mon, c); +
+ } +
+ } +
+ +
wl_list_remove(&c->link); +
setmon(c, NULL, 0); +
wl_list_remove(&c->flink); +
-- +
2.53.0 +
+
+ + + + +
+
+
+ + +
+