Created
July 6, 2022 05:35
-
-
Save alxbnct/48d3d54c0915dc11ef6f70ac67d4f5ed to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<stdio.h> | |
#include<stdlib.h> | |
#include<X11/Xlib.h> | |
#include<X11/cursorfont.h> | |
#include<unistd.h> // added for sleep/usleep | |
// original from [https://bbs.archlinux.org/viewtopic.php?id=85378 Select a screen area with mouse and return the geometry of this area? / Programming & Scripting / Arch Linux Forums] | |
// build with (Ubuntu 14.04): | |
// gcc -Wall xrectsel.c -o xrectsel -lX11 | |
int main(void) | |
{ | |
int rx = 0, ry = 0, rw = 0, rh = 0; | |
int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0; | |
int btn_pressed = 0, done = 0; | |
XEvent ev; | |
Display *disp = XOpenDisplay(NULL); | |
if(!disp) | |
return EXIT_FAILURE; | |
Screen *scr = NULL; | |
scr = ScreenOfDisplay(disp, DefaultScreen(disp)); | |
Window root = 0; | |
root = RootWindow(disp, XScreenNumberOfScreen(scr)); | |
Cursor cursor, cursor2; | |
cursor = XCreateFontCursor(disp, XC_left_ptr); | |
cursor2 = XCreateFontCursor(disp, XC_lr_angle); | |
XGCValues gcval; | |
gcval.foreground = XWhitePixel(disp, 0); | |
gcval.function = GXxor; | |
gcval.background = XBlackPixel(disp, 0); | |
gcval.plane_mask = gcval.background ^ gcval.foreground; | |
gcval.subwindow_mode = IncludeInferiors; | |
GC gc; | |
gc = XCreateGC(disp, root, | |
GCFunction | GCForeground | GCBackground | GCSubwindowMode, | |
&gcval); | |
/* this XGrab* stuff makes XPending true ? */ | |
if ((XGrabPointer | |
(disp, root, False, | |
ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, | |
GrabModeAsync, root, cursor, CurrentTime) != GrabSuccess)) | |
printf("couldn't grab pointer:"); | |
if ((XGrabKeyboard | |
(disp, root, False, GrabModeAsync, GrabModeAsync, | |
CurrentTime) != GrabSuccess)) | |
printf("couldn't grab keyboard:"); | |
// see also: http://stackoverflow.com/questions/19659486/xpending-cycle-is-making-cpu-100 | |
while (!done) { | |
//~ while (!done && XPending(disp)) { | |
//~ XNextEvent(disp, &ev); | |
if (!XPending(disp)) { usleep(1000); continue; } // fixes the 100% CPU hog issue in original code | |
if ( (XNextEvent(disp, &ev) >= 0) ) { | |
switch (ev.type) { | |
case MotionNotify: | |
/* this case is purely for drawing rect on screen */ | |
if (btn_pressed) { | |
if (rect_w) { | |
/* re-draw the last rect to clear it */ | |
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h); | |
} else { | |
/* Change the cursor to show we're selecting a region */ | |
XChangeActivePointerGrab(disp, | |
ButtonMotionMask | ButtonReleaseMask, | |
cursor2, CurrentTime); | |
} | |
rect_x = rx; | |
rect_y = ry; | |
rect_w = ev.xmotion.x - rect_x; | |
rect_h = ev.xmotion.y - rect_y; | |
if (rect_w < 0) { | |
rect_x += rect_w; | |
rect_w = 0 - rect_w; | |
} | |
if (rect_h < 0) { | |
rect_y += rect_h; | |
rect_h = 0 - rect_h; | |
} | |
/* draw rectangle */ | |
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h); | |
XFlush(disp); | |
} | |
break; | |
case ButtonPress: | |
btn_pressed = 1; | |
rx = ev.xbutton.x; | |
ry = ev.xbutton.y; | |
break; | |
case ButtonRelease: | |
done = 1; | |
break; | |
} | |
} | |
} | |
/* clear the drawn rectangle */ | |
if (rect_w) { | |
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h); | |
XFlush(disp); | |
} | |
rw = ev.xbutton.x - rx; | |
rh = ev.xbutton.y - ry; | |
/* cursor moves backwards */ | |
if (rw < 0) { | |
rx += rw; | |
rw = 0 - rw; | |
} | |
if (rh < 0) { | |
ry += rh; | |
rh = 0 - rh; | |
} | |
XCloseDisplay(disp); | |
printf("%dx%d+%d+%d\n",rw,rh,rx,ry); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment