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
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();