blob: e629eb4263d9c8451bcdc6d85a4d82cd4d191ece [file] [log] [blame]
Stepan Salenikovich8bc51e52015-03-21 20:17:29 -04001/*
2 * This code is based and adapted from:
3 * https://github.com/lolilolicon/FFcast2/blob/master/xrectsel.c
4 *
5 * now located at:
6 * https://github.com/lolilolicon/xrectsel/blob/master/xrectsel.c
7 *
8 * xrectsel.c -- print the geometry of a rectangular screen region.
9 * Copyright (C) 2011-2014 lolilolicon <lolilolicon@gmail.com>
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <X11/Xlib.h>
23#include <X11/cursorfont.h>
24#include <stdarg.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29void
30xrectsel(unsigned *x_sel, unsigned *y_sel, unsigned *w_sel, unsigned *h_sel)
31{
32 Display *dpy = XOpenDisplay(NULL);
33 if (!dpy)
34 return;
35
36 Window root = DefaultRootWindow(dpy);
37
38 XEvent ev;
39
40 GC sel_gc;
41 XGCValues sel_gv;
42
43 int btn_pressed = 0;
44 int x = 0, y = 0;
45 unsigned int width = 0, height = 0;
46 int start_x = 0, start_y = 0;
47
48 Cursor cursor;
49 cursor = XCreateFontCursor(dpy, XC_crosshair);
50
51 /* Grab pointer for these events */
52 XGrabPointer(dpy, root, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
53 GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
54
55 sel_gv.function = GXinvert;
56 sel_gv.subwindow_mode = IncludeInferiors;
57 sel_gv.line_width = 1;
58 sel_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode | GCLineWidth, &sel_gv);
59
60 for (;;) {
61 XNextEvent(dpy, &ev);
62
63 if (ev.type == ButtonPress) {
64 btn_pressed = 1;
65 x = start_x = ev.xbutton.x_root;
66 y = start_y = ev.xbutton.y_root;
67 width = height = 0;
68
69 } else if (ev.type == MotionNotify) {
70 if (!btn_pressed)
71 continue; /* Draw only if button is pressed */
72
73 /* Re-draw last Rectangle to clear it */
74 XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
75
76 x = ev.xbutton.x_root;
77 y = ev.xbutton.y_root;
78
79 if (x > start_x) {
80 width = x - start_x;
81 x = start_x;
82 } else {
83 width = start_x - x;
84 }
85
86 if (y > start_y) {
87 height = y - start_y;
88 y = start_y;
89 } else {
90 height = start_y - y;
91 }
92
93 /* Draw Rectangle */
94 XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
95 XFlush(dpy);
96
97 } else if (ev.type == ButtonRelease)
98 break;
99 }
100
101 /* Re-draw last Rectangle to clear it */
102 XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
103 XFlush(dpy);
104
105 XUngrabPointer(dpy, CurrentTime);
106 XFreeCursor(dpy, cursor);
107 XFreeGC(dpy, sel_gc);
108 XSync(dpy, 1);
109
110 *x_sel = x;
111 *y_sel = y;
112 *w_sel = width;
113 *h_sel = height;
114
115 XCloseDisplay(dpy);
116}