xrectdraw

Draw geometry of a rectangular screen region
git clone git://git.noxz.tech/xrectdraw
Log | Files | Refs | README | LICENSE

commit 21f56a5908b3c7e4f69f6d990d8ceb94e8b4f05c
parent 4e25a8e3f4e462612627db4a7115d5dacc61d734
Author: Chris Noxz <chris@noxz.tech>
Date:   Fri,  1 Nov 2019 20:29:00 +0100

Large commit with Makefile, license, config and more

Diffstat:
M.gitignore | 2++
ALICENSE | 21+++++++++++++++++++++
AMakefile | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.md | 38++++++++++++++++++++++++++++++++++++++
Aconfig.def.h | 8++++++++
Aconfig.mk | 21+++++++++++++++++++++
Mxrectdraw.c | 125++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
7 files changed, 210 insertions(+), 56 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,3 @@ xrectdraw +config.h +*.o diff --git a/LICENSE b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +© 2019 Chris Noxz <chris@noxz.tech> + +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. diff --git a/Makefile b/Makefile @@ -0,0 +1,51 @@ +.POSIX: + +include config.mk + +SRC = xrectdraw.c +OBJ = $(SRC:.c=.o) + +all: options xrectdraw + +options: + @echo xrectdraw build options: + @echo "VERSION = $(VERSION)" + @echo "CFLAGS = $(STCFLAGS)" + @echo "LDFLAGS = $(STLDFLAGS)" + @echo "CC = $(CC)" + +.c.o: + @echo CC $< + @$(CC) $(STCFLAGS) -c $< + +${OBJ}: config.h config.mk + +config.h: + @echo creating $@ from config.def.h + @cp config.def.h $@ + +xrectdraw: $(OBJ) + @echo CC -o $@ + @$(CC) -o $@ $(OBJ) $(STLDFLAGS) + +clean: + @echo cleaning + @rm -f xrectdraw $(OBJ) + +install: xrectdraw + @echo installing executables to ${PREFIX}/bin + @mkdir -p ${PREFIX}/bin + @cp -f xrectdraw ${PREFIX}/bin + @chmod 755 ${PREFIX}/bin/xrectdraw +# @echo installing manual page to ${MANPREFIX}/man1 +# @mkdir -p ${MANPREFIX}/man1 +# @cp -f xrectdraw.1 ${MANPREFIX}/man1 +# @chmod 644 ${MANPREFIX}/man1/xrectdraw.1 + +uninstall: + @echo removing executable files from ${PREFIX}/bin + @rm -f ${PREFIX}/bin/xrectdraw +# @echo removing manual page from ${MANPREFIX}/man1 +# @rm -f ${MANPREFIX}/man1/xrectdraw.1 + +.PHONY: all options clean install uninstall diff --git a/README.md b/README.md @@ -0,0 +1,38 @@ +xrectdraw +========= +A small program used to draw rectangles on X11. The idea came when I needed +something to indicate screen recordings for a small script using ffmpeg. I used +xrectsel for selecting the region for ffmpeg to capture, so I kinda got the +inspiration from there. + +xrectdraw actually draws four windows making up the borders of the rectangle. +This means no compositor is needed, the root window isn't hogged and the region +is not overlaied. + +Installation +------------ +Edit config.mk to match your local setup (xrectdraw is installed into the +/usr/local namespace by default), then simply enter the following command to +install (if necessary as root): + + make clean install + +Customization +------------- +xrectdraw can be customized by creating a custom config.h and (re)compiling the +source code. + +Usage +----- +Together with the source code is a script called *screenrec.sh* which is a fine +example of how xrectdraw can be used. The program is used like this: + + xrectdraw 10 20 100 200 \#ff0000 3:2:3:2 + +The example above draws a rectangle, 100px wide, 200px heigh at the position +(x:10px, y:20px). The borders are red, the top and bottom are 3px wide and the +right and left are 2pc wide. + +License +------- +The project is licensed under the MIT license. diff --git a/config.def.h b/config.def.h @@ -0,0 +1,8 @@ + /* See LICENSE file for copyright and license details. */ +#define BORDER_TOP 1 +#define BORDER_RIGHT 1 +#define BORDER_BOTTOM 1 +#define BORDER_LEFT 1 + +static int exit_key = 0x09; +static float dim_percentage = 0.4; diff --git a/config.mk b/config.mk @@ -0,0 +1,21 @@ +# xrectdraw version +VERSION = 0.0.1 + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# includes and libs +INCS = -I$(X11INC) +LIBS = -L$(X11LIB) -lX11 + +# flags +CFLAGS = -Wall -pedantic -std=c99 +CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# compiler and linker +CC = gcc diff --git a/xrectdraw.c b/xrectdraw.c @@ -1,3 +1,26 @@ +/* + * MIT License + * + * © 2019 Chris Noxz <chris@noxz.tech> + * + * 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. + */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -6,6 +29,8 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "config.def.h" + struct Border { int top; int right; @@ -13,14 +38,11 @@ struct Border { int left; }; -Display *dpy; -int screen, gfocus; -Window root; -Window win[4]; -Drawable drw; -XColor color; -XColor color_dim; -struct Border border; +static int screen, gfocus; +static Display *dpy; +static Window root, win[4]; +static XColor color[2]; +static struct Border border; void die(char *format, ...) @@ -37,21 +59,13 @@ die(char *format, ...) void draw(int x, int y, int width, int height) { - int i; + int i, ix, iy, iw, ih; XWindowAttributes wa; XSetWindowAttributes swa; XClassHint ch = {"xrectdraw", "xrectdraw"}; - XIM xim; - XIC xic; - - // setup for left border - int ix = x - border.left, - iy = y - border.top, - iw = border.left, - ih = height + border.bottom; swa.border_pixel = 0; - swa.background_pixel = color.pixel; + swa.background_pixel = color[0].pixel; swa.override_redirect = 1; swa.event_mask = ExposureMask | KeyPressMask @@ -61,38 +75,35 @@ draw(int x, int y, int width, int height) XGetWindowAttributes(dpy, root, &wa); for (i = 0; i < 4; i++) { - win[i] = XCreateWindow(dpy, root, ix, iy, iw, ih, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - - XSetClassHint(dpy, win[i], &ch); - - xim = XOpenIM(dpy, NULL, NULL, NULL); - xic = XCreateIC(xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, win[i], XNFocusWindow, win[i], NULL); - - XMapRaised(dpy, win[i]); - XSetInputFocus(dpy, win[i], RevertToParent, CurrentTime); - switch (i) { - // setup for right border - case 0: + case 0: // setup for left border + ix = x - border.left; + iy = y - border.top; + iw = border.left; + ih = height + border.bottom; + break; + case 1: // setup for right border ix += (width + border.left); iw = border.right; break; - // setup for top border - case 1: + case 2: // setup for top border ix -= (width + border.left); iw = (width + border.left + border.right); ih = border.top; break; - // setup for bottom border - case 2: + case 3: // setup for bottom border ih = border.bottom; iy += (height + border.top); break; } + + win[i] = XCreateWindow(dpy, root, ix, iy, iw, ih, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + + XSetClassHint(dpy, win[i], &ch); + XMapRaised(dpy, win[i]); + XSetInputFocus(dpy, win[i], RevertToParent, CurrentTime); } } @@ -107,6 +118,7 @@ hex(const char c) return c - 0x61 + 10; else puts("error: cannot set color"); + return 0; } void @@ -115,29 +127,31 @@ setcolor(const char *clr) int i, r; const char *ptr; - color.flags = DoRed | DoGreen | DoBlue; - color_dim.flags = DoRed | DoGreen | DoBlue; + color[0].flags = DoRed | DoGreen | DoBlue; + color[1].flags = DoRed | DoGreen | DoBlue; + for (i = 0; i < 3; i++) { ptr = clr + (1 + i * 2); r = (hex(ptr[0]) * 16 + hex(ptr[1])) * 256; switch (i) { case 0: - color.red = r; - color_dim.red = r * 0.4; + color[0].red = r; + color[1].red = r * dim_percentage; break; case 1: - color.green = r; - color_dim.green = r * 0.4; + color[0].green = r; + color[1].green = r * dim_percentage; break; case 2: - color.blue = r; - color_dim.blue = r * 0.4; + color[0].blue = r; + color[1].blue = r * dim_percentage; break; } } - XAllocColor(dpy, DefaultColormap(dpy, screen), &color); - XAllocColor(dpy, DefaultColormap(dpy, screen), &color_dim); + + XAllocColor(dpy, DefaultColormap(dpy, screen), &color[0]); + XAllocColor(dpy, DefaultColormap(dpy, screen), &color[1]); } void @@ -152,7 +166,7 @@ toggle() void highlight(int focus) { - unsigned long pixel = (gfocus = focus) ? color.pixel : color_dim.pixel; + unsigned long pixel = color[!(gfocus = focus)].pixel; for (int i = 0; i < 4; i++) { XSetWindowBackground(dpy, win[i], pixel); @@ -174,13 +188,12 @@ setborders(const char *str) int main(int argc, const char *argv[]) { - int width, height, - x, y; + int x, y, width, height; - border.top = 1; - border.right = 1; - border.bottom = 1; - border.left = 1; + border.top = BORDER_TOP; + border.right = BORDER_RIGHT; + border.bottom = BORDER_BOTTOM; + border.left = BORDER_LEFT; if (argc == 7 && argc--) setborders(argv[6]); @@ -220,7 +233,7 @@ main(int argc, const char *argv[]) XNextEvent(dpy, &ev); if (ev.type == Expose) continue; - else if (ev.type == KeyPress && ev.xkey.keycode == 0x09) + else if (ev.type == KeyPress && ev.xkey.keycode == exit_key) break; else if (ev.type == ButtonPress) toggle();