Browse Source

Initial import of xrectsel source

Note the prior history is left in FFcast.git
lolilolicon 4 years ago
commit
74a6f88cf0
7 changed files with 267 additions and 0 deletions
  1. 1
    0
      .gitattributes
  2. 15
    0
      .gitignore
  3. 2
    0
      Makefile.am
  4. 17
    0
      README.md
  5. 1
    0
      bootstrap
  6. 7
    0
      configure.ac
  7. 224
    0
      xrectsel.c

+ 1
- 0
.gitattributes View File

@@ -0,0 +1 @@
1
+.git* export-ignore

+ 15
- 0
.gitignore View File

@@ -0,0 +1,15 @@
1
+.deps/
2
+aclocal.m4
3
+autom4te.cache/
4
+build-aux/
5
+config.log
6
+config.status
7
+config.status.lineno
8
+configure
9
+configure.lineno
10
+Makefile
11
+Makefile.in
12
+xrectsel
13
+xrectsel-*.tar.gz
14
+*.o
15
+*~

+ 2
- 0
Makefile.am View File

@@ -0,0 +1,2 @@
1
+AM_CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-variadic-macros
2
+bin_PROGRAMS = xrectsel

+ 17
- 0
README.md View File

@@ -0,0 +1,17 @@
1
+xrectsel
2
+========
3
+
4
+`xrectsel` is a small program that tells you the geometry of a rectangular
5
+screen region which you have selected by dragging the mouse / pointer.
6
+
7
+When arguments are passed to `xrectsel`, a limited set of `%` format strings
8
+are recognized and substituted. Look at the source to see what are supported.
9
+
10
+`xrectsel` requires `libX11` to build.
11
+
12
+To build and install from source,
13
+
14
+    ./bootstrap  # required if ./configure is not present
15
+    ./configure --prefix /usr
16
+    make
17
+    make DESTDIR="$directory" install

+ 1
- 0
bootstrap View File

@@ -0,0 +1 @@
1
+autoreconf -vi

+ 7
- 0
configure.ac View File

@@ -0,0 +1,7 @@
1
+AC_INIT([xrectsel], [0.3])
2
+AC_CONFIG_AUX_DIR([build-aux])
3
+AM_INIT_AUTOMAKE([foreign subdir-objects])
4
+AC_PROG_CC
5
+AC_SEARCH_LIBS([XOpenDisplay], [X11], , AC_MSG_ERROR([libx11 is required]))
6
+AC_CONFIG_FILES([Makefile])
7
+AC_OUTPUT

+ 224
- 0
xrectsel.c View File

