diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-08-11 18:57:38 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-08-11 18:57:38 +0300 |
commit | e7ebe190d266649371ac901bdc4b152f64ec7f85 (patch) | |
tree | 57c47d4cb35207c63f24e90147d6bc2dd7ee38b9 | |
parent | 620143fb42cbc10f6ca2de50b7efdb37bcf4f37b (diff) | |
download | ebuild-repository-e7ebe190d266649371ac901bdc4b152f64ec7f85.tar.gz |
add patches to profile
20 files changed, 2663 insertions, 0 deletions
diff --git a/profiles/eug-vs/patches/x11-libs/libXft/bgra.patch b/profiles/eug-vs/patches/x11-libs/libXft/bgra.patch new file mode 100644 index 0000000..5c594cc --- /dev/null +++ b/profiles/eug-vs/patches/x11-libs/libXft/bgra.patch @@ -0,0 +1,861 @@ +From 723092ece088559f1af299236305911f4ee4d450 Mon Sep 17 00:00:00 2001 +From: Maxime Coste <mawww@kakoune.org> +Date: Thu, 28 Jan 2021 19:59:10 +1100 +Subject: [PATCH 1/3] Introduce a _XftCompositeString helper function + +Dispatch to XRenderCompositeString{8,16,32} based off the given width. + +Signed-off-by: Maxime Coste <mawww@kakoune.org> +--- + src/xftrender.c | 61 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 18 deletions(-) + +diff --git a/src/xftrender.c b/src/xftrender.c +index a352737..181c27a 100644 +--- a/src/xftrender.c ++++ b/src/xftrender.c +@@ -25,6 +25,47 @@ + #define NUM_LOCAL 1024 + #define NUM_ELT_LOCAL 128 + ++/* ++ * Dispatch glyph drawing to the correct XRenderCompositeString function ++ */ ++static void ++_XftCompositeString (Display *dpy, ++ int op, ++ Picture src, ++ Picture dst, ++ XRenderPictFormat *format, ++ GlyphSet glyphset, ++ int srcx, ++ int srcy, ++ int dstx, ++ int dsty, ++ int charwidth, ++ unsigned int *chars, ++ int nchars) ++{ ++ if (nchars == 0) ++ return; ++ ++ switch (charwidth) { ++ case 1: ++ default: ++ XRenderCompositeString8 (dpy, op, ++ src, dst, format, glyphset, ++ srcx, srcy, dstx, dsty, (char*)chars, nchars); ++ break; ++ case 2: ++ XRenderCompositeString16(dpy, op, ++ src, dst, format, glyphset, ++ srcx, srcy, dstx, dsty, (unsigned short*)chars, nchars); ++ break; ++ case 4: ++ XRenderCompositeString32(dpy, op, ++ src, dst, format, glyphset, ++ srcx, srcy, dstx, dsty, (unsigned int*)chars, nchars); ++ break; ++ } ++} ++ + /* + * Use the Render extension to draw the glyphs + */ +@@ -114,24 +155,8 @@ XftGlyphRender (Display *dpy, + case 4: char32[i] = (unsigned int) wire; break; + } + } +- switch (width) { +- case 1: +- default: +- XRenderCompositeString8 (dpy, op, +- src, dst, font->format, font->glyphset, +- srcx, srcy, x, y, char8, nglyphs); +- break; +- case 2: +- XRenderCompositeString16(dpy, op, +- src, dst, font->format, font->glyphset, +- srcx, srcy, x, y, char16, nglyphs); +- break; +- case 4: +- XRenderCompositeString32(dpy, op, +- src, dst, font->format, font->glyphset, +- srcx, srcy, x, y, char32, nglyphs); +- break; +- } ++ _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, ++ srcx, srcy, x, y, width, chars, nglyphs); + if (chars != char_local) + free (chars); + bail1: +-- +GitLab + + +From e0fc4ce7e87ab9c4b47e5c8e693f070dfd0d2f7b Mon Sep 17 00:00:00 2001 +From: Maxime Coste <mawww@kakoune.org> +Date: Thu, 28 Jan 2021 20:05:13 +1100 +Subject: [PATCH 2/3] Introduce a _XftCompositeText helper function + +Dispatch to XRenderCompositeText{8,16,32} based off the given width. + +Signed-off-by: Maxime Coste <mawww@kakoune.org> +--- + src/xftrender.c | 83 +++++++++++++++++++++++++++++-------------------- + 1 file changed, 49 insertions(+), 34 deletions(-) + +diff --git a/src/xftrender.c b/src/xftrender.c +index 181c27a..5852b2e 100644 +--- a/src/xftrender.c ++++ b/src/xftrender.c +@@ -164,6 +164,49 @@ bail1: + _XftFontManageMemory (dpy, pub); + } + ++/* ++ * Dispatch glyph drawing to the correct XRenderCompositeText function ++ */ ++static void ++_XftCompositeText (Display *dpy, ++ int op, ++ Picture src, ++ Picture dst, ++ XRenderPictFormat *format, ++ int srcx, ++ int srcy, ++ int dstx, ++ int dsty, ++ int eltwidth, ++ XGlyphElt8 *elts, ++ int nelt) ++{ ++ if (nelt == 0) ++ return; ++ ++ switch (eltwidth) { ++ case 1: ++ default: ++ XRenderCompositeText8 (dpy, op, ++ src, dst, format, ++ srcx, srcy, dstx, dsty, ++ (XGlyphElt8*)elts, nelt); ++ break; ++ case 2: ++ XRenderCompositeText16(dpy, op, ++ src, dst, format, ++ srcx, srcy, dstx, dsty, ++ (XGlyphElt16*)elts, nelt); ++ break; ++ case 4: ++ XRenderCompositeText32(dpy, op, ++ src, dst, format, ++ srcx, srcy, dstx, dsty, ++ (XGlyphElt32*)elts, nelt); ++ break; ++ } ++} ++ + _X_EXPORT void + XftGlyphSpecRender (Display *dpy, + int op, +@@ -345,23 +388,9 @@ XftGlyphSpecRender (Display *dpy, + elts[nelt].nchars = n; + nelt++; + } +- switch (width) { +- case 1: +- XRenderCompositeText8 (dpy, op, src, dst, font->format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- elts, nelt); +- break; +- case 2: +- XRenderCompositeText16 (dpy, op, src, dst, font->format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- (XGlyphElt16 *) elts, nelt); +- break; +- case 4: +- XRenderCompositeText32 (dpy, op, src, dst, font->format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- (XGlyphElt32 *) elts, nelt); +- break; +- } ++ _XftCompositeText(dpy, op, src, dst, font->format, ++ srcx, srcy, glyphs[0].x, glyphs[0].y, ++ width, elts, nelt); + + if (elts != elts_local) + free (elts); +@@ -635,23 +664,9 @@ XftGlyphFontSpecRender (Display *dpy, + elts[nelt].nchars = n; + nelt++; + } +- switch (width) { +- case 1: +- XRenderCompositeText8 (dpy, op, src, dst, format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- elts, nelt); +- break; +- case 2: +- XRenderCompositeText16 (dpy, op, src, dst, format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- (XGlyphElt16 *) elts, nelt); +- break; +- case 4: +- XRenderCompositeText32 (dpy, op, src, dst, format, +- srcx, srcy, glyphs[0].x, glyphs[0].y, +- (XGlyphElt32 *) elts, nelt); +- break; +- } ++ _XftCompositeText(dpy, op, src, dst, format, ++ srcx, srcy, glyphs[0].x, glyphs[0].y, ++ width, elts, nelt); + + if (elts != elts_local) + free (elts); +-- +GitLab + + +From d385aa3e5320d18918413df0e8aef3a713a47e0b Mon Sep 17 00:00:00 2001 +From: Maxime Coste <mawww@kakoune.org> +Date: Tue, 22 Oct 2019 22:46:49 +1100 +Subject: [PATCH 3/3] Add support for BGRA glyphs display and scaling + +Display is done using an XRender Picture, as XRender +glyphs are incompatible with BGRA rendering due to +their use of the glyph bitmap as a mask. + +Scaling is done by averaging all relevant pixel, which gives +much better result than nearest pixel sampling while staying +simple enough and not too computationally expensive. + +This enables color emoji rendering support. + +Fixes: #6 + +Signed-off-by: Maxime Coste <mawww@kakoune.org> +--- + src/xftfreetype.c | 18 +++- + src/xftglyphs.c | 234 +++++++++++++++++++++++++++++++++++++++++++--- + src/xftint.h | 2 + + src/xftrender.c | 69 +++++++++++--- + 4 files changed, 293 insertions(+), 30 deletions(-) + +diff --git a/src/xftfreetype.c b/src/xftfreetype.c +index 1f79a81..4325d65 100644 +--- a/src/xftfreetype.c ++++ b/src/xftfreetype.c +@@ -523,7 +523,7 @@ XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, XftFontInfo *fi) + /* + * Compute glyph load flags + */ +- fi->load_flags = FT_LOAD_DEFAULT; ++ fi->load_flags = FT_LOAD_DEFAULT | FT_LOAD_COLOR; + + #ifndef XFT_EMBEDDED_BITMAP + #define XFT_EMBEDDED_BITMAP "embeddedbitmap" +@@ -775,6 +775,7 @@ XftFontOpenInfo (Display *dpy, + FcChar32 hash_value; + FcChar32 rehash_value; + FcBool antialias; ++ FcBool color; + int max_glyph_memory; + int alloc_size; + int ascent, descent, height; +@@ -831,12 +832,18 @@ XftFontOpenInfo (Display *dpy, + if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) + antialias = FcFalse; + ++ color = FT_HAS_COLOR(face) ? FcTrue : FcFalse; ++ + /* + * Find the appropriate picture format + */ + if (fi->render) + { +- if (antialias) ++ if (color) ++ { ++ format = XRenderFindStandardFormat (dpy, PictStandardARGB32); ++ } ++ else if (antialias) + { + switch (fi->rgba) { + case FC_RGBA_RGB: +@@ -968,6 +975,13 @@ XftFontOpenInfo (Display *dpy, + * which doesn't happen in XftFontInfoFill + */ + font->info.antialias = antialias; ++ ++ /* ++ * Set color value, which is only known once the ++ * font was loaded ++ */ ++ font->info.color = color; ++ + /* + * bump XftFile reference count + */ +diff --git a/src/xftglyphs.c b/src/xftglyphs.c +index b536df4..e0bad10 100644 +--- a/src/xftglyphs.c ++++ b/src/xftglyphs.c +@@ -26,6 +26,8 @@ + + #include FT_SYNTHESIS_H + ++#include FT_GLYPH_H ++ + /* + * Validate the memory info for a font + */ +@@ -78,9 +80,11 @@ _XftFontValidateMemory (Display *dpy, XftFont *public) + static int + _compute_xrender_bitmap_size( FT_Bitmap* target, + FT_GlyphSlot slot, +- FT_Render_Mode mode ) ++ FT_Render_Mode mode, ++ FT_Matrix* matrix ) + { + FT_Bitmap* ftbit; ++ FT_Vector vector; + int width, height, pitch; + + if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) +@@ -91,6 +95,16 @@ _compute_xrender_bitmap_size( FT_Bitmap* target, + + width = (int)ftbit->width; + height = (int)ftbit->rows; ++ ++ if ( matrix && mode == FT_RENDER_MODE_NORMAL ) ++ { ++ vector.x = ftbit->width; ++ vector.y = ftbit->rows; ++ FT_Vector_Transform(&vector, matrix); ++ ++ width = (int)vector.x; ++ height = (int)vector.y; ++ } + pitch = (width+3) & ~3; + + switch ( ftbit->pixel_mode ) +@@ -112,6 +126,10 @@ _compute_xrender_bitmap_size( FT_Bitmap* target, + } + break; + ++ case FT_PIXEL_MODE_BGRA: ++ pitch = width * 4; ++ break; ++ + case FT_PIXEL_MODE_LCD: + if ( mode != FT_RENDER_MODE_LCD ) + return -1; +@@ -142,6 +160,105 @@ _compute_xrender_bitmap_size( FT_Bitmap* target, + return pitch * height; + } + ++/* this functions converts the glyph bitmap found in a FT_GlyphSlot ++ * into a different format while scaling by applying the given matrix ++ * (see _compute_xrender_bitmap_size) ++ * ++ * you should call this function after _compute_xrender_bitmap_size ++ * ++ * target :: target bitmap descriptor. Note that its 'buffer' pointer ++ * must point to memory allocated by the caller ++ * ++ * source :: the source bitmap descriptor ++ * ++ * matrix :: the scaling matrix to apply ++ */ ++static void ++_scaled_fill_xrender_bitmap( FT_Bitmap* target, ++ FT_Bitmap* source, ++ const FT_Matrix* matrix ) ++{ ++ unsigned char* src_buf = source->buffer; ++ unsigned char* dst_line = target->buffer; ++ int src_pitch = source->pitch; ++ int width = target->width; ++ int height = target->rows; ++ int pitch = target->pitch; ++ int h; ++ FT_Vector vector; ++ FT_Matrix inverse = *matrix; ++ int sampling_width; ++ int sampling_height; ++ int sample_count; ++ ++ if ( src_pitch < 0 ) ++ src_buf -= src_pitch * (source->rows - 1); ++ ++ FT_Matrix_Invert(&inverse); ++ ++ /* compute how many source pixels a target pixel spans */ ++ vector.x = 1; ++ vector.y = 1; ++ FT_Vector_Transform(&vector, &inverse); ++ sampling_width = vector.x / 2; ++ sampling_height = vector.y / 2; ++ sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1); ++ ++ for ( h = height; h > 0; h--, dst_line += pitch ) ++ { ++ int x; ++ ++ for ( x = 0; x < width; x++ ) ++ { ++ unsigned char* src; ++ ++#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) ++ ++ /* compute target pixel location in source space */ ++ vector.x = (x * 0x10000) + 0x10000 / 2; ++ vector.y = ((height - h) * 0x10000) + 0x10000 / 2; ++ FT_Vector_Transform(&vector, &inverse); ++ vector.x = CLAMP(FT_RoundFix(vector.x) / 0x10000, 0, source->width - 1); ++ vector.y = CLAMP(FT_RoundFix(vector.y) / 0x10000, 0, source->rows - 1); ++ ++ switch ( source->pixel_mode ) ++ { ++ case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */ ++ src = src_buf + (vector.y * src_pitch); ++ if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) ) ++ dst_line[x] = 0xff; ++ break; ++ ++ case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */ ++ src = src_buf + (vector.y * src_pitch); ++ dst_line[x] = src[vector.x]; ++ break; ++ ++ case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */ ++ { ++ int sample_x, sample_y; ++ int bgra[4] = {}; ++ for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y) ++ { ++ int src_y = CLAMP(vector.y + sample_y, 0, source->rows - 1); ++ src = src_buf + (src_y * src_pitch); ++ for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x) ++ { ++ int src_x = CLAMP(vector.x + sample_x, 0, source->width - 1); ++ for (int i = 0; i < 4; ++i) ++ bgra[i] += src[src_x * 4 + i]; ++ } ++ } ++ ++ for (int i = 0; i < 4; ++i) ++ dst_line[4 * x + i] = bgra[i] / sample_count; ++ break; ++ } ++ } ++ } ++ } ++} ++ + /* this functions converts the glyph bitmap found in a FT_GlyphSlot + * into a different format (see _compute_xrender_bitmap_size) + * +@@ -244,6 +361,11 @@ _fill_xrender_bitmap( FT_Bitmap* target, + } + break; + ++ case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */ ++ for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) ++ memcpy( dstLine, srcLine, width * 4 ); ++ break; ++ + case FT_PIXEL_MODE_LCD: + if ( !bgr ) + { +@@ -339,6 +461,55 @@ _fill_xrender_bitmap( FT_Bitmap* target, + } + } + ++/* This function creates a Picture for the given glyph on the default root window ++ * It will only work in Xinerama mode ++ * ++ * dpy :: target display ++ * ++ * format :: target pixmap format ++ * ++ * width :: picture width ++ * ++ * width :: picture height ++ * ++ * data :: bitmap data ++ * ++ */ ++static Picture ++_create_glyph_bgra_picture (Display *dpy, ++ XRenderPictFormat *format, ++ int width, ++ int height, ++ unsigned char *data) ++{ ++ XImage image = { ++ width, height, 0, ZPixmap, (char *)data, ++ dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32, ++ 32, 0, 32, ++ 0, 0, 0 ++ }; ++ Picture picture; ++ Pixmap pixmap; ++ GC gc; ++ ++ pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 32); ++ if (!pixmap) ++ return None; ++ ++ gc = XCreateGC(dpy, pixmap, 0, NULL); ++ if (!gc) ++ return None; ++ ++ XInitImage(&image); ++ XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, width, height); ++ picture = XRenderCreatePicture(dpy, pixmap, format, 0, NULL); ++ ++ XFreeGC(dpy, gc); ++ XFreePixmap(dpy, pixmap); ++ ++ return picture; ++} ++ + _X_EXPORT void + XftFontLoadGlyphs (Display *dpy, + XftFont *pub, +@@ -365,6 +536,8 @@ XftFontLoadGlyphs (Display *dpy, + FT_Vector vector; + FT_Face face; + FT_Render_Mode mode = FT_RENDER_MODE_MONO; ++ FcBool transform; ++ FcBool glyph_transform; + + if (!info) + return; +@@ -374,6 +547,8 @@ XftFontLoadGlyphs (Display *dpy, + if (!face) + return; + ++ if (font->info.color) ++ mode = FT_RENDER_MODE_NORMAL; + if (font->info.antialias) + { + switch (font->info.rgba) { +@@ -390,6 +565,8 @@ XftFontLoadGlyphs (Display *dpy, + } + } + ++ transform = font->info.transform && mode != FT_RENDER_MODE_MONO; ++ + while (nglyph--) + { + glyphindex = *glyphs++; +@@ -440,7 +617,7 @@ XftFontLoadGlyphs (Display *dpy, + /* + * Compute glyph metrics from FreeType information + */ +- if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP) ++ if (transform) + { + /* + * calculate the true width by transforming all four corners. +@@ -487,7 +664,7 @@ XftFontLoadGlyphs (Display *dpy, + * Clip charcell glyphs to the bounding box + * XXX transformed? + */ +- if (font->info.spacing >= FC_CHARCELL && !font->info.transform) ++ if (font->info.spacing >= FC_CHARCELL && !transform) + { + if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) + { +@@ -519,18 +696,20 @@ XftFontLoadGlyphs (Display *dpy, + } + } + ++ glyph_transform = transform; + if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP ) + { + error = FT_Render_Glyph( face->glyph, mode ); + if (error) + continue; ++ glyph_transform = False; + } + + FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE ); + + if (font->info.spacing >= FC_MONO) + { +- if (font->info.transform) ++ if (transform) + { + if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) + { +@@ -613,14 +792,27 @@ XftFontLoadGlyphs (Display *dpy, + } + } + +- size = _compute_xrender_bitmap_size( &local, glyphslot, mode ); ++ size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL ); + if ( size < 0 ) + continue; + + xftg->metrics.width = (unsigned short)local.width; + xftg->metrics.height = (unsigned short)local.rows; +- xftg->metrics.x = (short)(- glyphslot->bitmap_left); +- xftg->metrics.y = (short)( glyphslot->bitmap_top); ++ if (transform) ++ { ++ vector.x = - glyphslot->bitmap_left; ++ vector.y = glyphslot->bitmap_top; ++ ++ FT_Vector_Transform(&vector, &font->info.matrix); ++ ++ xftg->metrics.x = (short)vector.x; ++ xftg->metrics.y = (short)vector.y; ++ } ++ else ++ { ++ xftg->metrics.x = (short)(- glyphslot->bitmap_left); ++ xftg->metrics.y = (short)( glyphslot->bitmap_top); ++ } + + /* + * If the glyph is relatively large (> 1% of server memory), +@@ -645,9 +837,12 @@ XftFontLoadGlyphs (Display *dpy, + + local.buffer = bufBitmap; + +- _fill_xrender_bitmap( &local, glyphslot, mode, +- (font->info.rgba == FC_RGBA_BGR || +- font->info.rgba == FC_RGBA_VBGR ) ); ++ if (mode == FT_RENDER_MODE_NORMAL && glyph_transform) ++ _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, &font->info.matrix); ++ else ++ _fill_xrender_bitmap( &local, glyphslot, mode, ++ (font->info.rgba == FC_RGBA_BGR || ++ font->info.rgba == FC_RGBA_VBGR ) ); + + /* + * Copy or convert into local buffer. +@@ -662,6 +857,7 @@ XftFontLoadGlyphs (Display *dpy, + */ + glyph = (Glyph) glyphindex; + ++ xftg->picture = 0; + xftg->glyph_memory = (size_t)size + sizeof (XftGlyph); + if (font->format) + { +@@ -685,15 +881,21 @@ XftFontLoadGlyphs (Display *dpy, + } + } + } +- else if ( mode != FT_RENDER_MODE_NORMAL ) ++ else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL) + { + /* invert ARGB <=> BGRA */ + if (ImageByteOrder (dpy) != XftNativeByteOrder ()) + XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2); + } +- XRenderAddGlyphs (dpy, font->glyphset, &glyph, +- &xftg->metrics, 1, +- (char *) bufBitmap, size); ++ ++ if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) ++ xftg->picture = _create_glyph_bgra_picture(dpy, font->format, ++ local.width, local.rows, ++ bufBitmap); ++ else ++ XRenderAddGlyphs (dpy, font->glyphset, &glyph, ++ &xftg->metrics, 1, ++ (char *) bufBitmap, size); + } + else + { +@@ -744,7 +946,9 @@ XftFontUnloadGlyphs (Display *dpy, + { + if (font->format) + { +- if (font->glyphset) ++ if (xftg->picture) ++ XRenderFreePicture(dpy, xftg->picture); ++ else if (font->glyphset) + { + glyphBuf[nused++] = (Glyph) glyphindex; + if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0])) +diff --git a/src/xftint.h b/src/xftint.h +index ced9a02..1af40fe 100644 +--- a/src/xftint.h ++++ b/src/xftint.h +@@ -85,6 +85,7 @@ typedef struct _XftGlyph { + XGlyphInfo metrics; + void *bitmap; + unsigned long glyph_memory; ++ Picture picture; + } XftGlyph; + + /* +@@ -134,6 +135,7 @@ struct _XftFontInfo { + FT_F26Dot6 xsize, ysize; /* pixel size */ + FcBool antialias; /* doing antialiasing */ + FcBool embolden; /* force emboldening */ ++ FcBool color; /* contains color glyphs */ + int rgba; /* subpixel order */ + int lcd_filter; /* lcd filter */ + FT_Matrix matrix; /* glyph transformation matrix */ +diff --git a/src/xftrender.c b/src/xftrender.c +index 5852b2e..bd001be 100644 +--- a/src/xftrender.c ++++ b/src/xftrender.c +@@ -84,12 +84,14 @@ XftGlyphRender (Display *dpy, + int nglyphs) + { + XftFontInt *font = (XftFontInt *) pub; +- int i; ++ int i, j; + FT_UInt missing[XFT_NMISSING]; + int nmissing; + FT_UInt g, max; + int size, width; ++ int dstx, dsty; + Glyph wire; ++ XftGlyph* glyph; + char *char8; + unsigned short *char16; + unsigned int *char32; +@@ -141,22 +143,46 @@ XftGlyphRender (Display *dpy, + if (!chars) + goto bail1; + } ++ dstx = x; ++ dsty = y; + char8 = (char *) chars; + char16 = (unsigned short *) chars; + char32 = (unsigned int *) chars; +- for (i = 0; i < nglyphs; i++) ++ for (i = 0, j = 0; i < nglyphs; i++) + { + wire = (Glyph) glyphs[i]; + if (wire >= font->num_glyphs || !font->glyphs[wire]) + wire = 0; +- switch (width) { +- case 1: char8[i] = (char) wire; break; +- case 2: char16[i] = (unsigned short) wire; break; +- case 4: char32[i] = (unsigned int) wire; break; ++ glyph = font->glyphs[wire]; ++ if (glyph->picture) ++ { ++ _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, ++ srcx, srcy, x, y, width, chars, j); ++ XRenderComposite(dpy, PictOpOver, glyph->picture, None, ++ dst, 0, 0, 0, 0, dstx, dsty - glyph->metrics.y, ++ glyph->metrics.width, glyph->metrics.height); ++ ++ dstx += glyph->metrics.xOff; ++ dsty += glyph->metrics.yOff; ++ ++ x = dstx; ++ y = dsty; ++ j = 0; ++ } ++ else ++ { ++ switch (width) { ++ case 1: char8[j] = (char) wire; break; ++ case 2: char16[j] = (unsigned short) wire; break; ++ case 4: char32[j] = (unsigned int) wire; break; ++ } ++ dstx += glyph->metrics.xOff; ++ dsty += glyph->metrics.yOff; ++ ++j; + } + } + _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, +- srcx, srcy, x, y, width, chars, nglyphs); ++ srcx, srcy, x, y, width, chars, j); + if (chars != char_local) + free (chars); + bail1: +@@ -319,9 +345,10 @@ XftGlyphSpecRender (Display *dpy, + g = 0; + /* + * check to see if the glyph is placed where it would +- * fall using the normal spacing ++ * fall using the normal spacing and if it would render ++ * as a XRender glyph + */ +- if ((glyph = font->glyphs[g])) ++ if ((glyph = font->glyphs[g]) && !glyph->picture) + { + if (x != glyphs[i].x || y != glyphs[i].y) + { +@@ -335,7 +362,7 @@ XftGlyphSpecRender (Display *dpy, + } + + elts = elts_local; +- if (nelt > NUM_ELT_LOCAL) ++ if (!font->info.color && nelt > NUM_ELT_LOCAL) + { + elts = malloc ((size_t)nelt * sizeof (XGlyphElt8)); + if (!elts) +@@ -343,7 +370,7 @@ XftGlyphSpecRender (Display *dpy, + } + + /* +- * Generate the list of glyph elts ++ * Generate the list of glyph elts or render color glyphs + */ + nelt = 0; + x = y = 0; +@@ -357,6 +384,14 @@ XftGlyphSpecRender (Display *dpy, + g = 0; + if ((glyph = font->glyphs[g])) + { ++ if (glyph->picture) ++ { ++ XRenderComposite(dpy, PictOpOver, glyph->picture, None, ++ dst, 0, 0, 0, 0, ++ glyphs[i].x, glyphs[i].y - glyph->metrics.y, ++ glyph->metrics.width, glyph->metrics.height); ++ continue; ++ } + if (!i || x != glyphs[i].x || y != glyphs[i].y) + { + if (n) +@@ -589,7 +624,7 @@ XftGlyphFontSpecRender (Display *dpy, + * check to see if the glyph is placed where it would + * fall using the normal spacing + */ +- if ((glyph = font->glyphs[g])) ++ if ((glyph = font->glyphs[g]) && !glyph->picture) + { + if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y) + { +@@ -614,7 +649,7 @@ XftGlyphFontSpecRender (Display *dpy, + } + + /* +- * Generate the list of glyph elts ++ * Generate the list of glyph elts and render color glyphs + */ + nelt = 0; + x = y = 0; +@@ -632,6 +667,14 @@ XftGlyphFontSpecRender (Display *dpy, + g = 0; + if ((glyph = font->glyphs[g])) + { ++ if (glyph->picture) ++ { ++ XRenderComposite(dpy, PictOpOver, glyph->picture, None, ++ dst, 0, 0, 0, 0, ++ glyphs[i].x, glyphs[i].y - glyph->metrics.y, ++ glyph->metrics.width, glyph->metrics.height); ++ continue; ++ } + if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y) + { + if (n) +-- +GitLab + diff --git a/profiles/eug-vs/patches/x11-misc/dmenu/0001-chore-remove-config.h-on-clean.patch b/profiles/eug-vs/patches/x11-misc/dmenu/0001-chore-remove-config.h-on-clean.patch new file mode 100644 index 0000000..c0a2a76 --- /dev/null +++ b/profiles/eug-vs/patches/x11-misc/dmenu/0001-chore-remove-config.h-on-clean.patch @@ -0,0 +1,25 @@ +From 4005d1054e2df8919e3e2a76ecda61fb4dda43e0 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Wed, 19 Jan 2022 00:38:19 +0300 +Subject: [PATCH 1/4] chore: remove config.h on clean + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index a03a95c..fe864c3 100644 +--- a/Makefile ++++ b/Makefile +@@ -29,7 +29,7 @@ stest: stest.o + $(CC) -o $@ stest.o $(LDFLAGS) + + clean: +- rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz ++ rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz config.h + + dist: clean + mkdir -p dmenu-$(VERSION) +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-misc/dmenu/0002-feat-use-Fira-Code-and-gruvbox-cyan.patch b/profiles/eug-vs/patches/x11-misc/dmenu/0002-feat-use-Fira-Code-and-gruvbox-cyan.patch new file mode 100644 index 0000000..b8179c8 --- /dev/null +++ b/profiles/eug-vs/patches/x11-misc/dmenu/0002-feat-use-Fira-Code-and-gruvbox-cyan.patch @@ -0,0 +1,33 @@ +From b3d2fb0ce001a3fe69bd469613073672f8c935b6 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Wed, 19 Jan 2022 00:38:44 +0300 +Subject: [PATCH 2/4] feat: use Fira Code and gruvbox cyan + +--- + config.def.h | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1edb647..fe9f5f0 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,14 +3,12 @@ + + static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ + /* -fn option overrides fonts[0]; default X11 font or font set */ +-static const char *fonts[] = { +- "monospace:size=10" +-}; ++static const char *fonts[] = { "fira code nerd font:pixelsize=12:antialias=true:autohint=true" }; + static const char *prompt = NULL; /* -p option; prompt to the left of input field */ + static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, +- [SchemeSel] = { "#eeeeee", "#005577" }, ++ [SchemeSel] = { "#eeeeee", "#689d6a" }, + [SchemeOut] = { "#000000", "#00ffff" }, + }; + /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-misc/dmenu/0003-feat-use-gray-background.patch b/profiles/eug-vs/patches/x11-misc/dmenu/0003-feat-use-gray-background.patch new file mode 100644 index 0000000..7d3ce7a --- /dev/null +++ b/profiles/eug-vs/patches/x11-misc/dmenu/0003-feat-use-gray-background.patch @@ -0,0 +1,25 @@ +From da5301964aba42e48e15fb7c95614f2fd7e8fed3 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Sat, 16 Apr 2022 15:57:50 +0300 +Subject: [PATCH 3/4] feat: use gray background + +--- + config.def.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index fe9f5f0..c93f056 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -8,7 +8,7 @@ static const char *prompt = NULL; /* -p option; prompt to the left of + static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, +- [SchemeSel] = { "#eeeeee", "#689d6a" }, ++ [SchemeSel] = { "#eeeeee", "#928374" }, + [SchemeOut] = { "#000000", "#00ffff" }, + }; + /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-misc/dmenu/0004-feat-use-classic-background.patch b/profiles/eug-vs/patches/x11-misc/dmenu/0004-feat-use-classic-background.patch new file mode 100644 index 0000000..59a5918 --- /dev/null +++ b/profiles/eug-vs/patches/x11-misc/dmenu/0004-feat-use-classic-background.patch @@ -0,0 +1,25 @@ +From 76039705e8a053cea0ba927a81053cf4fae37a24 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Mon, 18 Apr 2022 21:28:35 +0300 +Subject: [PATCH 4/4] feat!: use classic background + +--- + config.def.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index c93f056..eb8dc64 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -8,7 +8,7 @@ static const char *prompt = NULL; /* -p option; prompt to the left of + static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, +- [SchemeSel] = { "#eeeeee", "#928374" }, ++ [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, + }; + /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0001-feat-change-MOD-to-SUPER.patch b/profiles/eug-vs/patches/x11-wm/dwm/0001-feat-change-MOD-to-SUPER.patch new file mode 100644 index 0000000..7d5b27e --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0001-feat-change-MOD-to-SUPER.patch @@ -0,0 +1,29 @@ +From d458f4d04c1acabeccbcf076f75ecc9ac0e7b89b Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Sat, 27 Mar 2021 14:08:46 +0300 +Subject: [PATCH 01/15] feat: change MOD to SUPER + +--- + config.def.h => config.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + rename config.def.h => config.h (99%) + +diff --git a/config.def.h b/config.h +similarity index 99% +rename from config.def.h +rename to config.h +index a2ac963..7c1d880 100644 +--- a/config.def.h ++++ b/config.h +@@ -45,7 +45,7 @@ static const Layout layouts[] = { + }; + + /* key definitions */ +-#define MODKEY Mod1Mask ++#define MODKEY Mod4Mask + #define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0002-feat-remove-config.h-on-clean-install.patch b/profiles/eug-vs/patches/x11-wm/dwm/0002-feat-remove-config.h-on-clean-install.patch new file mode 100644 index 0000000..908b403 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0002-feat-remove-config.h-on-clean-install.patch @@ -0,0 +1,25 @@ +From 3428deb37ae13d50ebcfc28120a29357a638bc37 Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Sat, 27 Mar 2021 14:23:26 +0300 +Subject: [PATCH 02/15] feat: remove config.h on clean install + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 77bcbc0..c05dbdd 100644 +--- a/Makefile ++++ b/Makefile +@@ -26,7 +26,7 @@ dwm: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + + clean: +- rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz ++ rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz config.h + + dist: clean + mkdir -p dwm-${VERSION} +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0003-feat-only-use-config.def.h.patch b/profiles/eug-vs/patches/x11-wm/dwm/0003-feat-only-use-config.def.h.patch new file mode 100644 index 0000000..49dc81b --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0003-feat-only-use-config.def.h.patch @@ -0,0 +1,38 @@ +From 3d3a54f278bf5c22b3ead64039b50d1ad187e9f6 Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Sat, 27 Mar 2021 14:23:55 +0300 +Subject: [PATCH 03/15] feat: only use config.def.h + +--- + config.h => config.def.h | 4 ++++ + 1 file changed, 4 insertions(+) + rename config.h => config.def.h (95%) + +diff --git a/config.h b/config.def.h +similarity index 95% +rename from config.h +rename to config.def.h +index 7c1d880..c3e0dbc 100644 +--- a/config.h ++++ b/config.def.h +@@ -2,6 +2,7 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappx = 5; /* gaps between windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +@@ -85,6 +86,9 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_minus, setgaps, {.i = -1 } }, ++ { MODKEY, XK_equal, setgaps, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0004-feat-bind-exit-to-E-and-kill-client-to-Q.patch b/profiles/eug-vs/patches/x11-wm/dwm/0004-feat-bind-exit-to-E-and-kill-client-to-Q.patch new file mode 100644 index 0000000..af9f866 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0004-feat-bind-exit-to-E-and-kill-client-to-Q.patch @@ -0,0 +1,34 @@ +From cb19e80b91882242475a0d48e0faf0eb44f898f3 Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Sat, 27 Mar 2021 16:06:46 +0300 +Subject: [PATCH 04/15] feat: bind exit to E and kill-client to Q + +--- + config.def.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index c3e0dbc..d89961f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -74,7 +74,7 @@ static Key keys[] = { + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, +- { MODKEY|ShiftMask, XK_c, killclient, {0} }, ++ { MODKEY|ShiftMask, XK_q, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, +@@ -98,7 +98,7 @@ static Key keys[] = { + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ShiftMask, XK_e, quit, {0} }, + }; + + /* button definitions */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0005-feat-apply-swallow-patch.patch b/profiles/eug-vs/patches/x11-wm/dwm/0005-feat-apply-swallow-patch.patch new file mode 100644 index 0000000..a950cb5 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0005-feat-apply-swallow-patch.patch @@ -0,0 +1,377 @@ +From ea694dbab24d8628f57821fb07d13e6f93571f6c Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Sat, 27 Mar 2021 21:40:35 +0300 +Subject: [PATCH 05/15] feat: apply swallow patch + +--- + config.mk | 2 +- + dwm.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 190 insertions(+), 9 deletions(-) + +diff --git a/config.mk b/config.mk +index b6eb7e0..2960227 100644 +--- a/config.mk ++++ b/config.mk +@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index a96f33c..1c2dd11 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,8 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <X11/Xlib-xcb.h> ++#include <xcb/res.h> + + #include "drw.h" + #include "util.h" +@@ -92,9 +94,11 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; ++ pid_t pid; + Client *next; + Client *snext; ++ Client *swallowing; + Monitor *mon; + Window win; + }; +@@ -138,6 +142,8 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ int isterminal; ++ int noswallow; + int monitor; + } Rule; + +@@ -169,6 +175,7 @@ static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static pid_t getparentprocess(pid_t p); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); + static long getstate(Window w); +@@ -176,6 +183,7 @@ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); + static void grabbuttons(Client *c, int focused); + static void grabkeys(void); + static void incnmaster(const Arg *arg); ++static int isdescprocess(pid_t p, pid_t c); + static void keypress(XEvent *e); + static void killclient(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); +@@ -207,8 +215,10 @@ static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static Client *swallowingclient(Window w); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static Client *termforwin(const Client *c); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); +@@ -228,6 +238,7 @@ static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); ++static pid_t winpid(Window w); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); +@@ -269,6 +280,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static xcb_connection_t *xcon; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -298,6 +311,7 @@ applyrules(Client *c) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { ++ c->isterminal = r->isterminal; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); +@@ -414,6 +428,47 @@ attachstack(Client *c) + c->mon->stack = c; + } + ++void ++swallow(Client *p, Client *c) ++{ ++ if (c->noswallow || c->isterminal) ++ return; ++ ++ detach(c); ++ detachstack(c); ++ ++ setclientstate(c, WithdrawnState); ++ XUnmapWindow(dpy, p->win); ++ ++ p->swallowing = c; ++ c->mon = p->mon; ++ ++ Window w = p->win; ++ p->win = c->win; ++ c->win = w; ++ updatetitle(p); ++ arrange(p->mon); ++ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); ++ configure(p); ++ updateclientlist(); ++} ++ ++void ++unswallow(Client *c) ++{ ++ c->win = c->swallowing->win; ++ ++ free(c->swallowing); ++ c->swallowing = NULL; ++ ++ updatetitle(c); ++ arrange(c->mon); ++ XMapWindow(dpy, c->win); ++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); ++ configure(c); ++ setclientstate(c, NormalState); ++} ++ + void + buttonpress(XEvent *e) + { +@@ -479,7 +534,7 @@ cleanup(void) + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) +- unmanage(m->stack, 0); ++ unmanage(m->stack, 0); // XXX - unmanage swallowing windows too + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); +@@ -653,6 +708,9 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ ++ else if ((c = swallowingclient(ev->window))) ++ unmanage(c->swallowing, 1); + } + + void +@@ -1021,12 +1079,13 @@ killclient(const Arg *arg) + void + manage(Window w, XWindowAttributes *wa) + { +- Client *c, *t = NULL; ++ Client *c, *t = NULL, *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; ++ c->pid = winpid(w); + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; +@@ -1041,6 +1100,7 @@ manage(Window w, XWindowAttributes *wa) + } else { + c->mon = selmon; + applyrules(c); ++ term = termforwin(c); + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) +@@ -1077,6 +1137,8 @@ manage(Window w, XWindowAttributes *wa) + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); ++ if (term) ++ swallow(term, c); + focus(NULL); + } + +@@ -1771,6 +1833,20 @@ unmanage(Client *c, int destroyed) + Monitor *m = c->mon; + XWindowChanges wc; + ++ if (c->swallowing) { ++ unswallow(c); ++ return; ++ } ++ ++ Client *s = swallowingclient(c->win); ++ if (s) { ++ free(s->swallowing); ++ s->swallowing = NULL; ++ arrange(m); ++ focus(NULL); ++ return; ++ } ++ + detach(c); + detachstack(c); + if (!destroyed) { +@@ -1785,9 +1861,12 @@ unmanage(Client *c, int destroyed) + XUngrabServer(dpy); + } + free(c); +- focus(NULL); +- updateclientlist(); +- arrange(m); ++ ++ if (!s) { ++ arrange(m); ++ focus(NULL); ++ updateclientlist(); ++ } + } + + void +@@ -2050,16 +2129,116 @@ view(const Arg *arg) + arrange(selmon); + } + ++pid_t ++winpid(Window w) ++{ ++ pid_t result = 0; ++ ++ xcb_res_client_id_spec_t spec = {0}; ++ spec.client = w; ++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; ++ ++ xcb_generic_error_t *e = NULL; ++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); ++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); ++ ++ if (!r) ++ return (pid_t)0; ++ ++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); ++ for (; i.rem; xcb_res_client_id_value_next(&i)) { ++ spec = i.data->spec; ++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { ++ uint32_t *t = xcb_res_client_id_value_value(i.data); ++ result = *t; ++ break; ++ } ++ } ++ ++ free(r); ++ ++ if (result == (pid_t)-1) ++ result = 0; ++ return result; ++} ++ ++pid_t ++getparentprocess(pid_t p) ++{ ++ unsigned int v = 0; ++ ++#ifdef __linux__ ++ FILE *f; ++ char buf[256]; ++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); ++ ++ if (!(f = fopen(buf, "r"))) ++ return 0; ++ ++ fscanf(f, "%*u %*s %*c %u", &v); ++ fclose(f); ++#endif /* __linux__ */ ++ ++ return (pid_t)v; ++} ++ ++int ++isdescprocess(pid_t p, pid_t c) ++{ ++ while (p != c && c != 0) ++ c = getparentprocess(c); ++ ++ return (int)c; ++} ++ ++Client * ++termforwin(const Client *w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ if (!w->pid || w->isterminal) ++ return NULL; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ ++Client * ++swallowingclient(Window w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->swallowing && c->swallowing->win == w) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ ++ + Client * + wintoclient(Window w) + { + Client *c; + Monitor *m; + +- for (m = mons; m; m = m->next) +- for (c = m->clients; c; c = c->next) ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { + if (c->win == w) + return c; ++ } ++ } + return NULL; + } + +@@ -2141,6 +2320,8 @@ main(int argc, char *argv[]) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); ++ if (!(xcon = XGetXCBConnection(dpy))) ++ die("dwm: cannot get xcb connection\n"); + checkotherwm(); + setup(); + #ifdef __OpenBSD__ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0006-feat-swap-h-l-and-behavior.patch b/profiles/eug-vs/patches/x11-wm/dwm/0006-feat-swap-h-l-and-behavior.patch new file mode 100644 index 0000000..df1917b --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0006-feat-swap-h-l-and-behavior.patch @@ -0,0 +1,42 @@ +From 8ac957c1f697fe1972e86b25f1db7051a1287ebd Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Tue, 30 Mar 2021 10:30:55 +0300 +Subject: [PATCH 06/15] feat: swap h/l and >/< behavior + +--- + config.def.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index d89961f..a04a85c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -70,8 +70,8 @@ static Key keys[] = { + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, +- { MODKEY, XK_h, setmfact, {.f = -0.05} }, +- { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY, XK_comma, setmfact, {.f = -0.05} }, ++ { MODKEY, XK_period, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_q, killclient, {0} }, +@@ -82,10 +82,10 @@ static Key keys[] = { + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, +- { MODKEY, XK_comma, focusmon, {.i = -1 } }, +- { MODKEY, XK_period, focusmon, {.i = +1 } }, +- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, +- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_h, focusmon, {.i = -1 } }, ++ { MODKEY, XK_l, focusmon, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_h, tagmon, {.i = -1 } }, ++ { MODKEY|ShiftMask, XK_l, tagmon, {.i = +1 } }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0007-feat-resize-on-MOD-r.patch b/profiles/eug-vs/patches/x11-wm/dwm/0007-feat-resize-on-MOD-r.patch new file mode 100644 index 0000000..7c29d10 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0007-feat-resize-on-MOD-r.patch @@ -0,0 +1,24 @@ +From c9cfcb6519b6f731bc0d3b77075eef7a81c9120a Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Thu, 15 Apr 2021 13:58:54 +0300 +Subject: [PATCH 07/15] feat: resize on MOD+r + +--- + config.def.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/config.def.h b/config.def.h +index a04a85c..b8d9510 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -86,6 +86,7 @@ static Key keys[] = { + { MODKEY, XK_l, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_h, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_l, tagmon, {.i = +1 } }, ++ { MODKEY, XK_r, resizemouse, {0} }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0008-feat-use-Fira-Code.patch b/profiles/eug-vs/patches/x11-wm/dwm/0008-feat-use-Fira-Code.patch new file mode 100644 index 0000000..6f18046 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0008-feat-use-Fira-Code.patch @@ -0,0 +1,83 @@ +From 11a83b5b8fb54a2d8decc454c15d198f18ef0022 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Tue, 18 Jan 2022 23:56:01 +0300 +Subject: [PATCH 08/15] feat: use Fira Code + +--- + config.def.h | 23 ++++++++--------------- + dwm.c | 2 +- + 2 files changed, 9 insertions(+), 16 deletions(-) + +diff --git a/config.def.h b/config.def.h +index b8d9510..a5914c1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,21 +2,18 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const unsigned int gappx = 5; /* gaps between windows */ + static const unsigned int snap = 32; /* snap pixel */ + 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 dmenufont[] = "monospace:size=10"; +-static const char col_gray1[] = "#222222"; +-static const char col_gray2[] = "#444444"; +-static const char col_gray3[] = "#bbbbbb"; +-static const char col_gray4[] = "#eeeeee"; +-static const char col_cyan[] = "#005577"; ++static const char *fonts[] = { "fira code nerd font:pixelsize=12:antialias=true:autohint=true" }; ++static const char col_background[] = "#1d2021"; ++static const char col_foreground[] = "#ebdbb2"; ++static const char col_primary[] = "#689d6a"; + static const char *colors[][3] = { + /* fg bg border */ +- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, +- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, ++ [SchemeNorm] = { col_foreground, col_background, "#000000" }, ++ [SchemeSel] = { col_foreground, col_primary, col_primary }, ++ [SchemeStatus] = { col_foreground, col_background, "#000000" }, + }; + + /* tagging */ +@@ -58,7 +55,7 @@ static const Layout layouts[] = { + + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; ++static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, NULL }; + static const char *termcmd[] = { "st", NULL }; + + static Key keys[] = { +@@ -87,9 +84,6 @@ static Key keys[] = { + { MODKEY|ShiftMask, XK_h, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_l, tagmon, {.i = +1 } }, + { MODKEY, XK_r, resizemouse, {0} }, +- { MODKEY, XK_minus, setgaps, {.i = -1 } }, +- { MODKEY, XK_equal, setgaps, {.i = +1 } }, +- { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +@@ -118,4 +112,3 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; +- +diff --git a/dwm.c b/dwm.c +index 1c2dd11..70d6fd9 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -61,7 +61,7 @@ + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +-enum { SchemeNorm, SchemeSel }; /* color schemes */ ++enum { SchemeNorm, SchemeSel, SchemeStatus }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0009-feat-apply-attachaside-patch.patch b/profiles/eug-vs/patches/x11-wm/dwm/0009-feat-apply-attachaside-patch.patch new file mode 100644 index 0000000..dcd1d89 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0009-feat-apply-attachaside-patch.patch @@ -0,0 +1,105 @@ +From c0c1de752e7b1daacbca4c580f1fa8661c50a09b Mon Sep 17 00:00:00 2001 +From: eug-vs <eug-vs@keemail.me> +Date: Fri, 23 Jul 2021 14:29:16 +0300 +Subject: [PATCH 09/15] feat: apply attachaside patch + +Source: https://dwm.suckless.org/patches/attachaside/ +--- + dwm.c | 32 ++++++++++++++++++++++++++++---- + 1 file changed, 28 insertions(+), 4 deletions(-) + +diff --git a/dwm.c b/dwm.c +index 70d6fd9..2d5a64d 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -51,7 +51,8 @@ + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) + #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) ++#define ISVISIBLEONTAG(C, T) ((C->tags & T)) ++#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) +@@ -153,6 +154,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac + static void arrange(Monitor *m); + static void arrangemon(Monitor *m); + static void attach(Client *c); ++static void attachaside(Client *c); + static void attachstack(Client *c); + static void buttonpress(XEvent *e); + static void checkotherwm(void); +@@ -192,6 +194,7 @@ static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); ++static Client *nexttagged(Client *c); + static Client *nexttiled(Client *c); + static void pop(Client *); + static void propertynotify(XEvent *e); +@@ -421,6 +424,17 @@ attach(Client *c) + c->mon->clients = c; + } + ++void ++attachaside(Client *c) { ++ Client *at = nexttagged(c); ++ if(!at) { ++ attach(c); ++ return; ++ } ++ c->next = at->next; ++ at->next = c; ++} ++ + void + attachstack(Client *c) + { +@@ -1126,7 +1140,7 @@ manage(Window w, XWindowAttributes *wa) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); +- attach(c); ++ attachaside(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +@@ -1258,6 +1272,16 @@ movemouse(const Arg *arg) + } + } + ++Client * ++nexttagged(Client *c) { ++ Client *walked = c->mon->clients; ++ for(; ++ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); ++ walked = walked->next ++ ); ++ return walked; ++} ++ + Client * + nexttiled(Client *c) + { +@@ -1483,7 +1507,7 @@ sendmon(Client *c, Monitor *m) + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ +- attach(c); ++ attachaside(c); + attachstack(c); + focus(NULL); + arrange(NULL); +@@ -1982,7 +2006,7 @@ updategeom(void) + m->clients = c->next; + detachstack(c); + c->mon = mons; +- attach(c); ++ attachaside(c); + attachstack(c); + } + if (m == selmon) +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0010-feat-change-master-width-to-75.patch b/profiles/eug-vs/patches/x11-wm/dwm/0010-feat-change-master-width-to-75.patch new file mode 100644 index 0000000..f396534 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0010-feat-change-master-width-to-75.patch @@ -0,0 +1,25 @@ +From 71cc9e0fcfd02a665d0859888d2ab3e81d2bda2c Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Wed, 19 Jan 2022 00:29:04 +0300 +Subject: [PATCH 10/15] feat: change master width to 75% + +--- + config.def.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index a5914c1..dc10d22 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -30,7 +30,7 @@ static const Rule rules[] = { + }; + + /* layout(s) */ +-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ ++static const float mfact = 0.75; /* factor of master area size [0.05..0.95] */ + static const int nmaster = 1; /* number of clients in master area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0011-patch-actual-fullscreen.patch b/profiles/eug-vs/patches/x11-wm/dwm/0011-patch-actual-fullscreen.patch new file mode 100644 index 0000000..2508f5a --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0011-patch-actual-fullscreen.patch @@ -0,0 +1,66 @@ +From 4745e69489042e1b33f278809e1f9e831d6704b1 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Thu, 20 Jan 2022 01:27:31 +0300 +Subject: [PATCH 11/15] patch: actual fullscreen + +--- + config.def.h | 1 + + dwm.1 | 3 +++ + dwm.c | 8 ++++++++ + 3 files changed, 12 insertions(+) + +diff --git a/config.def.h b/config.def.h +index dc10d22..b7d6205 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -75,6 +75,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ShiftMask, XK_m, togglefullscr, {0} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.1 b/dwm.1 +index ddc8321..3d310ac 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only). + .B Mod1\-Shift\-c + Close focused window. + .TP ++.B Mod1\-Shift\-f ++Toggle fullscreen for focused window. ++.TP + .B Mod1\-Shift\-space + Toggle focused window between tiled and floating state. + .TP +diff --git a/dwm.c b/dwm.c +index 2d5a64d..ea4fa50 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -225,6 +225,7 @@ static Client *termforwin(const Client *c); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglefullscr(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -1811,6 +1812,13 @@ togglefloating(const Arg *arg) + arrange(selmon); + } + ++void ++togglefullscr(const Arg *arg) ++{ ++ if(selmon->sel) ++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0012-patch-systray.patch b/profiles/eug-vs/patches/x11-wm/dwm/0012-patch-systray.patch new file mode 100644 index 0000000..04ecbf3 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0012-patch-systray.patch @@ -0,0 +1,749 @@ +From c5298ee42bbf9dbec0b8d9dc2f57b1f260ea2b45 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Thu, 20 Jan 2022 01:39:50 +0300 +Subject: [PATCH 12/15] patch: systray + +--- + config.def.h | 5 + + dwm.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 386 insertions(+), 26 deletions(-) + +diff --git a/config.def.h b/config.def.h +index b7d6205..2d2af1a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,11 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ ++static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ ++static const unsigned int systrayspacing = 2; /* systray spacing */ ++static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ ++static const int showsystray = 1; /* 0 means no systray */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "fira code nerd font:pixelsize=12:antialias=true:autohint=true" }; +diff --git a/dwm.c b/dwm.c +index ea4fa50..83362ce 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -60,12 +60,30 @@ + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + ++#define SYSTEM_TRAY_REQUEST_DOCK 0 ++ ++/* XEMBED messages */ ++#define XEMBED_EMBEDDED_NOTIFY 0 ++#define XEMBED_WINDOW_ACTIVATE 1 ++#define XEMBED_FOCUS_IN 4 ++#define XEMBED_MODALITY_ON 10 ++ ++#define XEMBED_MAPPED (1 << 0) ++#define XEMBED_WINDOW_ACTIVATE 1 ++#define XEMBED_WINDOW_DEACTIVATE 2 ++ ++#define VERSION_MAJOR 0 ++#define VERSION_MINOR 0 ++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR ++ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel, SchemeStatus }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, ++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ ++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ +@@ -148,6 +166,12 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct Systray Systray; ++struct Systray { ++ Window win; ++ Client *icons; ++}; ++ + /* function declarations */ + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +@@ -181,6 +205,7 @@ static pid_t getparentprocess(pid_t p); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); + static long getstate(Window w); ++static unsigned int getsystraywidth(); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); + static void grabbuttons(Client *c, int focused); + static void grabkeys(void); +@@ -200,13 +225,16 @@ static void pop(Client *); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); ++static void removesystrayicon(Client *i); + static void resize(Client *c, int x, int y, int w, int h, int interact); ++static void resizebarwin(Monitor *m); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); ++static void resizerequest(XEvent *e); + static void restack(Monitor *m); + static void run(void); + static void scan(void); +-static int sendevent(Client *c, Atom proto); ++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); +@@ -218,6 +246,8 @@ static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static Monitor *systraytomon(Monitor *m); ++static void mappingnotify(XEvent *e); + static Client *swallowingclient(Window w); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -238,6 +268,9 @@ static int updategeom(void); + static void updatenumlockmask(void); + static void updatesizehints(Client *c); + static void updatestatus(void); ++static void updatesystray(void); ++static void updatesystrayicongeom(Client *i, int w, int h); ++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); + static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); +@@ -245,12 +278,14 @@ static void view(const Arg *arg); + static pid_t winpid(Window w); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static Client *wintosystrayicon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + + /* variables */ ++static Systray *systray = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -273,9 +308,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, ++ [ResizeRequest] = resizerequest, + [UnmapNotify] = unmapnotify + }; +-static Atom wmatom[WMLast], netatom[NetLast]; ++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; + static int running = 1; + static Cur *cursor[CurLast]; + static Clr **scheme; +@@ -510,7 +546,7 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth()) + click = ClkStatusText; + else + click = ClkWinTitle; +@@ -553,6 +589,11 @@ cleanup(void) + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); ++ if (showsystray) { ++ XUnmapWindow(dpy, systray->win); ++ XDestroyWindow(dpy, systray->win); ++ free(systray); ++ } + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) +@@ -583,9 +624,57 @@ cleanupmon(Monitor *mon) + void + clientmessage(XEvent *e) + { ++ XWindowAttributes wa; ++ XSetWindowAttributes swa; + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + ++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { ++ /* add systray icons */ ++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { ++ if (!(c = (Client *)calloc(1, sizeof(Client)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); ++ if (!(c->win = cme->data.l[2])) { ++ free(c); ++ return; ++ } ++ c->mon = selmon; ++ c->next = systray->icons; ++ systray->icons = c; ++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { ++ /* use sane defaults */ ++ wa.width = bh; ++ wa.height = bh; ++ wa.border_width = 0; ++ } ++ c->x = c->oldx = c->y = c->oldy = 0; ++ c->w = c->oldw = wa.width; ++ c->h = c->oldh = wa.height; ++ c->oldbw = wa.border_width; ++ c->bw = 0; ++ c->isfloating = True; ++ /* reuse tags field as mapped status */ ++ c->tags = 1; ++ updatesizehints(c); ++ updatesystrayicongeom(c, wa.width, wa.height); ++ XAddToSaveSet(dpy, c->win); ++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); ++ XReparentWindow(dpy, c->win, systray->win, 0, 0); ++ /* use parents background color */ ++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ /* FIXME not sure if I have to send these events, too */ ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ XSync(dpy, False); ++ resizebarwin(selmon); ++ updatesystray(); ++ setclientstate(c, NormalState); ++ } ++ return; ++ } + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { +@@ -638,7 +727,7 @@ configurenotify(XEvent *e) + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); +- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); ++ resizebarwin(m); + } + focus(NULL); + arrange(NULL); +@@ -723,6 +812,11 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ else if ((c = wintosystrayicon(ev->window))) { ++ removesystrayicon(c); ++ resizebarwin(selmon); ++ updatesystray(); ++ } + + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); +@@ -769,22 +863,26 @@ dirtomon(int dir) + void + drawbar(Monitor *m) + { +- int x, w, tw = 0; ++ int x, w, tw = 0, stw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + ++ if(showsystray && m == systraytomon(m) && !systrayonleft) ++ stw = getsystraywidth(); ++ + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); +- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */ ++ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0); + } + ++ resizebarwin(m); + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) +@@ -805,7 +903,7 @@ drawbar(Monitor *m) + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + +- if ((w = m->ww - tw - x) > bh) { ++ if ((w = m->ww - tw - stw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +@@ -816,7 +914,7 @@ drawbar(Monitor *m) + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } +- drw_map(drw, m->barwin, 0, 0, m->ww, bh); ++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); + } + + void +@@ -853,8 +951,11 @@ expose(XEvent *e) + Monitor *m; + XExposeEvent *ev = &e->xexpose; + +- if (ev->count == 0 && (m = wintomon(ev->window))) ++ if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); ++ if (m == selmon) ++ updatesystray(); ++ } + } + + void +@@ -939,10 +1040,17 @@ getatomprop(Client *c, Atom prop) + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; ++ /* FIXME getatomprop should return the number of items and a pointer to ++ * the stored data instead of this workaround */ ++ Atom req = XA_ATOM; ++ if (prop == xatom[XembedInfo]) ++ req = xatom[XembedInfo]; + +- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, ++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; ++ if (da == xatom[XembedInfo] && dl == 2) ++ atom = ((Atom *)p)[1]; + XFree(p); + } + return atom; +@@ -976,6 +1084,16 @@ getstate(Window w) + return result; + } + ++unsigned int ++getsystraywidth() ++{ ++ unsigned int w = 0; ++ Client *i; ++ if(showsystray) ++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; ++ return w ? w + systrayspacing : 1; ++} ++ + int + gettextprop(Window w, Atom atom, char *text, unsigned int size) + { +@@ -1080,7 +1198,7 @@ killclient(const Arg *arg) + { + if (!selmon->sel) + return; +- if (!sendevent(selmon->sel, wmatom[WMDelete])) { ++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); +@@ -1172,6 +1290,12 @@ maprequest(XEvent *e) + { + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; ++ Client *i; ++ if ((i = wintosystrayicon(ev->window))) { ++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); ++ resizebarwin(selmon); ++ updatesystray(); ++ } + + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; +@@ -1306,6 +1430,16 @@ propertynotify(XEvent *e) + Window trans; + XPropertyEvent *ev = &e->xproperty; + ++ if ((c = wintosystrayicon(ev->window))) { ++ if (ev->atom == XA_WM_NORMAL_HINTS) { ++ updatesizehints(c); ++ updatesystrayicongeom(c, c->w, c->h); ++ } ++ else ++ updatesystrayiconstate(c, ev); ++ resizebarwin(selmon); ++ updatesystray(); ++ } + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) +@@ -1356,6 +1490,20 @@ recttomon(int x, int y, int w, int h) + return r; + } + ++void ++removesystrayicon(Client *i) ++{ ++ Client **ii; ++ ++ if (!showsystray || !i) ++ return; ++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); ++ if (ii) ++ *ii = i->next; ++ free(i); ++} ++ ++ + void + resize(Client *c, int x, int y, int w, int h, int interact) + { +@@ -1363,6 +1511,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) + resizeclient(c, x, y, w, h); + } + ++void ++resizebarwin(Monitor *m) { ++ unsigned int w = m->ww; ++ if (showsystray && m == systraytomon(m) && !systrayonleft) ++ w -= getsystraywidth(); ++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); ++} ++ + void + resizeclient(Client *c, int x, int y, int w, int h) + { +@@ -1435,6 +1591,19 @@ resizemouse(const Arg *arg) + } + } + ++void ++resizerequest(XEvent *e) ++{ ++ XResizeRequestEvent *ev = &e->xresizerequest; ++ Client *i; ++ ++ if ((i = wintosystrayicon(ev->window))) { ++ updatesystrayicongeom(i, ev->width, ev->height); ++ resizebarwin(selmon); ++ updatesystray(); ++ } ++} ++ + void + restack(Monitor *m) + { +@@ -1524,26 +1693,36 @@ setclientstate(Client *c, long state) + } + + int +-sendevent(Client *c, Atom proto) ++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) + { + int n; +- Atom *protocols; ++ Atom *protocols, mt; + int exists = 0; + XEvent ev; + +- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { +- while (!exists && n--) +- exists = protocols[n] == proto; +- XFree(protocols); ++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { ++ mt = wmatom[WMProtocols]; ++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { ++ while (!exists && n--) ++ exists = protocols[n] == proto; ++ XFree(protocols); ++ } ++ } ++ else { ++ exists = True; ++ mt = proto; + } + if (exists) { + ev.type = ClientMessage; +- ev.xclient.window = c->win; +- ev.xclient.message_type = wmatom[WMProtocols]; ++ ev.xclient.window = w; ++ ev.xclient.message_type = mt; + ev.xclient.format = 32; +- ev.xclient.data.l[0] = proto; +- ev.xclient.data.l[1] = CurrentTime; +- XSendEvent(dpy, c->win, False, NoEventMask, &ev); ++ ev.xclient.data.l[0] = d0; ++ ev.xclient.data.l[1] = d1; ++ ev.xclient.data.l[2] = d2; ++ ev.xclient.data.l[3] = d3; ++ ev.xclient.data.l[4] = d4; ++ XSendEvent(dpy, w, False, mask, &ev); + } + return exists; + } +@@ -1557,7 +1736,7 @@ setfocus(Client *c) + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } +- sendevent(c, wmatom[WMTakeFocus]); ++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); + } + + void +@@ -1646,6 +1825,10 @@ setup(void) + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); ++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); ++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); ++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); ++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); +@@ -1653,6 +1836,9 @@ setup(void) + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); ++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); ++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); ++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); +@@ -1661,6 +1847,8 @@ setup(void) + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); ++ /* init system tray */ ++ updatesystray(); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1794,7 +1982,18 @@ togglebar(const Arg *arg) + { + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); +- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); ++ resizebarwin(selmon); ++ if (showsystray) { ++ XWindowChanges wc; ++ if (!selmon->showbar) ++ wc.y = -bh; ++ else if (selmon->showbar) { ++ wc.y = 0; ++ if (!selmon->topbar) ++ wc.y = selmon->mh - bh; ++ } ++ XConfigureWindow(dpy, systray->win, CWY, &wc); ++ } + arrange(selmon); + } + +@@ -1913,11 +2112,18 @@ unmapnotify(XEvent *e) + else + unmanage(c, 0); + } ++ else if ((c = wintosystrayicon(ev->window))) { ++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do ++ * _not_ destroy them. We map those windows back */ ++ XMapRaised(dpy, c->win); ++ updatesystray(); ++ } + } + + void + updatebars(void) + { ++ unsigned int w; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, +@@ -1928,10 +2134,15 @@ updatebars(void) + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; +- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), ++ w = m->ww; ++ if (showsystray && m == systraytomon(m)) ++ w -= getsystraywidth(); ++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); ++ if (showsystray && m == systraytomon(m)) ++ XMapRaised(dpy, systray->win); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +@@ -2107,6 +2318,124 @@ updatestatus(void) + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); ++ updatesystray(); ++} ++ ++void ++updatesystrayicongeom(Client *i, int w, int h) ++{ ++ if (i) { ++ i->h = bh; ++ if (w == h) ++ i->w = bh; ++ else if (h == bh) ++ i->w = w; ++ else ++ i->w = (int) ((float)bh * ((float)w / (float)h)); ++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); ++ /* force icons into the systray dimensions if they don't want to */ ++ if (i->h > bh) { ++ if (i->w == i->h) ++ i->w = bh; ++ else ++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); ++ i->h = bh; ++ } ++ } ++} ++ ++void ++updatesystrayiconstate(Client *i, XPropertyEvent *ev) ++{ ++ long flags; ++ int code = 0; ++ ++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || ++ !(flags = getatomprop(i, xatom[XembedInfo]))) ++ return; ++ ++ if (flags & XEMBED_MAPPED && !i->tags) { ++ i->tags = 1; ++ code = XEMBED_WINDOW_ACTIVATE; ++ XMapRaised(dpy, i->win); ++ setclientstate(i, NormalState); ++ } ++ else if (!(flags & XEMBED_MAPPED) && i->tags) { ++ i->tags = 0; ++ code = XEMBED_WINDOW_DEACTIVATE; ++ XUnmapWindow(dpy, i->win); ++ setclientstate(i, WithdrawnState); ++ } ++ else ++ return; ++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, ++ systray->win, XEMBED_EMBEDDED_VERSION); ++} ++ ++void ++updatesystray(void) ++{ ++ XSetWindowAttributes wa; ++ XWindowChanges wc; ++ Client *i; ++ Monitor *m = systraytomon(NULL); ++ unsigned int x = m->mx + m->mw; ++ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing; ++ unsigned int w = 1; ++ ++ if (!showsystray) ++ return; ++ if (systrayonleft) ++ x -= sw + lrpad / 2; ++ if (!systray) { ++ /* init systray */ ++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); ++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); ++ wa.event_mask = ButtonPressMask | ExposureMask; ++ wa.override_redirect = True; ++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); ++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, ++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); ++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); ++ XMapRaised(dpy, systray->win); ++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); ++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { ++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); ++ XSync(dpy, False); ++ } ++ else { ++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); ++ free(systray); ++ systray = NULL; ++ return; ++ } ++ } ++ for (w = 0, i = systray->icons; i; i = i->next) { ++ /* make sure the background color stays the same */ ++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); ++ XMapRaised(dpy, i->win); ++ w += systrayspacing; ++ i->x = w; ++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); ++ w += i->w; ++ if (i->mon != m) ++ i->mon = m; ++ } ++ w = w ? w + systrayspacing : 1; ++ x -= w; ++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); ++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; ++ wc.stack_mode = Above; wc.sibling = m->barwin; ++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); ++ XMapWindow(dpy, systray->win); ++ XMapSubwindows(dpy, systray->win); ++ /* redraw background */ ++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); ++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); ++ XSync(dpy, False); + } + + void +@@ -2274,6 +2603,16 @@ wintoclient(Window w) + return NULL; + } + ++Client * ++wintosystrayicon(Window w) { ++ Client *i = NULL; ++ ++ if (!showsystray || !w) ++ return i; ++ for (i = systray->icons; i && i->win != w; i = i->next) ; ++ return i; ++} ++ + Monitor * + wintomon(Window w) + { +@@ -2327,6 +2666,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) + return -1; + } + ++Monitor * ++systraytomon(Monitor *m) { ++ Monitor *t; ++ int i, n; ++ if(!systraypinning) { ++ if(!m) ++ return selmon; ++ return m == selmon ? m : NULL; ++ } ++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; ++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; ++ if(systraypinningfailfirst && n < systraypinning) ++ return mons; ++ return t; ++} ++ + void + zoom(const Arg *arg) + { +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0013-feat-remove-accent-color.patch b/profiles/eug-vs/patches/x11-wm/dwm/0013-feat-remove-accent-color.patch new file mode 100644 index 0000000..efa5ed3 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0013-feat-remove-accent-color.patch @@ -0,0 +1,30 @@ +From cad1f11826b0f4a7fe4ee2f8e9328367e10a6140 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Thu, 31 Mar 2022 17:59:22 +0300 +Subject: [PATCH 13/15] feat: remove accent color + +--- + config.def.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 2d2af1a..41cfc16 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,11 +13,11 @@ static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "fira code nerd font:pixelsize=12:antialias=true:autohint=true" }; + static const char col_background[] = "#1d2021"; + static const char col_foreground[] = "#ebdbb2"; +-static const char col_primary[] = "#689d6a"; ++static const char col_primary[] = "#928374"; + static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_foreground, col_background, "#000000" }, +- [SchemeSel] = { col_foreground, col_primary, col_primary }, ++ [SchemeSel] = { col_foreground, col_primary, "#000000" }, + [SchemeStatus] = { col_foreground, col_background, "#000000" }, + }; + +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0014-fix-add-missing-terminal-flag-to-st.patch b/profiles/eug-vs/patches/x11-wm/dwm/0014-fix-add-missing-terminal-flag-to-st.patch new file mode 100644 index 0000000..4fdbe78 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0014-fix-add-missing-terminal-flag-to-st.patch @@ -0,0 +1,37 @@ +From c84ac19422e3cca5e8a2a1898304d7c55883a07b Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Sat, 2 Apr 2022 17:14:16 +0300 +Subject: [PATCH 14/15] fix: add missing terminal flag to st + +--- + config.def.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 41cfc16..f2c79ed 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -22,16 +22,16 @@ static const char *colors[][3] = { + }; + + /* tagging */ +-static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; ++static const char *tags[] = { "1", "2", "3", "4", "5" }; + + static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating isterminal noswallow monitor */ ++ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, ++ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + }; + + /* layout(s) */ +-- +2.35.1 + diff --git a/profiles/eug-vs/patches/x11-wm/dwm/0015-feat-use-classic-dwm-colors.patch b/profiles/eug-vs/patches/x11-wm/dwm/0015-feat-use-classic-dwm-colors.patch new file mode 100644 index 0000000..851bd14 --- /dev/null +++ b/profiles/eug-vs/patches/x11-wm/dwm/0015-feat-use-classic-dwm-colors.patch @@ -0,0 +1,30 @@ +From e3b2372f384a61f55c66d2c79581f9a0f1f39082 Mon Sep 17 00:00:00 2001 +From: eug-vs <eugene@eug-vs.xyz> +Date: Mon, 18 Apr 2022 21:20:32 +0300 +Subject: [PATCH 15/15] feat: use classic dwm colors + +--- + config.def.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index f2c79ed..b3ae63e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -13,11 +13,11 @@ static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "fira code nerd font:pixelsize=12:antialias=true:autohint=true" }; + static const char col_background[] = "#1d2021"; + static const char col_foreground[] = "#ebdbb2"; +-static const char col_primary[] = "#928374"; ++static const char col_cyan[] = "#005577"; + static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_foreground, col_background, "#000000" }, +- [SchemeSel] = { col_foreground, col_primary, "#000000" }, ++ [SchemeSel] = { col_foreground, col_cyan, col_cyan }, + [SchemeStatus] = { col_foreground, col_background, "#000000" }, + }; + +-- +2.35.1 + |