├── LICENSE.txt ├── Makefile ├── README.md ├── grabc.1 ├── grabc.c ├── grabc.pod ├── install-sh └── mkinstalldirs /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License is MIT 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included 11 | in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 18 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | # Makefile automatically generated by genmake 1.0, Mar-16-97 3 | # genmake 1.0 by ma_muquit@fccc.edu, RCS 4 | ## 5 | CC= cc 6 | DEFS= 7 | PROGNAME= grabc 8 | LIBS= -L/usr/X11R6/lib -lX11 9 | 10 | INCLUDES= -I. 11 | cp=/bin/cp -fv 12 | DESTDIR = 13 | binary=./grabc 14 | manpage=./grabc.1 15 | bindir=/usr/local/bin 16 | mandir=/usr/local/share/man/man1 17 | 18 | # replace -O with -g in order to debug 19 | 20 | DEFINES= $(INCLUDES) $(DEFS) -D__USE_FIXED_PROTOTYPES__ -DSYS_UNIX=1 21 | CFLAGS= -O $(DEFINES) 22 | 23 | SRCS = grabc.c 24 | 25 | OBJS = grabc.o 26 | 27 | .c.o: 28 | rm -f $@ 29 | $(CC) $(CFLAGS) -c $*.c 30 | 31 | all: $(PROGNAME) 32 | 33 | $(PROGNAME) : $(OBJS) 34 | $(CC) $(CFLAGS) -o $(PROGNAME) $(OBJS) $(LIBS) 35 | 36 | doc: 37 | pod2man grabc.pod > grabc.1 38 | 39 | install: installdirs install-bin install-man 40 | 41 | install-bin: 42 | ${cp} ${binary} ${DESTDIR}${bindir} 43 | 44 | installdirs: 45 | $(SHELL) ./mkinstalldirs ${DESTDIR}${bindir} 46 | $(SHELL) ./mkinstalldirs ${DESTDIR}${mandir} 47 | 48 | install-man: 49 | ${cp} ${manpage} ${DESTDIR}${mandir} 50 | 51 | deb: 52 | /bin/rm -f *.deb 53 | /bin/rm -rf /tmp/grabc 54 | make DESTDIR=/tmp/grabc install 55 | fpm -s dir -t deb -C /tmp/grabc --name grabc --version 1.0.2 --iteration 1 --description "A program to id entify a pixel color on an X Window" 56 | /bin/rm -rf /tmp/grabc 57 | clean: 58 | rm -f $(OBJS) $(PROGNAME) core *.deb 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Downloads](https://img.shields.io/github/downloads/muquit/grabc/total.svg)](https://github.com/muquit/grabc/releases) 2 | # grabc 3 | A command line tool to identify a pixel color on an X Window. 4 | 5 | When this program is run, the mouse pointer is grabbed and changed to 6 | a cross hair and when the mouse is clicked, the color of the clicked 7 | pixel is written to stdout in hex prefixed with # 8 | 9 | This program can be useful when you see a color and want to use the 10 | color in xterm or your window manager's border but no clue what the 11 | name of the color is. It's silly to use a image processing software 12 | to find it out. (That's how I described it 20 years ago, so keeping it 13 | this way for historical reasons - Apr-11-2018). 14 | 15 | # Synopsis 16 | 17 | ``` 18 | grabc v1.0.2 19 | A program to identify a pixel color of an X Window 20 | by muquit@muquit.com https://www.muquit.com/ 21 | 22 | Usage: grabc [options] 23 | Where the options are: 24 | -v - show version info 25 | -h - show this usage 26 | -hex - print pixel value as Hex on stdout 27 | -rgb - print pixel value as RGB on stderr 28 | -W - print the Window id at mouse click 29 | -w id - window id in hex, use with -l +x+y 30 | -l +x+y - pixel co-ordinate. requires window id 31 | -d - show debug messages 32 | -a - Print all 16 bits of color. Default is high order 8 bits 33 | Example: 34 | * Print pixel color in hex on stdout: 35 | $ grabc 36 | * Show usage: 37 | $ grabc -h 38 | * Print Window Id (Note the upper case W): 39 | $ grabc -W 40 | * Print pixel color of Window with id 0x13234 at location 10,20 41 | $ grabc -w 0x13234 -l +10+20 42 | ``` 43 | 44 | # How to compile 45 | Older version of this program is available on Ubuntu. However, if you need to get the latest version, you have to compile it yourself. 46 | 47 | * You will need ```libx11-dev``` package if you are on Ubuntu. 48 | ``` 49 | sudo apt-get -y install libx11-dev 50 | ``` 51 | * To compile, at the shell prompt, type: 52 | ``` 53 | make 54 | ``` 55 | 56 | * To install, at the shell prompt, type: 57 | ``` 58 | sudo make install 59 | ``` 60 | The binary *grabc* will be install in /usr/local/bin/ and the man page *grabc.1* 61 | will be installed in /usr/local/share/man/man1/ 62 | 63 | If you want to install it in some other directory: 64 | ``` 65 | make DESTDIR=/tmp/grabc install 66 | ``` 67 | 68 | * If you want to create a debian package, install [fpm](https://github.com/jordansissel/fpm) first, then type: 69 | ``` 70 | make deb 71 | ``` 72 | 73 | * Install the debian package: 74 | ``` 75 | sudo dpkg -i ./grabc_1.0.2-1_amd64.deb 76 | ``` 77 | 78 | * To uninstall the debian package: 79 | ``` 80 | sudo dpkg -r grabc 81 | ``` 82 | 83 | # Know Issues 84 | 85 | * If color grabbed from root window, it might always show #000000 (Depending 86 | on the Window Manager in use) 87 | 88 | 89 | # ChangeLog 90 | 91 | # v1.0.2 92 | * Was not working properly on Ubuntu Terminal. It was using default Colormap. Do not use default colormap, rather get it from window attributes. 93 | * If could not get XImage from target window, it is probably root window, 94 | so try to grab it from there. 95 | * Added some options 96 | * Color can be grabbed from a specific location 97 | 98 | * Change Copyright to MIT from GNU GPL 99 | 100 | (Apr-10-2018) 101 | 102 | # v1.0.1 103 | * first cut 104 | 105 | (march-16-1997) 106 | 107 | 108 | # License 109 | 110 | MIT 111 | -------------------------------------------------------------------------------- /grabc.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is turned on, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .nr rF 0 58 | .if \n(.g .if rF .nr rF 1 59 | .if (\n(rF:(\n(.g==0)) \{ 60 | . if \nF \{ 61 | . de IX 62 | . tm Index:\\$1\t\\n%\t"\\$2" 63 | .. 64 | . if !\nF==2 \{ 65 | . nr % 0 66 | . nr F 2 67 | . \} 68 | . \} 69 | .\} 70 | .rr rF 71 | .\" 72 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 73 | .\" Fear. Run. Save yourself. No user-serviceable parts. 74 | . \" fudge factors for nroff and troff 75 | .if n \{\ 76 | . ds #H 0 77 | . ds #V .8m 78 | . ds #F .3m 79 | . ds #[ \f1 80 | . ds #] \fP 81 | .\} 82 | .if t \{\ 83 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 84 | . ds #V .6m 85 | . ds #F 0 86 | . ds #[ \& 87 | . ds #] \& 88 | .\} 89 | . \" simple accents for nroff and troff 90 | .if n \{\ 91 | . ds ' \& 92 | . ds ` \& 93 | . ds ^ \& 94 | . ds , \& 95 | . ds ~ ~ 96 | . ds / 97 | .\} 98 | .if t \{\ 99 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 100 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 101 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 102 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 103 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 104 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 105 | .\} 106 | . \" troff and (daisy-wheel) nroff accents 107 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 108 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 109 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 110 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 111 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 112 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 113 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 114 | .ds ae a\h'-(\w'a'u*4/10)'e 115 | .ds Ae A\h'-(\w'A'u*4/10)'E 116 | . \" corrections for vroff 117 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 118 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 119 | . \" for low resolution devices (crt and lpr) 120 | .if \n(.H>23 .if \n(.V>19 \ 121 | \{\ 122 | . ds : e 123 | . ds 8 ss 124 | . ds o a 125 | . ds d- d\h'-1'\(ga 126 | . ds D- D\h'-1'\(hy 127 | . ds th \o'bp' 128 | . ds Th \o'LP' 129 | . ds ae ae 130 | . ds Ae AE 131 | .\} 132 | .rm #[ #] #H #V #F C 133 | .\" ======================================================================== 134 | .\" 135 | .IX Title "GRABC 1" 136 | .TH GRABC 1 "2018-04-16" "perl v5.22.1" "User Contributed Perl Documentation" 137 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 138 | .\" way too many mistakes in technical documents. 139 | .if n .ad l 140 | .nh 141 | .SH "NAME" 142 | grabc \- A tool to identify a pixel color of an X Window. 143 | .SH "SYNOPSIS" 144 | .IX Header "SYNOPSIS" 145 | .Vb 3 146 | \& grabc v1.0.2 147 | \& A program to identify a pixel color of an X Window 148 | \& by muquit@muquit.com https://www.muquit.com/ 149 | \& 150 | \& Usage: grabc [options] 151 | \& Where the options are: 152 | \& \-v \- show version info 153 | \& \-h \- show this usage 154 | \& \-hex \- print pixel value as Hex on stdout 155 | \& \-rgb \- print pixel value as RGB on stderr 156 | \& \-W \- print the Window id at mouse click 157 | \& \-w id \- window id in hex, use \-l +x+y 158 | \& \-l +x+y \- pixel co\-ordinate. requires window id 159 | \& \-d \- show debug messages 160 | \& \-a \- Print all 16 bits of color. Default is high order 8 bits 161 | \& Example: 162 | \& * Print pixel color in hex on stdout: 163 | \& $ grabc 164 | \& * Show usage: 165 | \& $ grabc \-h 166 | \& * Print Window Id (Note the upper case W): 167 | \& $ grabc \-W 168 | \& * Print pixel color of Window iwith id 0x13234 at location 10,20 169 | \& $ grabc \-w 0x13234 \-l +10+20 170 | .Ve 171 | .SH "DESCRIPTION" 172 | .IX Header "DESCRIPTION" 173 | grabc is a simple but very useful program to determine the color string in 174 | hex (or in \s-1RGB\s0 components) by clicking on a pixel on the screen. While web 175 | browsing, lots of time you find a nice color and wonder what color is that. 176 | Well just use grabc! 177 | .PP 178 | When this program is run, the mouse pointer is grabbed and changed to a 179 | cross hair and when the mouse is clicked, the color of the clicked pixel 180 | is written to stdout in hex prefixed with #. 181 | .SH "LICENSE" 182 | .IX Header "LICENSE" 183 | \&\s-1MIT\s0 184 | .SH "AUTHOR" 185 | .IX Header "AUTHOR" 186 | grabc is written by Muhammad Muquit . 187 | Homepage: . 188 | -------------------------------------------------------------------------------- /grabc.c: -------------------------------------------------------------------------------- 1 | /* A program to pick a color by clicking the mouse. 2 | * 3 | * RCS: 4 | * $Revision$ 5 | * $Date$ 6 | * 7 | * Description: 8 | * 9 | * When this program is run, the mouse pointer is grabbed and changed to 10 | * a cross hair and when the mouse is clicked, the color of the clicked 11 | * pixel is written to stdout in hex prefixed with # 12 | * 13 | * This program can be useful when you see a color and want to use the 14 | * color in xterm or your window manager's border but no clue what the 15 | * name of the color is. It's silly to use a image processing software 16 | * to find it out. 17 | * 18 | * Example: 19 | * xterm -bg `grabc` -fg `grabc` (silly but esoteric!) 20 | * 21 | * Development History: 22 | * who when why 23 | * ma_muquit@fccc.edu march-16-1997 first cut 24 | * muquit@muquit.com Apr-10-2018 Do not use default colormap, 25 | * rather get it from window attributes. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #ifndef True 50 | #define True 1 51 | #endif 52 | 53 | #ifndef False 54 | #define False 0 55 | #endif 56 | 57 | #define VERSION_S "1.0.2" 58 | 59 | static int g_debug = False; 60 | static int g_print_in_hex = True; 61 | static int g_print_in_rgb = False; 62 | static int g_print_all_16_bits = False; 63 | static Window g_window_id = (Window) NULL; 64 | static int g_loc_specified = False; 65 | static int g_x = 1; 66 | static int g_y = 1; 67 | static unsigned int g_width = 0; 68 | static unsigned int g_height = 0; 69 | static Cursor g_cross_cursor=(Cursor) NULL; 70 | 71 | /* private function prototypes */ 72 | static Window select_window (Display *,int *x,int *y); 73 | 74 | static Window findSubWindow(Display *display,Window top_winodw, 75 | Window window_to_check,int *x,int *y); 76 | 77 | static Window get_window_color(Display *display,XColor *color); 78 | static int MXError(Display *display,XErrorEvent *error); 79 | 80 | static void show_usage(void) 81 | { 82 | char 83 | **p; 84 | 85 | static char *options[]= 86 | { 87 | " -v - show version info", 88 | " -h - show this usage", 89 | " -hex - print pixel value as Hex on stdout", 90 | " -rgb - print pixel value as RGB on stderr", 91 | " -W - print the Window id at mouse click", 92 | " -w id - window id in hex, use -l +x+y", 93 | " -l +x+y - pixel co-ordinate. requires window id", 94 | " -d - show debug messages", 95 | " -a - Print all 16 bits RGB components of color", 96 | " Default is high order 8 bits of components", 97 | "Example:", 98 | "* Print pixel color in hex on stdout:", 99 | " $ grabc", 100 | "* Show usage:", 101 | " $ grabc -h", 102 | "* Print Window Id (Note the upper case W):", 103 | " $ grabc -W", 104 | "* Print pixel color of Window iwith id 0x13234 at location 10,20", 105 | " $ grabc -w 0x13234 -l +10+20", 106 | (char *) NULL 107 | 108 | }; 109 | 110 | (void) printf("\n"); 111 | (void) printf("grabc v%s\n",VERSION_S); 112 | (void) printf("A program to identify a pixel color of an X Window\n"); 113 | (void) printf("by muquit@muquit.com https://www.muquit.com/\n\n"); 114 | (void) printf("Usage: grabc [options]\n"); 115 | (void) printf("Where the options are:\n"); 116 | for (p=options; *p != NULL; p++) 117 | { 118 | (void) fprintf(stdout,"%s\n",*p); 119 | (void) fflush(stdout); 120 | } 121 | } 122 | 123 | 124 | static void log_debug(const char *fmt,...) 125 | { 126 | va_list 127 | args; 128 | if (!g_debug) 129 | { 130 | return; 131 | } 132 | va_start(args, fmt); 133 | (void) fprintf(stderr,"[Debug]: "); 134 | vfprintf(stderr,fmt,args); 135 | (void) fprintf(stderr,"\n"); 136 | va_end(args); 137 | } 138 | 139 | static Cursor get_cross_cursor(Display *display) 140 | { 141 | if (g_cross_cursor == (Cursor) NULL) 142 | { 143 | g_cross_cursor=XCreateFontCursor(display,XC_tcross); 144 | if (g_cross_cursor == (Cursor) NULL) 145 | { 146 | (void) fprintf (stderr,"ERROR: Failed to create Cross Cursor!\n"); 147 | exit(1); 148 | } 149 | } 150 | return g_cross_cursor; 151 | } 152 | static Window grab_mouse(Display *display,Window root_window) 153 | { 154 | int 155 | status; 156 | 157 | Window 158 | subwindow; 159 | 160 | XEvent 161 | event; 162 | 163 | Cursor 164 | target_cursor; 165 | 166 | 167 | if (g_window_id != (Window) NULL) 168 | { 169 | return g_window_id; 170 | } 171 | 172 | target_cursor = get_cross_cursor(display); 173 | status=XGrabPointer(display,root_window,False, 174 | (unsigned int) ButtonPressMask,GrabModeSync, 175 | GrabModeAsync,root_window,target_cursor,CurrentTime); 176 | if (status == GrabSuccess) 177 | { 178 | XAllowEvents(display,SyncPointer,CurrentTime); 179 | XWindowEvent(display,root_window,ButtonPressMask,&event); 180 | subwindow = event.xbutton.subwindow; 181 | } 182 | else 183 | { 184 | return root_window; 185 | } 186 | 187 | return subwindow; 188 | } 189 | static void upgrab_mouse(Display *display) 190 | { 191 | if (g_window_id != (Window) NULL) 192 | { 193 | XUngrabPointer(display,CurrentTime); 194 | } 195 | } 196 | 197 | 198 | 199 | 200 | 201 | /* 202 | ** function to select a window 203 | ** output parameters: x,y (coordinate of the point of click) 204 | ** reutrns Window 205 | ** exits if mouse can not be grabbed 206 | */ 207 | static Window select_window(Display *display,int *x,int *y) 208 | { 209 | Cursor 210 | target_cursor; 211 | 212 | int 213 | status; 214 | 215 | Window 216 | target_window, 217 | root_window; 218 | 219 | XEvent 220 | event; 221 | 222 | /* 223 | ** If window id and location is specified return the window id as 224 | ** target window. Also initilaize x, y those specified with -l 225 | */ 226 | if ((g_window_id != (Window) NULL) && g_loc_specified) 227 | { 228 | log_debug("Returning passing window: %lx",g_window_id); 229 | (*x) = g_x; 230 | (*y) = g_y; 231 | return g_window_id; 232 | } 233 | target_window=(Window) NULL; 234 | target_cursor = get_cross_cursor(display); 235 | root_window=XRootWindow(display,XDefaultScreen(display)); 236 | // log_debug("Root Window ID: 0x%08lx",root_window); 237 | 238 | status=XGrabPointer(display,root_window,False, 239 | (unsigned int) ButtonPressMask,GrabModeSync, 240 | GrabModeAsync,root_window,target_cursor,CurrentTime); 241 | if (status == GrabSuccess) 242 | { 243 | XAllowEvents(display,SyncPointer,CurrentTime); 244 | XWindowEvent(display,root_window,ButtonPressMask,&event); 245 | Window subwindow = event.xbutton.subwindow; 246 | 247 | if (event.type == ButtonPress) 248 | { 249 | target_window=findSubWindow(display,root_window, 250 | subwindow, 251 | &event.xbutton.x, 252 | &event.xbutton.y ); 253 | 254 | if (target_window == (Window) NULL) 255 | { 256 | (void) fprintf (stderr, 257 | "ERROR: Failed to get target window, getting root window!\n"); 258 | target_window=root_window; 259 | } 260 | if (!g_loc_specified) 261 | { 262 | XUngrabPointer(display,CurrentTime); 263 | } 264 | } 265 | 266 | } 267 | else 268 | { 269 | (void) fprintf (stderr,"ERROR: Failed to grab mouse pointer!\n"); 270 | exit(1); 271 | } 272 | 273 | /* free things we do not need, always a good practice */ 274 | (*x)=event.xbutton.x; 275 | (*y)=event.xbutton.y; 276 | 277 | return (target_window); 278 | } 279 | 280 | /* find a window */ 281 | static Window findSubWindow(Display *display,Window top_window, 282 | Window window_to_check,int *x,int *y) 283 | { 284 | int 285 | newx, 286 | newy; 287 | 288 | Window 289 | window; 290 | 291 | if (top_window == (Window) NULL) 292 | return ((Window) NULL); 293 | 294 | if (window_to_check == (Window) NULL) 295 | return ((Window) NULL); 296 | 297 | /* initialize automatics */ 298 | window=window_to_check; 299 | 300 | while ((XTranslateCoordinates(display,top_window,window_to_check, 301 | *x,*y,&newx,&newy,&window) != 0) && 302 | (window != (Window) NULL)) 303 | { 304 | if (window != (Window) NULL) 305 | { 306 | top_window=window_to_check; 307 | window_to_check=window; 308 | (*x)=newx; 309 | (*y)=newy; 310 | } 311 | } 312 | 313 | if (window == (Window) NULL) 314 | window=window_to_check; 315 | 316 | 317 | (*x)=newx; 318 | (*y)=newy; 319 | 320 | return (window); 321 | } 322 | 323 | /* 324 | * get the color of the pixel of the point of mouse click 325 | * output paramter: XColor *color 326 | * 327 | * returns 328 | * target Window on success 329 | * NULL on failure 330 | * 331 | */ 332 | 333 | static Window get_window_color(Display *display,XColor *color) 334 | { 335 | Window 336 | root_window, 337 | target_window; 338 | 339 | XImage 340 | *ximage; 341 | 342 | int 343 | x, 344 | y; 345 | 346 | Status 347 | status; 348 | 349 | root_window=XRootWindow(display,XDefaultScreen(display)); 350 | target_window=select_window(display,&x,&y); 351 | 352 | log_debug(" Root Window Id: 0x%08lx",root_window); 353 | log_debug("Target Window Id: 0x%08lx X,Y: +%d+%d",target_window,x,y); 354 | 355 | if (target_window == (Window) NULL) 356 | return (Window) NULL; 357 | 358 | ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap); 359 | if (ximage == (XImage *) NULL) 360 | { 361 | /* Try root window */ 362 | log_debug("Could not get XImage from Window: 0x%08lx",target_window); 363 | log_debug("Trying to get XImage from root window: 0x%08lx",root_window); 364 | ximage=XGetImage(display,root_window,x,y,1,1,AllPlanes,ZPixmap); 365 | if (ximage == (XImage *) NULL) 366 | { 367 | log_debug("Could not get XImage from target or root window"); 368 | return (Window) NULL; 369 | } 370 | else 371 | { 372 | log_debug("OK successfully got XImage from root window"); 373 | target_window = root_window; 374 | } 375 | 376 | } 377 | 378 | color->pixel=XGetPixel(ximage,0,0); 379 | XDestroyImage(ximage); 380 | 381 | return (target_window); 382 | } 383 | 384 | /* forgiving X error handler */ 385 | 386 | static int MXError (Display *display, XErrorEvent *error) 387 | { 388 | int 389 | xerrcode; 390 | 391 | xerrcode = error->error_code; 392 | 393 | if (xerrcode == BadAlloc || 394 | (xerrcode == BadAccess && error->request_code==88)) 395 | { 396 | return (False); 397 | } 398 | else 399 | { 400 | switch (error->request_code) 401 | { 402 | case X_GetGeometry: 403 | { 404 | if (error->error_code == BadDrawable) 405 | return (False); 406 | break; 407 | } 408 | 409 | case X_GetWindowAttributes: 410 | case X_QueryTree: 411 | { 412 | if (error->error_code == BadWindow) 413 | return (False); 414 | break; 415 | } 416 | 417 | case X_QueryColors: 418 | { 419 | if (error->error_code == BadValue) 420 | return(False); 421 | break; 422 | } 423 | } 424 | } 425 | return (True); 426 | } 427 | 428 | int main(int argc,char **argv) 429 | { 430 | Display 431 | *display; 432 | 433 | int 434 | x, 435 | y, 436 | status; 437 | 438 | XColor 439 | color; 440 | 441 | int 442 | rc, 443 | i, 444 | r, 445 | g, 446 | b; 447 | 448 | Window 449 | window_id, 450 | target_window; 451 | 452 | XWindowAttributes 453 | window_attributes; 454 | 455 | char 456 | *option; 457 | 458 | for (i=1; i < argc; i++) 459 | { 460 | option = argv[i]; 461 | switch(*(option+1)) 462 | { 463 | case 'a': 464 | { 465 | g_print_all_16_bits = True; 466 | break; 467 | } 468 | case 'd': 469 | { 470 | g_debug = True; 471 | break; 472 | } 473 | 474 | case 'h': 475 | { 476 | if (strncmp("hex",option+1,3) == 0) 477 | { 478 | g_print_in_hex = True; 479 | } 480 | else 481 | { 482 | show_usage(); 483 | return(1); 484 | } 485 | break; 486 | } 487 | 488 | case 'r': 489 | { 490 | if (strncmp("rgb",option+1,3) == 0) 491 | { 492 | g_print_in_rgb = True; 493 | } 494 | break; 495 | } 496 | 497 | case 'w': 498 | { 499 | if (*option == '-') 500 | { 501 | i++; 502 | if (i == argc) 503 | { 504 | (void) fprintf(stderr,"ERROR: Missing Window id\n"); 505 | return(1); 506 | } 507 | } 508 | g_window_id = (Window) strtol(argv[i],NULL, 16); 509 | break; 510 | } 511 | case 'W': 512 | { 513 | display=XOpenDisplay((char *) NULL); 514 | if (display == NULL) 515 | { 516 | (void) fprintf(stderr,"ERROR: Could not open Display\n"); 517 | return(1); 518 | } 519 | Window window = select_window(display, &x, &y); 520 | if (window != (Window) NULL) 521 | { 522 | log_debug("Window ID: 0x%08lx",window); 523 | (void) fprintf(stdout,"0x%lx\n",window); 524 | } 525 | return(1); 526 | break; 527 | } 528 | 529 | case 'l': 530 | { 531 | if (*option == '-') 532 | { 533 | i++; 534 | if (i == argc) 535 | { 536 | (void) fprintf(stderr,"ERROR: Missing location +x+y\n"); 537 | return(1); 538 | } 539 | } 540 | rc = XParseGeometry(argv[i], &g_x,&g_y,&g_width,&g_height); 541 | if (rc == 0) 542 | { 543 | (void) fprintf(stderr,"ERROR: Could not parse location: %s\n",argv[i]); 544 | (void) fprintf(stderr,"Example: -l +10+20\n"); 545 | return(1); 546 | } 547 | g_loc_specified = True; 548 | 549 | break; 550 | } 551 | 552 | case 'v': 553 | { 554 | (void) fprintf(stderr,"grabc v%s\n",VERSION_S); 555 | return(1); 556 | break; 557 | } 558 | 559 | default: 560 | { 561 | break; 562 | } 563 | } 564 | } 565 | 566 | if (g_loc_specified && (g_window_id == (Window) NULL)) 567 | { 568 | (void) fprintf(stderr,"ERROR: Please specify window id with -w in hex to use this option\n"); 569 | (void) fprintf(stderr,"Use -W option to find the Window Id\n"); 570 | return(1); 571 | } 572 | 573 | display=XOpenDisplay((char *) NULL); 574 | XSetErrorHandler(MXError); 575 | 576 | if (display == (Display *) NULL) 577 | { 578 | (void) fprintf (stderr,"ERROR: Failed to open DISPLAY!\n"); 579 | exit(1); 580 | } 581 | 582 | target_window = get_window_color(display,&color); 583 | if (target_window != (Window) NULL) 584 | { 585 | status = XGetWindowAttributes(display, target_window, 586 | &window_attributes); 587 | if (status == False || window_attributes.map_state != IsViewable) 588 | { 589 | (void) fprintf(stderr,"ERROR: Could not get Window Attributes\n"); 590 | return(1); 591 | } 592 | XQueryColor(display, window_attributes.colormap, &color); 593 | if (g_print_all_16_bits) 594 | { 595 | (void) fprintf(stdout,"#%04x%04x%04x\n", 596 | (unsigned int)color.red, 597 | (unsigned int) color.green, 598 | (unsigned int) color.blue); 599 | (void) fflush(stdout); 600 | if (g_print_in_rgb) 601 | { 602 | (void) fprintf(stderr,"%d,%d,%d\n", 603 | (unsigned int)color.red, 604 | (unsigned int) color.green, 605 | (unsigned int) color.blue); 606 | } 607 | 608 | } 609 | else 610 | { 611 | r=(color.red >> 8); 612 | g=(color.green >> 8); 613 | b=(color.blue >> 8); 614 | log_debug("Color: #%02x%02x%02x",r,g,b); 615 | (void) fprintf (stdout,"#%02x%02x%02x\n",r,g,b); 616 | (void) fflush(stdout); 617 | /* 618 | ** write the values in decimal on stderr 619 | */ 620 | if (g_print_in_rgb) 621 | { 622 | (void) fprintf(stderr,"%d,%d,%d\n",r,g,b); 623 | } 624 | } 625 | } 626 | else 627 | { 628 | (void) fprintf (stderr,"ERROR: Failed to grab color!\n"); 629 | } 630 | return (0); 631 | } 632 | -------------------------------------------------------------------------------- /grabc.pod: -------------------------------------------------------------------------------- 1 | =head1 NAME 2 | 3 | grabc - A tool to identify a pixel color of an X Window. 4 | 5 | =head1 SYNOPSIS 6 | 7 | grabc v1.0.2 8 | A program to identify a pixel color of an X Window 9 | by muquit@muquit.com https://www.muquit.com/ 10 | 11 | Usage: grabc [options] 12 | Where the options are: 13 | -v - show version info 14 | -h - show this usage 15 | -hex - print pixel value as Hex on stdout 16 | -rgb - print pixel value as RGB on stderr 17 | -W - print the Window id at mouse click 18 | -w id - window id in hex, use -l +x+y 19 | -l +x+y - pixel co-ordinate. requires window id 20 | -d - show debug messages 21 | -a - Print all 16 bits of color. Default is high order 8 bits 22 | Example: 23 | * Print pixel color in hex on stdout: 24 | $ grabc 25 | * Show usage: 26 | $ grabc -h 27 | * Print Window Id (Note the upper case W): 28 | $ grabc -W 29 | * Print pixel color of Window iwith id 0x13234 at location 10,20 30 | $ grabc -w 0x13234 -l +10+20 31 | 32 | =head1 DESCRIPTION 33 | 34 | grabc is a simple but very useful program to determine the color string in 35 | hex (or in RGB components) by clicking on a pixel on the screen. While web 36 | browsing, lots of time you find a nice color and wonder what color is that. 37 | Well just use grabc! 38 | 39 | When this program is run, the mouse pointer is grabbed and changed to a 40 | cross hair and when the mouse is clicked, the color of the clicked pixel 41 | is written to stdout in hex prefixed with #. 42 | 43 | =head1 LICENSE 44 | 45 | MIT 46 | 47 | =head1 AUTHOR 48 | 49 | grabc is written by Muhammad Muquit Emuquit@muquit.comE. 50 | Homepage: L. 51 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | true 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | else 122 | instcmd=mkdir 123 | fi 124 | else 125 | 126 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 127 | # might cause directories to be created, which would be especially bad 128 | # if $src (and thus $dsttmp) contains '*'. 129 | 130 | if [ -f $src -o -d $src ] 131 | then 132 | true 133 | else 134 | echo "install: $src does not exist" 135 | exit 1 136 | fi 137 | 138 | if [ x"$dst" = x ] 139 | then 140 | echo "install: no destination specified" 141 | exit 1 142 | else 143 | true 144 | fi 145 | 146 | # If destination is a directory, append the input filename; if your system 147 | # does not like double slashes in filenames, you may need to add some logic 148 | 149 | if [ -d $dst ] 150 | then 151 | dst="$dst"/`basename $src` 152 | else 153 | true 154 | fi 155 | fi 156 | 157 | ## this sed command emulates the dirname command 158 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 159 | 160 | # Make sure that the destination directory exists. 161 | # this part is taken from Noah Friedman's mkinstalldirs script 162 | 163 | # Skip lots of stat calls in the usual case. 164 | if [ ! -d "$dstdir" ]; then 165 | defaultIFS=' 166 | ' 167 | IFS="${IFS-${defaultIFS}}" 168 | 169 | oIFS="${IFS}" 170 | # Some sh's can't handle IFS=/ for some reason. 171 | IFS='%' 172 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 173 | IFS="${oIFS}" 174 | 175 | pathcomp='' 176 | 177 | while [ $# -ne 0 ] ; do 178 | pathcomp="${pathcomp}${1}" 179 | shift 180 | 181 | if [ ! -d "${pathcomp}" ] ; 182 | then 183 | $mkdirprog "${pathcomp}" 184 | else 185 | true 186 | fi 187 | 188 | pathcomp="${pathcomp}/" 189 | done 190 | fi 191 | 192 | if [ x"$dir_arg" != x ] 193 | then 194 | $doit $instcmd $dst && 195 | 196 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 197 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 198 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 199 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 200 | else 201 | 202 | # If we're going to rename the final executable, determine the name now. 203 | 204 | if [ x"$transformarg" = x ] 205 | then 206 | dstfile=`basename $dst` 207 | else 208 | dstfile=`basename $dst $transformbasename | 209 | sed $transformarg`$transformbasename 210 | fi 211 | 212 | # don't allow the sed command to completely eliminate the filename 213 | 214 | if [ x"$dstfile" = x ] 215 | then 216 | dstfile=`basename $dst` 217 | else 218 | true 219 | fi 220 | 221 | # Make a temp file name in the proper directory. 222 | 223 | dsttmp=$dstdir/#inst.$$# 224 | 225 | # Move or copy the file name to the temp name 226 | 227 | $doit $instcmd $src $dsttmp && 228 | 229 | trap "rm -f ${dsttmp}" 0 && 230 | 231 | # and set any options; do chmod last to preserve setuid bits 232 | 233 | # If any of these fail, we abort the whole thing. If we want to 234 | # ignore errors from any of these, just make sure not to ignore 235 | # errors from the above "$doit $instcmd $src $dsttmp" command. 236 | 237 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 238 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 239 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 240 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 241 | 242 | # Now rename the file to the real destination. 243 | 244 | $doit $rmcmd -f $dstdir/$dstfile && 245 | $doit $mvcmd $dsttmp $dstdir/$dstfile 246 | 247 | fi && 248 | 249 | 250 | exit 0 251 | -------------------------------------------------------------------------------- /mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | # $Id: mkinstalldirs,v 1.1 2000/09/20 19:05:51 gson Exp $ 8 | 9 | errstatus=0 10 | 11 | for file 12 | do 13 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 14 | shift 15 | 16 | pathcomp= 17 | for d 18 | do 19 | pathcomp="$pathcomp$d" 20 | case "$pathcomp" in 21 | -* ) pathcomp=./$pathcomp ;; 22 | esac 23 | 24 | if test ! -d "$pathcomp"; then 25 | echo "mkdir $pathcomp" 1>&2 26 | 27 | mkdir "$pathcomp" || lasterr=$? 28 | 29 | if test ! -d "$pathcomp"; then 30 | errstatus=$lasterr 31 | fi 32 | fi 33 | 34 | pathcomp="$pathcomp/" 35 | done 36 | done 37 | 38 | exit $errstatus 39 | 40 | # mkinstalldirs ends here 41 | --------------------------------------------------------------------------------