commit 8917670ecee53ffd46e89f1ac22ffe9ecf5090e1 from: Benjamin Stürz date: Sun Dec 17 01:26:27 2023 UTC Import xbgcd commit - 15f3a3a2f5fe4fb609bf560f1cd26ac8907a24c8 commit + 8917670ecee53ffd46e89f1ac22ffe9ecf5090e1 blob - cbfb9ef599eeff12bd160d287b1a825a53164915 blob + bededa2e85204ddaa587830d57929b26e88f6a40 --- Makefile +++ Makefile @@ -14,7 +14,7 @@ HDR_STEST = ${HDR_DMENU} MAN = dwm/dwm.1 st/st.1 dmenu/dmenu.1 dmenu/stest.1 -all: bin/dwm bin/st bin/bedstatus bin/dmenu bin/stest +all: bin/dwm bin/st bin/bedstatus bin/dmenu bin/stest bin/xbgcd clean: rm -rf bin @@ -55,4 +55,8 @@ bin/stest: ${SRC_STEST} ${HDR_STEST} @mkdir -p bin ${CC} -o $@ ${SRC_STEST} ${CFLAGS} +bin/xbgcd: xbgcd/xbgcd.c + @mkdir -p bin + ${CC} -o $@ xbgcd/xbgcd.c ${CFLAGS} `pkg-config --cflags --libs x11` + .PHONY: all clean install blob - 424ce83fa920781beb8cd499a0f309d9818bcf88 blob + b45a56b765d53dd6b0f39145b3f8774bf4e88fab --- TODO +++ TODO @@ -1,7 +1,6 @@ # Import - surf - tabbed -- xbgcd - slock - nsxiv blob - /dev/null blob + 1b12b24364134eaa04e79f3b3384c3405190386d (mode 644) --- /dev/null +++ xbgcd/LICENSE @@ -0,0 +1,22 @@ +MIT/X Consortium License + +© 2022 Benjamin Stürz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + blob - /dev/null blob + d9731410f1b432c39c46631480e57c66dcc3b0ca (mode 644) --- /dev/null +++ xbgcd/config.h @@ -0,0 +1,16 @@ + +// Define the color steps. +static const struct MyColor steps[] = { + { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 }, + { 0.0, 0.0, 1.0 }, +}; + +// The initial background color. +static const struct MyColor initial_color = { 0.5, 0.5, 0.5 }; + +// Interpolation increent per substep. +static const float sub_step_inc = 0.01f; + +// Delay (in milliseconds) between substeps. +static const unsigned delay = 100; blob - /dev/null blob + d36d9c8c5fde5ad200f4e2a9f61d9ffa16ae67a9 (mode 644) --- /dev/null +++ xbgcd/xbgcd.c @@ -0,0 +1,130 @@ +/* See LICENSE file for copyright and license details. + * + * X background color daemon is really simple. It just uses interpolation + * between steps to get the new background color. If the substep reaches 1.0f, + * it resets it, and starts the next step. + */ +#include +#include +#include +#include +#include +#include + +struct MyColor { + float r, g, b; +}; + +#include "config.h" + +const size_t num_steps = (sizeof steps) / (sizeof *steps); + +static Display *dpy; +static int screen; +static Window root; + +static unsigned long MyColorToPixel (const struct MyColor *color); +static unsigned long NameToPixel (const char *color); +static void FillBackground (const struct MyColor *color); +static void die (const char *s); + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp (argv[1], "-v")) { + die ("xkbcd-" VERSION); + } else if (argc != 1) { + die ("usage: xbcd [-v]"); + } + + dpy = XOpenDisplay (NULL); + if (!dpy) + die ("xkbcd: unable to open display"); + +#ifdef __OpenBSD__ + if (pledge ("stdio", NULL) == -1) + die ("pledge"); +#endif // __OpenBSD__ + + screen = DefaultScreen (dpy); + root = RootWindow (dpy, screen); + + size_t step = 0; + float sub_step = 0.0f; + struct MyColor prev = initial_color; + + while (1) { + const struct MyColor cur = steps[step]; + const struct MyColor c = { + .r = prev.r + (cur.r - prev.r) * sub_step, + .g = prev.g + (cur.g - prev.g) * sub_step, + .b = prev.b + (cur.b - prev.b) * sub_step, + }; + + FillBackground (&c); + + sub_step += sub_step_inc; + + if (sub_step > 1.0f) { + step = (step + 1) % num_steps; + prev = cur; + sub_step -= 1.0f; + } + usleep (delay * 1000); + } + XCloseDisplay (dpy); + return 0; +} + +static unsigned long +MyColorToPixel (const struct MyColor *color) +{ + char str[8]; + const int r = (int)(color->r * 255.0f); + const int g = (int)(color->g * 255.0f); + const int b = (int)(color->b * 255.0f); + + snprintf (str, sizeof str, "#%02X%02X%02X", r, g, b); + + return NameToPixel (str); +} + +// This function is taken from xsetroot: https://github.com/freedesktop/xorg-xsetroot/blob/master/xsetroot.c +static unsigned long +NameToPixel (const char *name) +{ + XColor ecolor; + + if (!name || !*name) + return BlackPixel (dpy, screen); + + Colormap colormap = DefaultColormap (dpy, screen); + + if (!XParseColor (dpy, colormap, name, &ecolor)) { + fprintf (stderr, "xbgcd: unknown color '%s'\n", name); + return BlackPixel (dpy, screen); + } + + if (!XAllocColor (dpy, colormap, &ecolor)) { + fprintf (stderr, "xbgcd: unable to allocate color for '%s'\n", name); + return BlackPixel (dpy, screen); + } + + return ecolor.pixel; +} + +static void +FillBackground (const struct MyColor *color) +{ + unsigned long pixel = MyColorToPixel (color); + XSetWindowBackground (dpy, root, pixel); + XClearWindow (dpy, root); + XFlush (dpy); +} + +static void +die (const char *s) +{ + fprintf (stderr, "%s\n", s); + exit (1); +}