commit 4be2da1ec8745d51df63e92c149f3d1484a1113f
Author: muquit <muquit@gmail.com>
Date: Wed, 11 Apr 2018 19:08:10 -0400
Import to git
Diffstat:
A | Makefile | | | 31 | +++++++++++++++++++++++++++++++ |
A | README | | | 21 | +++++++++++++++++++++ |
A | grabc.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);
+}