|
|
- /* xrectsel.c -- print the geometry of a rectangular screen region.
-
- Copyright (C) 2011-2014 lolilolicon <lolilolicon@gmail.com>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include <config.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <X11/Xlib.h>
- #include <X11/cursorfont.h>
-
- #define die(args...) do {error(args); exit(EXIT_FAILURE); } while(0)
-
- typedef struct Region Region;
- struct Region {
- Window root;
- int x; /* offset from left of screen */
- int y; /* offset from top of screen */
- int X; /* offset from right of screen */
- int Y; /* offset from bottom of screen */
- unsigned int w; /* width */
- unsigned int h; /* height */
- unsigned int b; /* border_width */
- unsigned int d; /* depth */
- };
-
- static void error(const char *errstr, ...);
- static int print_region_attr(const char *fmt, Region region);
- static int select_region(Display *dpy, Window root, Region *region);
-
- int main(int argc, const char *argv[])
- {
- Display *dpy;
- Window root;
- Region sr; /* selected region */
- const char *fmt; /* format string */
-
- dpy = XOpenDisplay(NULL);
- if (!dpy) {
- die("failed to open display %s\n", getenv("DISPLAY"));
- }
-
- root = DefaultRootWindow(dpy);
-
- fmt = argc > 1 ? argv[1] : "%wx%h+%x+%y\n";
-
- /* interactively select a rectangular region */
- if (select_region(dpy, root, &sr) != EXIT_SUCCESS) {
- XCloseDisplay(dpy);
- die("failed to select a rectangular region\n");
- }
-
- print_region_attr(fmt, sr);
-
- XCloseDisplay(dpy);
- return EXIT_SUCCESS;
- }
-
- static void error(const char *errstr, ...)
- {
- va_list ap;
-
- fprintf(stderr, "xrectsel: ");
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- }
-
- static int print_region_attr(const char *fmt, Region region)
- {
- const char *s;
-
- for (s = fmt; *s; ++s) {
- if (*s == '%') {
- switch (*++s) {
- case '%':
- putchar('%');
- break;
- case 'x':
- printf("%i", region.x);
- break;
- case 'y':
- printf("%i", region.y);
- break;
- case 'X':
- printf("%i", region.X);
- break;
- case 'Y':
- printf("%i", region.Y);
- break;
- case 'w':
- printf("%u", region.w);
- break;
- case 'h':
- printf("%u", region.h);
- break;
- case 'b':
- printf("%u", region.b);
- break;
- case 'd':
- printf("%u", region.d);
- break;
- }
- } else {
- putchar(*s);
- }
- }
-
- return 0;
- }
-
- static int select_region(Display *dpy, Window root, Region *region)
- {
- XEvent ev;
-
- GC sel_gc;
- XGCValues sel_gv;
-
- int done = 0, btn_pressed = 0;
- int x = 0, y = 0;
- unsigned int width = 0, height = 0;
- int start_x = 0, start_y = 0;
-
- Cursor cursor;
- cursor = XCreateFontCursor(dpy, XC_crosshair);
-
- /* Grab pointer for these events */
- XGrabPointer(dpy, root, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
- GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
-
- sel_gv.function = GXinvert;
- sel_gv.subwindow_mode = IncludeInferiors;
- sel_gv.line_width = 1;
- sel_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode | GCLineWidth, &sel_gv);
-
- for (;;) {
- XNextEvent(dpy, &ev);
- switch (ev.type) {
- case ButtonPress:
- btn_pressed = 1;
- x = start_x = ev.xbutton.x_root;
- y = start_y = ev.xbutton.y_root;
- width = height = 0;
- break;
- case MotionNotify:
- /* Draw only if button is pressed */
- if (btn_pressed) {
- /* Re-draw last Rectangle to clear it */
- XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
-
- x = ev.xbutton.x_root;
- y = ev.xbutton.y_root;
-
- if (x > start_x) {
- width = x - start_x;
- x = start_x;
- } else {
- width = start_x - x;
- }
- if (y > start_y) {
- height = y - start_y;
- y = start_y;
- } else {
- height = start_y - y;
- }
-
- /* Draw Rectangle */
- XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
- XFlush(dpy);
- }
- break;
- case ButtonRelease:
- done = 1;
- break;
- default:
- break;
- }
- if (done)
- break;
- }
-
- /* Re-draw last Rectangle to clear it */
- XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
- XFlush(dpy);
-
- XUngrabPointer(dpy, CurrentTime);
- XFreeCursor(dpy, cursor);
- XFreeGC(dpy, sel_gc);
- XSync(dpy, 1);
-
- Region rr; /* root region */
- Region sr; /* selected region */
-
- if (False == XGetGeometry(dpy, root, &rr.root, &rr.x, &rr.y, &rr.w, &rr.h, &rr.b, &rr.d)) {
- error("failed to get root window geometry\n");
- return EXIT_FAILURE;
- }
- sr.x = x;
- sr.y = y;
- sr.w = width;
- sr.h = height;
- /* calculate right and bottom offset */
- sr.X = rr.w - sr.x - sr.w;
- sr.Y = rr.h - sr.y - sr.h;
- /* those doesn't really make sense but should be set */
- sr.b = rr.b;
- sr.d = rr.d;
- *region = sr;
- return EXIT_SUCCESS;
- }
|