grabc

Tool to identify pixel colors on X
git clone https://git.sinitax.com/muquit/grabc
Log | Files | Refs | README | Upstream | sfeed.txt

commit 4be2da1ec8745d51df63e92c149f3d1484a1113f
Author: muquit <muquit@gmail.com>
Date:   Wed, 11 Apr 2018 19:08:10 -0400

Import to git

Diffstat:
AMakefile | 31+++++++++++++++++++++++++++++++
AREADME | 21+++++++++++++++++++++
Agrabc.c | 639+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 691 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,31 @@ +## +# Makefile automatically generated by genmake 1.0, Mar-16-97 +# genmake 1.0 by ma_muquit@fccc.edu, RCS +## +CC= cc +DEFS= +PROGNAME= grabc +LIBS= -L/usr/X11R6/lib -lX11 + +INCLUDES= -I. + +# replace -O with -g in order to debug + +DEFINES= $(INCLUDES) $(DEFS) -D__USE_FIXED_PROTOTYPES__ -DSYS_UNIX=1 +CFLAGS= -O $(DEFINES) + +SRCS = grabc.c + +OBJS = grabc.o + +.c.o: + rm -f $@ + $(CC) $(CFLAGS) -c $*.c + +all: $(PROGNAME) + +$(PROGNAME) : $(OBJS) + $(CC) $(CFLAGS) -o $(PROGNAME) $(OBJS) $(LIBS) + +clean: + rm -f $(OBJS) $(PROGNAME) core diff --git a/README b/README @@ -0,0 +1,21 @@ +A simple program to determine the color string in hex by clicking on a pixel. + + When this program is run, the mouse pointer is grabbed and changed to + a cross hair and when the mouse is clicked, the color of the clicked + pixel is written to stdout in hex prefixed with # + + This program can be useful when you see a color and want to use the + color in xterm or your window manager's border but no clue what the + name of the color is. It's silly to use a image processing software + to find it out. + +To compile, at the shell prompt, type: + make + +-- +Muhammd A Muquit +ma_muquit@fccc.edu +http://www.fccc.edu/users/muquit/ + +March 16, 1997 +(a quick hack on my home linux box) diff --git a/grabc.c b/grabc.c @@ -0,0 +1,639 @@ +/* A program to pick a color by clicking the mouse. + * + * RCS: + * $Revision$ + * $Date$ + * + * Description: + * + * When this program is run, the mouse pointer is grabbed and changed to + * a cross hair and when the mouse is clicked, the color of the clicked + * pixel is written to stdout in hex prefixed with # + * + * This program can be useful when you see a color and want to use the + * color in xterm or your window manager's border but no clue what the + * name of the color is. It's silly to use a image processing software + * to find it out. + * + * Example: + * xterm -bg `grabc` -fg `grabc` (silly but esoteric!) + * + * Development History: + * who when why + * ma_muquit@fccc.edu march-16-1997 first cut + * muquit@muquit.com Apr-10-2018 Do not use default colormap, + * rather get it from window attributes. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#include <math.h> +#include <signal.h> +#include <time.h> + +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xresource.h> +#include <X11/Xproto.h> +#include <X11/Xatom.h> +#include <X11/cursorfont.h> +#include <X11/keysym.h> + +#ifndef True +#define True 1 +#endif + +#ifndef False +#define False 0 +#endif + +#define VERSION_S "1.0.2" + +static int g_debug = False; +static int g_print_in_hex = False; +static int g_print_in_rgb = False; +static int g_print_all_16_bits = False; +static Window g_window_id = (Window) NULL; +static int g_loc_specified = False; +static int g_x = 1; +static int g_y = 1; +static unsigned int g_width = 0; +static unsigned int g_height = 0; +static Cursor g_cross_cursor=(Cursor) NULL; + +/* private function prototypes */ +static Window select_window (Display *,int *x,int *y); + +static Window findSubWindow(Display *display,Window top_winodw, + Window window_to_check,int *x,int *y); + +static Window get_window_color(Display *display,XColor *color); +static int MXError(Display *display,XErrorEvent *error); + +static void show_usage(void) +{ + char + **p; + + static char *options[]= + { +" -v - show version info", +" -h - show this usage", +" -hex - print pixel value as Hex on stdout", +" -rgb - print pixel value as RGB on stdout", +" -W - print the Window id at mouse click", +" -w id - window id in hex, use before -l", +" -l +x+y - pixel co-ordinate. requires window id", +" -d - show debug messages", +" -a - Print all 16 bits of color. Default is high order 8 bits", +"Example:", +"* Print pixel color in hex on stdout and rgb on stderr:", +" $ grabc", +"* Show usage:", +" $ grabc -h", +"* Print Window Id (Note the upper case W):", +" $ grabc -W", +"* Print pixel color of Window iwith id 0x13234 at location 10,20", +" $ grabc -w 0x13234 -l +10+20", +(char *) NULL + + }; + + (void) printf("\n"); + (void) printf("grabc Version: %s\n",VERSION_S); + (void) printf("A program to identify a pixel color of an X Window\n"); + (void) printf("by muquit@muquit.com https://www.muquit.com/\n\n"); + (void) printf("Usage: grabc [options]\n"); + (void) printf("Where the options are:\n"); + for (p=options; *p != NULL; p++) + { + (void) fprintf(stdout,"%s\n",*p); + (void) fflush(stdout); + } +} + + +static void log_debug(const char *fmt,...) +{ + va_list + args; + if (!g_debug) + { + return; + } + va_start(args, fmt); + (void) fprintf(stderr,"(debug): "); + vfprintf(stderr,fmt,args); + (void) fprintf(stderr,"\n"); + va_end(args); +} + +static Cursor get_cross_cursor(Display *display) +{ + if (g_cross_cursor == (Cursor) NULL) + { + g_cross_cursor=XCreateFontCursor(display,XC_tcross); + if (g_cross_cursor == (Cursor) NULL) + { + (void) fprintf (stderr,"ERROR: Failed to create Cross Cursor!\n"); + exit(1); + } + } + return g_cross_cursor; +} +static Window grab_mouse(Display *display,Window root_window) +{ + int + status; + + Window + subwindow; + + XEvent + event; + + Cursor + target_cursor; + + + if (g_window_id != (Window) NULL) + { + return g_window_id; + } + + target_cursor = get_cross_cursor(display); + status=XGrabPointer(display,root_window,False, + (unsigned int) ButtonPressMask,GrabModeSync, + GrabModeAsync,root_window,target_cursor,CurrentTime); + if (status == GrabSuccess) + { + XAllowEvents(display,SyncPointer,CurrentTime); + XWindowEvent(display,root_window,ButtonPressMask,&event); + subwindow = event.xbutton.subwindow; + } + else + { + return root_window; + } + + return subwindow; +} +static void upgrab_mouse(Display *display) +{ + if (g_window_id != (Window) NULL) + { + XUngrabPointer(display,CurrentTime); + } +} + + + + + +/* +** function to select a window +** output parameters: x,y (coordinate of the point of click) +** reutrns Window +** exits if mouse can not be grabbed +*/ +static Window select_window(Display *display,int *x,int *y) +{ + Cursor + target_cursor; + + static Cursor + cross_cursor=(Cursor) NULL; + int + status; + + Window + target_window, + root_window; + + XEvent + event; + + /* + ** If window id and location is specified return the window id as + ** target window. Also initilaize x, y those specified with -l + */ + if ((g_window_id != (Window) NULL) && g_loc_specified) + { + log_debug("Returning passing window: %lx",g_window_id); + (*x) = g_x; + (*y) = g_y; + return g_window_id; + } + target_window=(Window) NULL; + target_cursor = get_cross_cursor(display); + root_window=XRootWindow(display,XDefaultScreen(display)); + log_debug("Root window: 0x%08lx",root_window); + +// if (!g_loc_specified) +// { + status=XGrabPointer(display,root_window,False, + (unsigned int) ButtonPressMask,GrabModeSync, + GrabModeAsync,root_window,target_cursor,CurrentTime); + if (status == GrabSuccess) + { + XAllowEvents(display,SyncPointer,CurrentTime); + XWindowEvent(display,root_window,ButtonPressMask,&event); + Window subwindow = event.xbutton.subwindow; + + if (event.type == ButtonPress) + { + target_window=findSubWindow(display,root_window, + subwindow, + &event.xbutton.x, + &event.xbutton.y ); + + if (target_window == (Window) NULL) + { + (void) fprintf (stderr, + "ERROR: Failed to get target window, getting root window!\n"); + target_window=root_window; + } + log_debug("Target Window id: 0x%lx", target_window); + if (!g_loc_specified) + { + XUngrabPointer(display,CurrentTime); + } + } + + } + else + { + (void) fprintf (stderr,"ERROR: Failed to grab mouse pointer!\n"); + exit(1); + } + + /* free things we do not need, always a good practice */ + XFreeCursor(display,cross_cursor); + (*x)=event.xbutton.x; + (*y)=event.xbutton.y; +// } +// else +// { +// (*x) = g_x; +// (*y) = g_y; +// } + + + log_debug("x,y: +%d+%d",(*x),(*y)); + return (target_window); +} + +/* find a window */ +static Window findSubWindow(Display *display,Window top_window, + Window window_to_check,int *x,int *y) +{ + int + newx, + newy; + + Window + window; + + if (top_window == (Window) NULL) + return ((Window) NULL); + + if (window_to_check == (Window) NULL) + return ((Window) NULL); + + /* initialize automatics */ + window=window_to_check; + + while ((XTranslateCoordinates(display,top_window,window_to_check, + *x,*y,&newx,&newy,&window) != 0) && + (window != (Window) NULL)) + { + if (window != (Window) NULL) + { + top_window=window_to_check; + window_to_check=window; + (*x)=newx; + (*y)=newy; + } + } + + if (window == (Window) NULL) + window=window_to_check; + + + (*x)=newx; + (*y)=newy; + + log_debug("Window id: %lx",window); + + return (window); +} + +/* + * get the color of the pixel of the point of mouse click + * output paramter: XColor *color + * + * returns + * target Window on success + * NULL on failure + * + */ + +static Window get_window_color(Display *display,XColor *color) +{ + Window + root_window, + target_window; + + XImage + *ximage; + + int + x, + y; + + Status + status; + + root_window=XRootWindow(display,XDefaultScreen(display)); + log_debug("Root window: 0x%08lx",root_window); + target_window=select_window(display,&x,&y); + + log_debug("Selected Window id: %lx",target_window); + + if (target_window == (Window) NULL) + return (Window) NULL; + + log_debug("Getting Ximage x,y:%d,%d",x,y); + ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap); + if (ximage == (XImage *) NULL) + { + /* Try root window */ + log_debug("Could not get XImage from window: 0x%lx",target_window); + log_debug("Trying to get XImage from root window: 0x%lx",root_window); + ximage=XGetImage(display,root_window,x,y,1,1,AllPlanes,ZPixmap); + if (ximage == (XImage *) NULL) + { + log_debug("Could not get XImage from target or root window"); + return (Window) NULL; + } + else + { + log_debug("OK successfully got XImage from root window"); + target_window = root_window; + } + + } + + color->pixel=XGetPixel(ximage,0,0); + XDestroyImage(ximage); + + return (target_window); +} + +/* forgiving X error handler */ + +static int MXError (Display *display, XErrorEvent *error) +{ + int + xerrcode; + + xerrcode = error->error_code; + + if (xerrcode == BadAlloc || + (xerrcode == BadAccess && error->request_code==88)) + { + return (False); + } + else + { + switch (error->request_code) + { + case X_GetGeometry: + { + if (error->error_code == BadDrawable) + return (False); + break; + } + + case X_GetWindowAttributes: + case X_QueryTree: + { + if (error->error_code == BadWindow) + return (False); + break; + } + + case X_QueryColors: + { + if (error->error_code == BadValue) + return(False); + break; + } + } + } + return (True); +} + +int main(int argc,char **argv) +{ + Display + *display; + + int + x, + y, + status; + + XColor + color; + + int + rc, + i, + r, + g, + b; + + Window + window_id, + target_window; + + XWindowAttributes + window_attributes; + + char + *option; + + for (i=1; i < argc; i++) + { + option = argv[i]; + switch(*(option+1)) + { + case 'a': + { + g_print_all_16_bits = True; + break; + } + case 'd': + { + g_debug = True; + break; + } + + case 'h': + { + if (strncmp("hex",option+1,3) == 0) + { + + } + else + { + show_usage(); + return(1); + } + break; + } + + case 'w': + { + if (*option == '-') + { + i++; + if (i == argc) + { + (void) fprintf(stderr,"ERROR: Missing Window id\n"); + return(1); + } + } + g_window_id = (Window) strtol(argv[i],NULL, 16); + + break; + } + case 'W': + { + display=XOpenDisplay((char *) NULL); + if (display == NULL) + { + (void) fprintf(stderr,"ERROR: Could not open Display\n"); + return(1); + } + Window window = select_window(display, &x, &y); + if (window != (Window) NULL) + { + (void) fprintf(stdout,"0x%lx\n",window); + } + return(1); + break; + } + + case 'l': + { + if (*option == '-') + { + i++; + if (i == argc) + { + (void) fprintf(stderr,"ERROR: Missing location +x+y\n"); + return(1); + } + } + rc = XParseGeometry(argv[i], &g_x,&g_y,&g_width,&g_height); + if (rc == 0) + { + (void) fprintf(stderr,"ERROR: Could not parse location: %s\n",argv[i]); + (void) fprintf(stderr,"Example: -l +10+20\n"); + return(1); + } + if (g_window_id == (Window) NULL) + { + (void) fprintf(stderr,"ERROR: Please specify window id with -w in hex to use this option\n"); + (void) fprintf(stderr,"Use -W option to find the Window Id\n"); + return(1); + } + g_loc_specified = True; + + break; + } + + case 'v': + { + (void) fprintf(stderr,"grabc v%s\n",VERSION_S); + return(1); + break; + } + + default: + { + break; + } + } + + /* + if (strncmp(argv[i],"-h",2) == 0 || + strncmp(argv[i],"-v",2) == 0) + { + (void) fprintf (stderr,"grabc %s by muquit@muquit.com\n", + VERSION_S); + (void) fprintf(stderr,"https://www.muquit.com/\n"); + exit(1); + } + if (strncmp(argv[i],"-d",2) == 0) + { + debug = True; + } + */ + } + + display=XOpenDisplay((char *) NULL); + XSetErrorHandler(MXError); + + if (display == (Display *) NULL) + { + (void) fprintf (stderr,"ERROR: Failed to open DISPLAY!\n"); + exit(1); + } + + target_window = get_window_color(display,&color); + if (target_window != (Window) NULL) + { + status = XGetWindowAttributes(display, target_window, + &window_attributes); + if (status == False || window_attributes.map_state != IsViewable) + { + (void) fprintf(stderr,"ERROR: Could not get Window Attributes\n"); + return(1); + } + XQueryColor(display, window_attributes.colormap, &color); + if (g_print_all_16_bits) + { + (void) fprintf(stdout,"#%04x%04x%04x\n", + (unsigned int)color.red, + (unsigned int) color.green, + (unsigned int) color.blue); + (void) fflush(stdout); + } + else + { + r=(color.red >> 8); + g=(color.green >> 8); + b=(color.blue >> 8); + (void) fprintf (stdout,"#%02x%02x%02x\n",r,g,b); + (void) fflush(stdout); + } + /* + ** write the values in decimal on stderr + */ + (void) fprintf(stderr,"%d,%d,%d\n",r,g,b); + } + else + { + (void) fprintf (stderr,"ERROR: Failed to grab color!\n"); + } + return (0); +}