mirror of
				https://codeberg.org/dwl/dwl-patches.git
				synced 2025-10-27 02:04:16 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			200ff6ee53
			...
			31f3786218
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 31f3786218 | ||
|   | 4386e4295f | ||
|   | e39a7b2a5f | ||
|   | 5ba7a22893 | 
							
								
								
									
										11
									
								
								_STALE_PATCHES/tab-pango/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								_STALE_PATCHES/tab-pango/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| ### 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 | ||||
| - [git branch](https://codeberg.org/dev-gm/dwl/src/branch/tab) | ||||
| - [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
									
								
								_STALE_PATCHES/tab-pango/tab.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										461
									
								
								_STALE_PATCHES/tab-pango/tab.patch
									
									
									
									
									
										Normal 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 | ||||
| 
 | ||||
| @ -1,9 +1,25 @@ | ||||
| ### Description | ||||
| Add a tab bar or window title to the top or bottom of windows. | ||||
| Add tabs or a title bar to the top or bottom of windows. | ||||
| 
 | ||||
| Much of the code was taken from the [bar patch](/dwl/dwl-patches/src/branch/main/patches/bar).  | ||||
| 
 | ||||
| **This is the new version using `drwl`. The [old version](/dwl/dwl-patches/src/branch/main/_STALE_PATCHES/tab-pango) is deprecated.** | ||||
| 
 | ||||
| ### Dependencies | ||||
| - tllist (build dependency, required & pulled automatically by fcft) | ||||
| - fcft | ||||
| - pixman | ||||
| 
 | ||||
| ### Download | ||||
| - [git branch](https://codeberg.org/dev-gm/dwl/src/branch/tab) | ||||
| - [2024-03-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/tab/tab.patch) | ||||
| - [git branch](/dev-gm/dwl/src/branch/tab)  | ||||
| - [0.7](/dwl/dwl-patches/raw/branch/main/patches/tab/tab-0.7.patch) | ||||
| - [0.7 + bar](/dwl/dwl-patches/raw/branch/main/patches/tab/tab-0.7-bar.patch) | ||||
| - [main 2024-11-15](/dwl/dwl-patches/raw/branch/main/patches/tab/tab.patch) | ||||
| 
 | ||||
| ### Authors | ||||
| - [dev-gm](https://codeberg.org/dev-gm) | ||||
| 
 | ||||
| ### Credits | ||||
| - [sewn](https://codeberg.org/sewn) | ||||
| - [MadcowOG](https://codeberg.org/MadcowOG) | ||||
| - [kolumni](https://codeberg.org/kolumni) | ||||
|  | ||||
							
								
								
									
										768
									
								
								patches/tab/tab-0.7-bar.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										768
									
								
								patches/tab/tab-0.7-bar.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,768 @@ | ||||
| From b8c4c5656b9829e0102e8a2821e2172d3bcdaa04 Mon Sep 17 00:00:00 2001 | ||||
| From: Gavin M <git@gavinm.us> | ||||
| Date: Sat, 16 Nov 2024 08:00:35 -0500 | ||||
| Subject: [PATCH] Add tab support | ||||
| 
 | ||||
| ---
 | ||||
|  config.def.h |  25 +++- | ||||
|  dwl.c        | 393 +++++++++++++++++++++++++++++++++++++++++++++++---- | ||||
|  2 files changed, 387 insertions(+), 31 deletions(-) | ||||
| 
 | ||||
| diff --git a/config.def.h b/config.def.h
 | ||||
| index 5d1dc2b..8053e83 100644
 | ||||
| --- a/config.def.h
 | ||||
| +++ b/config.def.h
 | ||||
| @@ -10,6 +10,13 @@ static const unsigned int borderpx         = 1;  /* border pixel of windows */
 | ||||
|  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 char *tbar_fonts[]            = {"monospace:size=10"};
 | ||||
| +static const int tbar_top                  = 0;
 | ||||
| +static const int tbar_height               = -1;
 | ||||
| +static const int tbar_borderpx             = 1;
 | ||||
| +static const int tbar_padding              = 10;
 | ||||
| +static const float tbar_scale              = -1; /* -1 means use monitor scale */
 | ||||
| +static const int tbar_float_sel_sep        = 0; /* should tbar be highlighted only on the currently selected window or on both the last selected floating window and the laste selected tiling window */
 | ||||
|  static const float rootcolor[]             = COLOR(0x000000ff); | ||||
|  /* 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 */ | ||||
| @@ -20,6 +27,13 @@ static uint32_t colors[][3]                = {
 | ||||
|  	[SchemeUrg]  = { 0,          0,          0x770000ff }, | ||||
|  }; | ||||
|   | ||||
| +static uint32_t tbar_colors[][3]       = {
 | ||||
| +	/*               fg          bg          border    */
 | ||||
| +	[SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x555555ff },
 | ||||
| +	[SchemeSel]  = { 0xeeeeeeff, 0x005577ff, 0x555555ff },
 | ||||
| +	[SchemeUrg]  = { 0,          0,          0x555555ff },
 | ||||
| +};
 | ||||
| +
 | ||||
|  /* tagging - TAGCOUNT must be no greater than 31 */ | ||||
|  static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; | ||||
|   | ||||
| @@ -34,12 +48,15 @@ static const Rule rules[] = {
 | ||||
|  	{ "firefox_EXAMPLE",  NULL,       1 << 8,       0,           -1 }, /* Start on ONLY tag "9" */ | ||||
|  }; | ||||
|   | ||||
| +static const unsigned int floating_tbar_type = TBarLabel;
 | ||||
| +static const int floating_tbar_only_top = 0;
 | ||||
| +
 | ||||
|  /* layout(s) */ | ||||
|  static const Layout layouts[] = { | ||||
| -	/* symbol     arrange function */
 | ||||
| -	{ "[]=",      tile },
 | ||||
| -	{ "><>",      NULL },    /* no layout function means floating behavior */
 | ||||
| -	{ "[M]",      monocle },
 | ||||
| +	/* symbol     tbar type      tbar only on top     arrange function */
 | ||||
| +	{ "[]=",      TBarLabel,     0,                   tile },
 | ||||
| +	{ "><>",      TBarLabel,     0,                   NULL },    /* no layout function means floating behavior */
 | ||||
| +	{ "[M]",      TBarMultiple,  1,                   monocle },
 | ||||
|  }; | ||||
|   | ||||
|  /* monitors */ | ||||
| diff --git a/dwl.c b/dwl.c
 | ||||
| index 1e199f3..d99da58 100644
 | ||||
| --- a/dwl.c
 | ||||
| +++ b/dwl.c
 | ||||
| @@ -13,6 +13,7 @@
 | ||||
|  #include <time.h> | ||||
|  #include <unistd.h> | ||||
|  #include <wayland-server-core.h> | ||||
| +#include <wayland-util.h>
 | ||||
|  #include <wlr/backend.h> | ||||
|  #include <wlr/backend/libinput.h> | ||||
|  #include <wlr/render/allocator.h> | ||||
| @@ -90,6 +91,7 @@ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
 | ||||
|  enum { XDGShell, LayerShell, X11 }; /* client types */ | ||||
|  enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ | ||||
|  enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ | ||||
| +enum { TBarNone, TBarLabel, TBarMultiple, TBarAlways }; /* tbar types */
 | ||||
|  #ifdef XWAYLAND | ||||
|  enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, | ||||
|  	NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ | ||||
| @@ -110,6 +112,14 @@ typedef struct {
 | ||||
|  	const Arg arg; | ||||
|  } Button; | ||||
|   | ||||
| +typedef struct {
 | ||||
| +	struct wlr_buffer base;
 | ||||
| +	struct wl_listener release;
 | ||||
| +	bool busy;
 | ||||
| +	Img *image;
 | ||||
| +	uint32_t data[];
 | ||||
| +} Buffer;
 | ||||
| +
 | ||||
|  typedef struct Monitor Monitor; | ||||
|  typedef struct { | ||||
|  	/* Must keep these three elements in this order */ | ||||
| @@ -119,6 +129,11 @@ 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 *tbar_buffer;
 | ||||
| +	Drwl *drw;
 | ||||
| +	Buffer *pool[2];
 | ||||
| +	int tbar_height, tbar_real_height;
 | ||||
| +	float tbar_scale;
 | ||||
|  	struct wl_list link; | ||||
|  	struct wl_list flink; | ||||
|  	union { | ||||
| @@ -146,7 +161,7 @@ typedef struct {
 | ||||
|  #endif | ||||
|  	unsigned int bw; | ||||
|  	uint32_t tags; | ||||
| -	int isfloating, isurgent, isfullscreen;
 | ||||
| +	int isfloating, isurgent, isfullscreen, tbar_enabled, resize_tbar_enabled;
 | ||||
|  	uint32_t resize; /* configure serial of a pending resize */ | ||||
|  } Client; | ||||
|   | ||||
| @@ -190,17 +205,11 @@ typedef struct {
 | ||||
|   | ||||
|  typedef struct { | ||||
|  	const char *symbol; | ||||
| +	unsigned int tbar_type; /* type of tbar */
 | ||||
| +	int tbar_only_top;
 | ||||
|  	void (*arrange)(Monitor *); | ||||
|  } Layout; | ||||
|   | ||||
| -typedef struct {
 | ||||
| -	struct wlr_buffer base;
 | ||||
| -	struct wl_listener release;
 | ||||
| -	bool busy;
 | ||||
| -	Img *image;
 | ||||
| -	uint32_t data[];
 | ||||
| -} Buffer;
 | ||||
| -
 | ||||
|  struct Monitor { | ||||
|  	struct wl_list link; | ||||
|  	struct wlr_output *wlr_output; | ||||
| @@ -275,10 +284,11 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
 | ||||
|  static void arrangelayers(Monitor *m); | ||||
|  static void axisnotify(struct wl_listener *listener, void *data); | ||||
|  static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy); | ||||
| -static void bufdestroy(struct wlr_buffer *buffer);
 | ||||
| -static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags,
 | ||||
| +static Buffer *bufclient(Client *c);
 | ||||
| +static void bufdestroy(struct wlr_buffer *wlr_buffer);
 | ||||
| +static bool bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags,
 | ||||
|  		void **data, uint32_t *format, size_t *stride); | ||||
| -static void bufdataend(struct wlr_buffer *buffer);
 | ||||
| +static void bufdataend(struct wlr_buffer *wlr_buffer);
 | ||||
|  static Buffer *bufmon(Monitor *m); | ||||
|  static void bufrelease(struct wl_listener *listener, void *data); | ||||
|  static void buttonpress(struct wl_listener *listener, void *data); | ||||
| @@ -316,12 +326,15 @@ static void destroysessionlock(struct wl_listener *listener, void *data);
 | ||||
|  static void destroysessionmgr(struct wl_listener *listener, void *data); | ||||
|  static void destroykeyboardgroup(struct wl_listener *listener, void *data); | ||||
|  static Monitor *dirtomon(enum wlr_direction dir); | ||||
| +static void drawtbars(Monitor *m, int floating, int clients_changed);
 | ||||
| +static void drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout);
 | ||||
|  static void drawbar(Monitor *m); | ||||
|  static void drawbars(void); | ||||
|  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 gpureset(struct wl_listener *listener, void *data); | ||||
|  static void handlesig(int signo); | ||||
| @@ -529,14 +542,16 @@ void
 | ||||
|  arrange(Monitor *m) | ||||
|  { | ||||
|  	Client *c; | ||||
| +	int enabled;
 | ||||
|   | ||||
|  	if (!m->wlr_output->enabled) | ||||
|  		return; | ||||
|   | ||||
|  	wl_list_for_each(c, &clients, link) { | ||||
|  		if (c->mon == m) { | ||||
| -			wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
 | ||||
| -			client_set_suspended(c, !VISIBLEON(c, m));
 | ||||
| +			enabled = VISIBLEON(c, m);
 | ||||
| +			wlr_scene_node_set_enabled(&c->scene->node, enabled);
 | ||||
| +			client_set_suspended(c, !enabled);
 | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| @@ -561,6 +576,7 @@ arrange(Monitor *m)
 | ||||
|   | ||||
|  	if (m->lt[m->sellt]->arrange) | ||||
|  		m->lt[m->sellt]->arrange(m); | ||||
| +
 | ||||
|  	motionnotify(0, NULL, 0, 0, 0, 0); | ||||
|  	checkidleinhibitor(NULL); | ||||
|  } | ||||
| @@ -650,6 +666,36 @@ baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy)
 | ||||
|  	return true; | ||||
|  } | ||||
|   | ||||
| +Buffer *
 | ||||
| +bufclient(Client *c)
 | ||||
| +{
 | ||||
| +	size_t i;
 | ||||
| +	Buffer *buf = NULL;
 | ||||
| +
 | ||||
| +	for (i = 0; i < LENGTH(c->pool); i++) {
 | ||||
| +		if (c->pool[i]) {
 | ||||
| +			if (c->pool[i]->busy)
 | ||||
| +				continue;
 | ||||
| +			buf = c->pool[i];
 | ||||
| +			break;
 | ||||
| +		}
 | ||||
| +
 | ||||
| +		buf = ecalloc(1, sizeof(Buffer) + (int)(c->geom.width * c->tbar_scale * 4 * (c->tbar_height + 2*tbar_borderpx)));
 | ||||
| +		buf->image = drwl_image_create(NULL, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx, buf->data);
 | ||||
| +		wlr_buffer_init(&buf->base, &buffer_impl, (int)(c->geom.width * c->tbar_scale), c->tbar_height + 2*tbar_borderpx);
 | ||||
| +		c->pool[i] = buf;
 | ||||
| +		break;
 | ||||
| +	}
 | ||||
| +	if (!buf)
 | ||||
| +		return NULL;
 | ||||
| +
 | ||||
| +	buf->busy = true;
 | ||||
| +	LISTEN(&buf->base.events.release, &buf->release, bufrelease);
 | ||||
| +	wlr_buffer_lock(&buf->base);
 | ||||
| +	drwl_setimage(c->drw, buf->image);
 | ||||
| +	return buf;
 | ||||
| +}
 | ||||
| +
 | ||||
|  void | ||||
|  bufdestroy(struct wlr_buffer *wlr_buffer) | ||||
|  { | ||||
| @@ -827,6 +873,21 @@ checkidleinhibitor(struct wlr_surface *exclude)
 | ||||
|  void | ||||
|  cleanup(void) | ||||
|  { | ||||
| +	Client *c;
 | ||||
| +	unsigned int i;
 | ||||
| +
 | ||||
| +	wl_list_for_each(c, &clients, link) {
 | ||||
| +		if (!c->tbar_enabled)
 | ||||
| +			continue;
 | ||||
| +
 | ||||
| +		for (i = 0; i < LENGTH(c->pool); i++)
 | ||||
| +			wlr_buffer_drop(&c->pool[i]->base);
 | ||||
| +
 | ||||
| +		drwl_setimage(c->drw, NULL);
 | ||||
| +		drwl_destroy(c->drw);
 | ||||
| +
 | ||||
| +		wlr_scene_node_destroy(&c->tbar_buffer->node);
 | ||||
| +	}
 | ||||
|  #ifdef XWAYLAND | ||||
|  	wlr_xwayland_destroy(xwayland); | ||||
|  	xwayland = NULL; | ||||
| @@ -1230,6 +1291,10 @@ createnotify(struct wl_listener *listener, void *data)
 | ||||
|  	c = toplevel->base->data = ecalloc(1, sizeof(*c)); | ||||
|  	c->surface.xdg = toplevel->base; | ||||
|  	c->bw = borderpx; | ||||
| +	c->tbar_enabled = 0;
 | ||||
| +	c->resize_tbar_enabled = 0;
 | ||||
| +	c->tbar_height = 0;
 | ||||
| +	c->tbar_buffer = NULL;
 | ||||
|   | ||||
|  	LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); | ||||
|  	LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); | ||||
| @@ -1579,6 +1644,166 @@ drawbars(void)
 | ||||
|  		drawbar(m); | ||||
|  } | ||||
|   | ||||
| +void
 | ||||
| +drawtbars(Monitor *m, int floating, int clients_changed)
 | ||||
| +{
 | ||||
| +	unsigned int tbar_type, tbar_only_top, len = 0;
 | ||||
| +	int nodraw = 0, ismonocle;
 | ||||
| +	Client *c, *sel = NULL, *sel_in_layout = NULL;
 | ||||
| +
 | ||||
| +	if (!m)
 | ||||
| +		return;
 | ||||
| +
 | ||||
| +	tbar_type = floating ? floating_tbar_type : m->lt[m->sellt]->tbar_type;
 | ||||
| +	tbar_only_top = floating ? floating_tbar_only_top : m->lt[m->sellt]->tbar_only_top;
 | ||||
| +	ismonocle = m->lt[m->sellt]->arrange == monocle;
 | ||||
| +
 | ||||
| +	if (!clients_changed && !floating && ismonocle && (sel = focustop_onlytiled(m, 1))) {
 | ||||
| +		wlr_scene_node_raise_to_top(&sel->scene->node);
 | ||||
| +		if (sel->tbar_buffer)
 | ||||
| +			wlr_scene_node_raise_to_top(&sel->tbar_buffer->node);
 | ||||
| +		return;
 | ||||
| +	}
 | ||||
| +	
 | ||||
| +	if (tbar_type == TBarNone)
 | ||||
| +		nodraw = 2;
 | ||||
| +
 | ||||
| +	if (!nodraw) {
 | ||||
| +		wl_list_for_each(c, &fstack, flink) {
 | ||||
| +			if (!VISIBLEON(c, m))
 | ||||
| +				continue;
 | ||||
| +			if (!sel && (!tbar_float_sel_sep || c->isfloating == floating))
 | ||||
| +				sel = c;
 | ||||
| +			if (!sel_in_layout && c->isfloating == floating)
 | ||||
| +				sel_in_layout = c;
 | ||||
| +			if (c->isfloating == floating && !c->isfullscreen)
 | ||||
| +				len++;
 | ||||
| +		}
 | ||||
| +
 | ||||
| +		if (len == 0)
 | ||||
| +			return;
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	if (tbar_type == TBarMultiple && len <= 1)
 | ||||
| +		nodraw = 2;
 | ||||
| +
 | ||||
| +	wl_list_for_each(c, &fstack, flink) {
 | ||||
| +		if (!VISIBLEON(c, m) || c->isfloating != floating)
 | ||||
| +			continue;
 | ||||
| +		if (c->tbar_buffer && c->tbar_enabled && (nodraw == 2 || c->isfullscreen)) {
 | ||||
| +			wlr_scene_node_set_enabled(&c->tbar_buffer->node, 0);
 | ||||
| +			c->tbar_enabled = 0;
 | ||||
| +			if (m->lt[m->sellt]->arrange != tile)
 | ||||
| +				resize(c, c->geom, 0);
 | ||||
| +		}
 | ||||
| +		if (!nodraw && !c->isfullscreen) {
 | ||||
| +			drawtbar(c, tbar_type, len, ismonocle ? c : sel_in_layout, sel_in_layout);
 | ||||
| +			if (!ismonocle && tbar_only_top)
 | ||||
| +				nodraw = 1;
 | ||||
| +		}
 | ||||
| +		if (c == sel_in_layout) {
 | ||||
| +			wlr_scene_node_raise_to_top(&sel_in_layout->scene->node);
 | ||||
| +			if (sel_in_layout->tbar_buffer)
 | ||||
| +				wlr_scene_node_raise_to_top(&sel_in_layout->tbar_buffer->node);
 | ||||
| +		}
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	if (m->lt[m->sellt]->arrange == tile)
 | ||||
| +		m->lt[m->sellt]->arrange(m);
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +drawtbar(Client *c, unsigned int tbar_type, unsigned int len, Client *sel, Client *sel_in_layout)
 | ||||
| +{
 | ||||
| +	Buffer *buf;
 | ||||
| +	float width = c->geom.width * c->tbar_scale;
 | ||||
| +	unsigned int i, scheme;
 | ||||
| +	Client *l;
 | ||||
| +	uint32_t tbar_border_colors[][3] = {
 | ||||
| +		[SchemeNorm] = { [ColBg] = tbar_colors[SchemeNorm][2] },
 | ||||
| +		[SchemeSel] = { [ColBg] = tbar_colors[SchemeSel][2] },
 | ||||
| +		[SchemeUrg] = { [ColBg] = tbar_colors[SchemeUrg][2] }
 | ||||
| +	};
 | ||||
| +
 | ||||
| +	if (!c->tbar_buffer)
 | ||||
| +		c->tbar_buffer = wlr_scene_buffer_create(c->scene, NULL);
 | ||||
| +
 | ||||
| +	for (i = 0; i < LENGTH(c->pool); i++) {
 | ||||
| +		if (c->pool[i]) {
 | ||||
| +			wlr_buffer_drop(&c->pool[i]->base);
 | ||||
| +			c->pool[i] = NULL;
 | ||||
| +		}
 | ||||
| +	}
 | ||||
| +	drwl_setimage(c->drw, NULL);
 | ||||
| +
 | ||||
| +	if (!(buf = bufclient(c)))
 | ||||
| +		return;
 | ||||
| +
 | ||||
| +	switch (tbar_type) {
 | ||||
| +		case TBarLabel:
 | ||||
| +			scheme = c->isurgent ? SchemeUrg : (c == sel ? SchemeSel : SchemeNorm);
 | ||||
| +
 | ||||
| +			if (tbar_borderpx) {
 | ||||
| +				drwl_setscheme(c->drw, tbar_border_colors[scheme]);
 | ||||
| +				drwl_rect(c->drw, 0, 0, (unsigned int)width, tbar_borderpx, 1, 1);
 | ||||
| +				drwl_rect(c->drw, 0, c->tbar_height + tbar_borderpx, (unsigned int)width, tbar_borderpx, 1, 1);
 | ||||
| +				drwl_rect(c->drw, 0, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1);
 | ||||
| +				drwl_rect(c->drw, (unsigned int)width - tbar_borderpx, tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1);
 | ||||
| +			}
 | ||||
| +
 | ||||
| +			drwl_setscheme(c->drw, tbar_colors[scheme]);
 | ||||
| +			drwl_text(c->drw, tbar_borderpx, tbar_borderpx,
 | ||||
| +				(unsigned int)width - 2*tbar_borderpx, c->tbar_height,
 | ||||
| +				tbar_padding, client_get_title(c), 0);
 | ||||
| +
 | ||||
| +			break;
 | ||||
| +
 | ||||
| +		case TBarMultiple:
 | ||||
| +		case TBarAlways:
 | ||||
| +			width /= len;
 | ||||
| +			i = 0;
 | ||||
| +
 | ||||
| +			wl_list_for_each(l, &clients, link) {
 | ||||
| +				if (!VISIBLEON(l, c->mon) || l->isfullscreen || l->isfloating != c->isfloating)
 | ||||
| +					continue;
 | ||||
| +
 | ||||
| +				scheme = l->isurgent ? SchemeUrg : (l == sel ? SchemeSel : SchemeNorm);
 | ||||
| +
 | ||||
| +				if (tbar_borderpx) {
 | ||||
| +					drwl_setscheme(c->drw, tbar_border_colors[scheme]);
 | ||||
| +					drwl_rect(c->drw, (unsigned int)(width*i), 0, (unsigned int)width, tbar_borderpx, 1, 1);
 | ||||
| +					drwl_rect(c->drw, (unsigned int)(width*i), c->tbar_height + tbar_borderpx,
 | ||||
| +			   			(unsigned int)width, tbar_borderpx, 1, 1);
 | ||||
| +					drwl_rect(c->drw, (unsigned int)(width*i), tbar_borderpx, tbar_borderpx, c->tbar_height, 1, 1);
 | ||||
| +					if (i == len-1)
 | ||||
| +						drwl_rect(c->drw, (unsigned int)(width*(i+1)) - tbar_borderpx, tbar_borderpx,
 | ||||
| +							tbar_borderpx, c->tbar_height + 2*tbar_borderpx, 1, 1);
 | ||||
| +				}
 | ||||
| +
 | ||||
| +				drwl_setscheme(c->drw, tbar_colors[scheme]);
 | ||||
| +				drwl_text(c->drw, (unsigned int)(width*i) + tbar_borderpx, tbar_borderpx,
 | ||||
| +					(unsigned int)width - (i == len-1 ? 2*tbar_borderpx : tbar_borderpx),
 | ||||
| +					c->tbar_height, tbar_padding, client_get_title(l), 0);
 | ||||
| +
 | ||||
| +				i += 1;
 | ||||
| +			}
 | ||||
| +
 | ||||
| +			break;
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	c->tbar_enabled = 1;
 | ||||
| +	if (!c->resize_tbar_enabled)
 | ||||
| +		resize(c, c->geom, 0);
 | ||||
| +
 | ||||
| +	wlr_scene_buffer_set_dest_size(c->tbar_buffer, c->geom.width,
 | ||||
| +						c->tbar_real_height + 2*tbar_borderpx);
 | ||||
| +	wlr_scene_node_set_position(&c->tbar_buffer->node, 0, tbar_top ? 0
 | ||||
| +						: (c->geom.height - c->tbar_real_height - 2*tbar_borderpx));
 | ||||
| +	wlr_scene_buffer_set_buffer(c->tbar_buffer, &buf->base);
 | ||||
| +	wlr_scene_node_set_enabled(&c->tbar_buffer->node, 1);
 | ||||
| +	wlr_buffer_unlock(&buf->base);
 | ||||
| +}
 | ||||
| +
 | ||||
|  void | ||||
|  focusclient(Client *c, int lift) | ||||
|  { | ||||
| @@ -1635,6 +1860,12 @@ focusclient(Client *c, int lift)
 | ||||
|  			client_activate_surface(old, 0); | ||||
|  		} | ||||
|  	} | ||||
| +
 | ||||
| +	if (c && c->mon)
 | ||||
| +		drawtbars(c->mon, c->isfloating, 0);
 | ||||
| +	if (c && old_c && old_c->mon && (old_c->mon != c->mon || old_c->isfloating != c->isfloating))
 | ||||
| +		drawtbars(old_c->mon, old_c->isfloating, 0);
 | ||||
| +
 | ||||
|  	drawbars(); | ||||
|   | ||||
|  	if (!c) { | ||||
| @@ -1705,6 +1936,20 @@ focustop(Monitor *m)
 | ||||
|  	return NULL; | ||||
|  } | ||||
|   | ||||
| +Client *
 | ||||
| +focustop_onlytiled(Monitor *m, int onlytiled)
 | ||||
| +{
 | ||||
| +	Client *c;
 | ||||
| +	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) | ||||
|  { | ||||
| @@ -1764,6 +2009,7 @@ incnmaster(const Arg *arg)
 | ||||
|  		return; | ||||
|  	selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); | ||||
|  	arrange(selmon); | ||||
| +	drawtbars(selmon, 0, 0);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -1932,6 +2178,7 @@ mapnotify(struct wl_listener *listener, void *data)
 | ||||
|  	Client *w, *c = wl_container_of(listener, c, map); | ||||
|  	Monitor *m; | ||||
|  	int i; | ||||
| +	char fontattrs[12];
 | ||||
|   | ||||
|  	/* Create scene tree for this client and its border */ | ||||
|  	c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); | ||||
| @@ -1988,6 +2235,20 @@ unset_fullscreen:
 | ||||
|  		if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags)) | ||||
|  			setfullscreen(w, 0); | ||||
|  	} | ||||
| +
 | ||||
| +	if (!(c->drw = drwl_create()))
 | ||||
| +		die("failed to create drwl context");
 | ||||
| +	c->tbar_scale = tbar_scale > 0 ? tbar_scale : m->wlr_output->scale;
 | ||||
| +	snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale);
 | ||||
| +	if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs)))
 | ||||
| +		die("Could not load font");
 | ||||
| +	if (!c->tbar_height) {
 | ||||
| +		c->tbar_height = c->drw->font->height;
 | ||||
| +		if (tbar_height > c->tbar_height)
 | ||||
| +			c->tbar_height = tbar_height;
 | ||||
| +		c->tbar_real_height = (int)((float)c->tbar_height / c->tbar_scale);
 | ||||
| +	}
 | ||||
| +	drawtbars(c->mon, c->isfloating, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2012,18 +2273,28 @@ void
 | ||||
|  monocle(Monitor *m) | ||||
|  { | ||||
|  	Client *c; | ||||
| -	int n = 0;
 | ||||
| +	int n = 0, old_tbar_enabled;
 | ||||
|   | ||||
|  	wl_list_for_each(c, &clients, link) { | ||||
|  		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) | ||||
|  			continue; | ||||
| -		resize(c, m->w, 0);
 | ||||
| +		if (!n)
 | ||||
| +			wlr_scene_node_raise_to_top(&c->scene->node);
 | ||||
|  		n++; | ||||
| +		if (n > 1)
 | ||||
| +			break;
 | ||||
| +	}
 | ||||
| +	wl_list_for_each(c, &fstack, flink) {
 | ||||
| +		if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
 | ||||
| +			continue;
 | ||||
| +		old_tbar_enabled = c->tbar_enabled;
 | ||||
| +		c->tbar_enabled = m->lt[m->sellt]->tbar_type != TBarNone
 | ||||
| +			&& m->lt[m->sellt]->tbar_type == TBarMultiple ? n > 1 : 1;
 | ||||
| +		resize(c, m->w, 0);
 | ||||
| +		c->tbar_enabled = old_tbar_enabled;
 | ||||
|  	} | ||||
|  	if (n) | ||||
|  		snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); | ||||
| -	if ((c = focustop(m)))
 | ||||
| -		wlr_scene_node_raise_to_top(&c->scene->node);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2384,32 +2655,37 @@ resize(Client *c, struct wlr_box geo, int interact)
 | ||||
|  { | ||||
|  	struct wlr_box *bbox; | ||||
|  	struct wlr_box clip; | ||||
| +	unsigned int th;
 | ||||
|   | ||||
|  	if (!c->mon || !client_surface(c)->mapped) | ||||
|  		return; | ||||
|   | ||||
|  	bbox = interact ? &sgeom : &c->mon->w; | ||||
|   | ||||
| +	th = c->tbar_enabled ? (unsigned int)(c->tbar_real_height + 2*tbar_borderpx) : c->bw;
 | ||||
| +
 | ||||
|  	client_set_bounds(c, geo.width, geo.height); | ||||
|  	c->geom = geo; | ||||
|  	applybounds(c, bbox); | ||||
|   | ||||
|  	/* 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->scene_surface->node, c->bw, tbar_top ? th : c->bw);
 | ||||
| +	wlr_scene_rect_set_size(c->border[0], c->geom.width, (c->tbar_enabled && tbar_top) ? 0 : c->bw);
 | ||||
| +	wlr_scene_rect_set_size(c->border[1], c->geom.width, (c->tbar_enabled && !tbar_top) ? 0 : c->bw);
 | ||||
| +	wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - th - c->bw);
 | ||||
| +	wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - th - 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->border[2]->node, 0, tbar_top ? th : c->bw);
 | ||||
| +	wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, tbar_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 - th - c->bw);
 | ||||
|  	client_get_clip(c, &clip); | ||||
|  	wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); | ||||
| +
 | ||||
| +	c->resize_tbar_enabled = c->tbar_enabled;
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2505,6 +2781,8 @@ setfloating(Client *c, int floating)
 | ||||
|  			: c->isfloating ? LyrFloat : LyrTile]); | ||||
|  	arrange(c->mon); | ||||
|  	drawbars(); | ||||
| +	drawtbars(c->mon, 0, 1);
 | ||||
| +	drawtbars(c->mon, 1, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2528,6 +2806,7 @@ setfullscreen(Client *c, int fullscreen)
 | ||||
|  	} | ||||
|  	arrange(c->mon); | ||||
|  	drawbars(); | ||||
| +	drawtbars(c->mon, c->isfloating, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2553,6 +2832,7 @@ setlayout(const Arg *arg)
 | ||||
|  	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); | ||||
|  	arrange(selmon); | ||||
|  	drawbar(selmon); | ||||
| +	drawtbars(selmon, 0, 1);
 | ||||
|  } | ||||
|   | ||||
|  /* arg > 1.0 will set mfact absolutely */ | ||||
| @@ -2568,6 +2848,7 @@ setmfact(const Arg *arg)
 | ||||
|  		return; | ||||
|  	selmon->mfact = f; | ||||
|  	arrange(selmon); | ||||
| +	drawtbars(selmon, 0, 0);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2820,6 +3101,8 @@ setup(void)
 | ||||
|  	status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy), | ||||
|  		STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL); | ||||
|   | ||||
| +	drwl_init();
 | ||||
| +
 | ||||
|  	/* 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 */ | ||||
| @@ -2898,14 +3181,22 @@ tag(const Arg *arg)
 | ||||
|  	focusclient(focustop(selmon), 1); | ||||
|  	arrange(selmon); | ||||
|  	drawbars(); | ||||
| +	drawtbars(selmon, 0, 1);
 | ||||
| +	drawtbars(selmon, 1, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
|  tagmon(const Arg *arg) | ||||
|  { | ||||
|  	Client *sel = focustop(selmon); | ||||
| -	if (sel)
 | ||||
| +	Monitor *old_mon = selmon;
 | ||||
| +	if (sel) {
 | ||||
|  		setmon(sel, dirtomon(arg->i), 0); | ||||
| +		if (selmon)
 | ||||
| +			drawtbars(selmon, sel->isfloating, 1);
 | ||||
| +		if (old_mon && selmon != old_mon)
 | ||||
| +			drawtbars(old_mon, sel->isfloating, 1);
 | ||||
| +	}
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2979,6 +3270,8 @@ toggletag(const Arg *arg)
 | ||||
|  	focusclient(focustop(selmon), 1); | ||||
|  	arrange(selmon); | ||||
|  	drawbars(); | ||||
| +	drawtbars(selmon, 0, 1);
 | ||||
| +	drawtbars(selmon, 1, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -2992,6 +3285,8 @@ toggleview(const Arg *arg)
 | ||||
|  	focusclient(focustop(selmon), 1); | ||||
|  	arrange(selmon); | ||||
|  	drawbars(); | ||||
| +	drawtbars(selmon, 0, 1);
 | ||||
| +	drawtbars(selmon, 1, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -3022,6 +3317,9 @@ unmapnotify(struct wl_listener *listener, void *data)
 | ||||
|  { | ||||
|  	/* Called when the surface is unmapped, and should no longer be shown. */ | ||||
|  	Client *c = wl_container_of(listener, c, unmap); | ||||
| +	Monitor *m = c->mon;
 | ||||
| +	unsigned int i;
 | ||||
| +
 | ||||
|  	if (c == grabc) { | ||||
|  		cursor_mode = CurNormal; | ||||
|  		grabc = NULL; | ||||
| @@ -3038,6 +3336,20 @@ unmapnotify(struct wl_listener *listener, void *data)
 | ||||
|  		wl_list_remove(&c->flink); | ||||
|  	} | ||||
|   | ||||
| +	if (m && !c->isfloating && m->lt[m->sellt]->arrange == monocle)
 | ||||
| +		drawtbars(m, c->isfloating, 1);
 | ||||
| +
 | ||||
| +	if (c->tbar_enabled) {
 | ||||
| +		for (i = 0; i < LENGTH(c->pool); i++)
 | ||||
| +			if (c->pool[i])
 | ||||
| +				wlr_buffer_drop(&c->pool[i]->base);
 | ||||
| +
 | ||||
| +		drwl_setimage(c->drw, NULL);
 | ||||
| +		drwl_destroy(c->drw);
 | ||||
| +
 | ||||
| +		wlr_scene_node_destroy(&c->tbar_buffer->node);
 | ||||
| +	}
 | ||||
| +
 | ||||
|  	wlr_scene_node_destroy(&c->scene->node); | ||||
|  	drawbars(); | ||||
|  	motionnotify(0, NULL, 0, 0, 0, 0); | ||||
| @@ -3058,9 +3370,12 @@ updatemons(struct wl_listener *listener, void *data)
 | ||||
|  	Client *c; | ||||
|  	struct wlr_output_configuration_head_v1 *config_head; | ||||
|  	Monitor *m; | ||||
| +	char fontattrs[12];
 | ||||
|   | ||||
|  	/* First remove from the layout the disabled monitors */ | ||||
|  	wl_list_for_each(m, &mons, link) { | ||||
| +		if (m->asleep)
 | ||||
| +			continue;
 | ||||
|  		if (m->wlr_output->enabled || m->asleep) | ||||
|  			continue; | ||||
|  		config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output); | ||||
| @@ -3124,6 +3439,23 @@ updatemons(struct wl_listener *listener, void *data)
 | ||||
|  		if (!selmon) { | ||||
|  			selmon = m; | ||||
|  		} | ||||
| +
 | ||||
| +		wl_list_for_each(c, &clients, link) {
 | ||||
| +			if (!VISIBLEON(c, m) || (c->drw && (tbar_scale > 0 || c->tbar_scale == m->wlr_output->scale)))
 | ||||
| +				continue;
 | ||||
| +			if (!c->drw && !(c->drw = drwl_create()))
 | ||||
| +				die("failed to create drwl context");
 | ||||
| +			drwl_font_destroy(c->drw->font);
 | ||||
| +			c->tbar_scale = m->wlr_output->scale;
 | ||||
| +			snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * c->tbar_scale);
 | ||||
| +			if (!(drwl_font_create(c->drw, LENGTH(tbar_fonts), tbar_fonts, fontattrs)))
 | ||||
| +				die("Could not load font");
 | ||||
| +			if (!c->tbar_height) {
 | ||||
| +				c->tbar_height = c->drw->font->height;
 | ||||
| +				if (tbar_height > c->tbar_height)
 | ||||
| +					c->tbar_height = tbar_height;
 | ||||
| +			}
 | ||||
| +		}
 | ||||
|  	} | ||||
|   | ||||
|  	if (selmon && selmon->wlr_output->enabled) { | ||||
| @@ -3195,6 +3527,7 @@ updatetitle(struct wl_listener *listener, void *data)
 | ||||
|  	Client *c = wl_container_of(listener, c, set_title); | ||||
|  	if (c == focustop(c->mon)) | ||||
|  		drawbars(); | ||||
| +	drawtbars(c->mon, c->isfloating, 1);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -3322,8 +3655,10 @@ zoom(const Arg *arg)
 | ||||
|  	wl_list_remove(&sel->link); | ||||
|  	wl_list_insert(&clients, &sel->link); | ||||
|   | ||||
| +	drawtbars(selmon, 0, 1);
 | ||||
|  	focusclient(sel, 1); | ||||
|  	arrange(selmon); | ||||
| +	drawtbars(selmon, 0, 0);
 | ||||
|  } | ||||
|   | ||||
|  #ifdef XWAYLAND | ||||
| @@ -3375,6 +3710,10 @@ createnotifyx11(struct wl_listener *listener, void *data)
 | ||||
|  	c->surface.xwayland = xsurface; | ||||
|  	c->type = X11; | ||||
|  	c->bw = client_is_unmanaged(c) ? 0 : borderpx; | ||||
| +	c->tbar_enabled = 0;
 | ||||
| +	c->resize_tbar_enabled = 0;
 | ||||
| +	c->tbar_height = 0;
 | ||||
| +	c->tbar_buffer = NULL;
 | ||||
|   | ||||
|  	/* Listen to the various events it can emit */ | ||||
|  	LISTEN(&xsurface->events.associate, &c->associate, associatex11); | ||||
| -- 
 | ||||
| 2.47.0 | ||||
| 
 | ||||
							
								
								
									
										1249
									
								
								patches/tab/tab-0.7.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1249
									
								
								patches/tab/tab-0.7.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user