@@ -0,0 +1,224 @@
1
+/* xrectsel.c -- print the geometry of a rectangular screen region.
2
+
3
+   Copyright (C) 2011-2014  lolilolicon <lolilolicon@gmail.com>
4
+
5
+   This program is free software: you can redistribute it and/or modify
6
+   it under the terms of the GNU General Public License as published by
7
+   the Free Software Foundation, either version 3 of the License, or
8
+   (at your option) any later version.
9
+
10
+   This program is distributed in the hope that it will be useful,
11
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+   GNU General Public License for more details.
14
+
15
+   You should have received a copy of the GNU General Public License
16
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+*/
18
+
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <stdarg.h>
22
+#include <string.h>
23
+#include <X11/Xlib.h>
24
+#include <X11/cursorfont.h>
25
+
26
+#define die(args...) do {error(args); exit(EXIT_FAILURE); } while(0)
27
+
28
+typedef struct Region Region;
29
+struct Region {
30
+  Window root;
31
+  int x; /* offset from left of screen */
32
+  int y; /* offset from top of screen */
33
+  int X; /* offset from right of screen */
34
+  int Y; /* offset from bottom of screen */
35
+  unsigned int w; /* width */
36
+  unsigned int h; /* height */
37
+  unsigned int b; /* border_width */
38
+  unsigned int d; /* depth */
39
+};
40
+
41
+static void error(const char *errstr, ...);
42
+static int print_region_attr(const char *fmt, Region region);
43
+static int select_region(Display *dpy, Window root, Region *region);
44
+
45
+int main(int argc, const char *argv[])
46
+{
47
+  Display *dpy;
48
+  Window root;
49
+  Region sr; /* selected region */
50
+  const char *fmt; /* format string */
51
+
52
+  dpy = XOpenDisplay(NULL);
53
+  if (!dpy) {
54
+    die("failed to open display %s\n", getenv("DISPLAY"));
55
+  }
56
+
57
+  root = DefaultRootWindow(dpy);
58
+
59
+  fmt = argc > 1 ? argv[1] : "%wx%h+%x+%y\n";
60
+
61
+  /* interactively select a rectangular region */
62
+  if (select_region(dpy, root, &sr) != EXIT_SUCCESS) {
63
+    XCloseDisplay(dpy);
64
+    die("failed to select a rectangular region\n");
65
+  }
66
+
67
+  print_region_attr(fmt, sr);
68
+
69
+  XCloseDisplay(dpy);
70
+  return EXIT_SUCCESS;
71
+}
72
+
73
+static void error(const char *errstr, ...)
74
+{
75
+  va_list ap;
76
+
77
+  fprintf(stderr, "xrectsel: ");
78
+  va_start(ap, errstr);
79
+  vfprintf(stderr, errstr, ap);
80
+  va_end(ap);
81
+}
82
+
83
+static int print_region_attr(const char *fmt, Region region)
84
+{
85
+  const char *s;
86
+
87
+  for (s = fmt; *s; ++s) {
88
+    if (*s == '%') {
89
+      switch (*++s) {
90
+        case '%':
91
+          putchar('%');
92
+          break;
93
+        case 'x':
94
+          printf("%i", region.x);
95
+          break;
96
+        case 'y':
97
+          printf("%i", region.y);
98
+          break;
99
+        case 'X':
100
+          printf("%i", region.X);
101
+          break;
102
+        case 'Y':
103
+          printf("%i", region.Y);
104
+          break;
105
+        case 'w':
106
+          printf("%u", region.w);
107
+          break;
108
+        case 'h':
109
+          printf("%u", region.h);
110
+          break;
111
+        case 'b':
112
+          printf("%u", region.b);
113
+          break;
114
+        case 'd':
115
+          printf("%u", region.d);
116
+          break;
117
+      }
118
+    } else {
119
+      putchar(*s);
120
+    }
121
+  }
122
+
123
+  return 0;
124
+}
125
+
126
+static int select_region(Display *dpy, Window root, Region *region)
127
+{
128
+  XEvent ev;
129
+
130
+  GC sel_gc;
131
+  XGCValues sel_gv;
132
+
133
+  int done = 0, btn_pressed = 0;
134
+  int x = 0, y = 0;
135
+  unsigned int width = 0, height = 0;
136
+  int start_x = 0, start_y = 0;
137
+
138
+  Cursor cursor;
139
+  cursor = XCreateFontCursor(dpy, XC_crosshair);
140
+
141
+  /* Grab pointer for these events */
142
+  XGrabPointer(dpy, root, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
143
+               GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
144
+
145
+  sel_gv.function = GXinvert;
146
+  sel_gv.subwindow_mode = IncludeInferiors;
147
+  sel_gv.line_width = 1;
148
+  sel_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode | GCLineWidth, &sel_gv);
149
+
150
+  for (;;) {
151
+    XNextEvent(dpy, &ev);
152
+    switch (ev.type) {
153
+      case ButtonPress:
154
+        btn_pressed = 1;
155
+        x = start_x = ev.xbutton.x_root;
156
+        y = start_y = ev.xbutton.y_root;
157
+        width = height = 0;
158
+        break;
159
+      case MotionNotify:
160
+        /* Draw only if button is pressed */
161
+        if (btn_pressed) {
162
+          /* Re-draw last Rectangle to clear it */
163
+          XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
164
+
165
+          x = ev.xbutton.x_root;
166
+          y = ev.xbutton.y_root;
167
+
168
+          if (x > start_x) {
169
+            width = x - start_x;
170
+            x = start_x;
171
+          } else {
172
+            width = start_x - x;
173
+          }
174
+          if (y > start_y) {
175
+            height = y - start_y;
176
+            y = start_y;
177
+          } else {
178
+            height = start_y - y;
179
+          }
180
+
181
+          /* Draw Rectangle */
182
+          XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
183
+          XFlush(dpy);
184
+        }
185
+        break;
186
+      case ButtonRelease:
187
+        done = 1;
188
+        break;
189
+      default:
190
+        break;
191
+    }
192
+    if (done)
193
+      break;
194
+  }
195
+
196
+  /* Re-draw last Rectangle to clear it */
197
+  XDrawRectangle(dpy, root, sel_gc, x, y, width, height);
198
+  XFlush(dpy);
199
+
200
+  XUngrabPointer(dpy, CurrentTime);
201
+  XFreeCursor(dpy, cursor);
202
+  XFreeGC(dpy, sel_gc);
203
+  XSync(dpy, 1);
204
+
205
+  Region rr; /* root region */
206
+  Region sr; /* selected region */
207
+
208
+  if (False == XGetGeometry(dpy, root, &rr.root, &rr.x, &rr.y, &rr.w, &rr.h, &rr.b, &rr.d)) {
209
+    error("failed to get root window geometry\n");
210
+    return EXIT_FAILURE;
211
+  }
212
+  sr.x = x;
213
+  sr.y = y;
214
+  sr.w = width;
215
+  sr.h = height;
216
+  /* calculate right and bottom offset */
217
+  sr.X = rr.w - sr.x - sr.w;
218
+  sr.Y = rr.h - sr.y - sr.h;
219
+  /* those doesn't really make sense but should be set */
220
+  sr.b = rr.b;
221
+  sr.d = rr.d;
222
+  *region = sr;
223
+  return EXIT_SUCCESS;
224
+}