transSet.c revision f33d31a3
1/* Copyright © 2003-2004 Matthew Hawn 2 * Copyright © 2003-2004 Andreas Kohn 3 * Copyright © 2003-2004 Roman Divacky 4 * Copyright © 2003-2004 Keith Packard 5 * Copyright © 2005-2007 Daniel Forchheimer 6 * Copyright © 2011-2012 Arnaud Fontaine 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28#ifdef HAVE_CONFIG_H 29# include "config.h" 30#endif 31 32#define VERSIONSTR "6" 33 34#include <stdio.h> 35#include <X11/Xlib.h> 36#include <X11/Xatom.h> 37#include "dsimple.h" 38#include <stdlib.h> 39#include <getopt.h> 40#include <string.h> 41#include <sys/types.h> 42 43Window target_win; 44 45/* needed by dsimple.c */ 46 47void 48Usage (void) 49{ 50 fputs ("usage: transset [-options ...] [opacity]\n" 51 "options:\n" 52 " -h, --help display this message\n" 53 " -t, --toggle force toggle of opacity\n" 54 " -c, --click select by clicking on window (default)\n" 55 " -p, --point select the window currently under the cursor\n" 56 " -a, --actual select the actual window\n" 57 " -n, --name NAME select by name, NAME is matched as regular expression\n" 58 " --no-regex don't use regular expression for matching name\n" 59 " -i, --id select by window id\n" 60 " --inc increase by the given opacity\n" 61 " --dec decrease by given opacity\n" 62 " -m, --min OPACITY minimum possible opacity (default = 0)\n" 63 " -x, --max OPACITY maximum possible opacity (default = 1)\n" 64 " -v, --verbose print some debug info\n" 65 " -V, --version print version number\n", 66 stderr); 67 68 exit (1); 69} 70 71#define OPAQUE 0xffffffff 72#define OPACITY "_NET_WM_WINDOW_OPACITY" 73 74/* returns the highest parent of child that is not the root-window */ 75static Window 76Get_Top_Window (Display *disp, Window child) { 77 Window parent; 78 Window root; 79 Window *child_list; 80 unsigned int num_children; 81 82 if (!XQueryTree (disp, child, &root, &parent, &child_list, 83 &num_children)) 84 Fatal_Error ("Can't query window tree."); 85 86 XFree ((void *) child_list); 87 if (parent == root) 88 return child; 89 90 while (parent != root) { 91 child = parent; 92 if (!XQueryTree (disp, child, &root, &parent, &child_list, 93 &num_children)) 94 Fatal_Error ("Can't query window tree."); 95 XFree ((void *) child_list); 96 } 97 return child; 98} 99 100static Window 101Get_Actual_Window (Display *disp) 102{ 103 int i; 104 Window w; 105 106 XGetInputFocus (disp, &w, &i); 107 return Get_Top_Window (disp, w); 108} 109 110typedef enum { 111 SELECT_METHOD_CLICK = 0, 112 SELECT_METHOD_WINDOW_UNDER_CURSOR = 1, 113 SELECT_METHOD_WINDOW_ID = 2, 114 SELECT_METHOD_WINDOW_NAME = 3, 115 SELECT_METHOD_FOCUSED_WINDOW = 4 116} select_method_t; 117 118int 119main (int argc, char **argv) 120{ 121 Bool gotd = False; 122 double d = 0.75; 123 unsigned int opacity; 124 unsigned int current_opacity; 125 select_method_t select_method = SELECT_METHOD_CLICK; 126 Bool flag_toggle = False; 127 Bool flag_increase = False; 128 Bool flag_decrease = False; 129 Bool flag_verbose = False; 130 Bool flag_no_regex = False; 131 int o; 132 double min = 0.0, max = 1.0; 133 char *idstr = NULL, *namestr = NULL; 134 char *windowname = NULL; 135 136 int options_index = 0; 137 static struct option long_options[] = { 138 {"toggle", 0, NULL, 't'}, 139 {"help", 0, NULL, 'h'}, 140 {"point", 0, NULL, 'p'}, 141 {"actual", 0, NULL, 'a'}, 142 {"click", 0, NULL, 'c'}, 143 {"id", 1, NULL, 'i'}, 144 {"name", 1, NULL, 'n'}, 145 {"inc", 0, NULL, '1'}, 146 {"dec", 0, NULL, '2'}, 147 {"min", 1, NULL, 'm'}, 148 {"max", 1, NULL, 'x'}, 149 {"no-regex", 0, NULL, '4'}, 150 {"version", 0, NULL, 'V'}, 151 {"verbose", 0, NULL, 'v'}, 152 {0, 0, 0, 0} 153 }; 154 unsigned char *data; 155 156 Atom actual; 157 int format; 158 unsigned long n, left; 159 160 /* wonderful utility */ 161 Setup_Display_And_Screen (&argc, argv); 162 163 /* parse arguments */ 164 while ((o = getopt_long (argc, argv, "thapci:n:vVm:x:123", 165 long_options, &options_index)) != -1) { 166 switch (o) { 167 case 't': 168 flag_toggle = True; 169 break; 170 case 'h': 171 Usage (); 172 break; 173 case 'c': 174 select_method = SELECT_METHOD_CLICK; 175 break; 176 case 'p': 177 select_method = SELECT_METHOD_WINDOW_UNDER_CURSOR; 178 break; 179 case 'i': 180 idstr = optarg; 181 select_method = SELECT_METHOD_WINDOW_ID; 182 break; 183 case 'n': 184 namestr = optarg; 185 select_method = SELECT_METHOD_WINDOW_NAME; 186 break; 187 case 'a': 188 select_method = SELECT_METHOD_FOCUSED_WINDOW; 189 break; 190 case '1': 191 flag_increase = True; 192 break; 193 case '2': 194 flag_decrease = True; 195 break; 196 case 'v': 197 flag_verbose = True; 198 break; 199 case '4': 200 flag_no_regex = True; 201 break; 202 case 'm': 203 min = atof (optarg); 204 break; 205 case 'x': 206 max = atof (optarg); 207 break; 208 case 'V': 209 fprintf (stderr, "%s\nversion: %s\nreleased: %s\n", 210 PACKAGE_STRING, VERSIONSTR, RELEASE_DATE); 211 exit (1); 212 break; 213 default: 214 Usage (); 215 } 216 } 217 218 if (optind < argc) { 219 d = atof (argv[optind]); 220 gotd = True; 221 } 222 223 /* select the window to make transparent */ 224 switch (select_method) { 225 case SELECT_METHOD_WINDOW_UNDER_CURSOR: 226 /* don't wait for click */ 227 if (flag_verbose) 228 printf ("Selecting window by click\n"); 229 target_win = Get_Window_Under_Cursor (dpy); 230 break; 231 232 case SELECT_METHOD_WINDOW_ID: 233 /* pretty much ripped from dsimple.c */ 234 if (flag_verbose) 235 printf ("Selecting window by id\n"); 236 sscanf (idstr, "0x%lx", &target_win); 237 if (!target_win) 238 sscanf (idstr, "%ld", &target_win); 239 if (!target_win) { 240 fprintf (stderr, "Invalid window id format: %s.\n", idstr); 241 XCloseDisplay (dpy); 242 return 1; 243 } 244 if (flag_verbose) 245 printf ("Selected 0x%x, trying to get top parent ... ", 246 (unsigned int) target_win); 247 target_win = Get_Top_Window (dpy, target_win); 248 if (flag_verbose) 249 printf ("found 0x%x\n", (unsigned int) target_win); 250 251 break; 252 253 case SELECT_METHOD_WINDOW_NAME: 254 /* select by name, pretty much ripped from dsimple.c */ 255 if (flag_verbose) 256 printf ("Selecting window by name\n"); 257 258 if (flag_no_regex) 259 target_win = Window_With_Name (dpy, RootWindow (dpy, screen), 260 namestr); 261 else 262 target_win = Window_With_Name_Regex (dpy, RootWindow (dpy, screen), 263 namestr); 264 265 if (!target_win) { 266 fprintf (stderr, "No window matching %s exists!\n", namestr); 267 XCloseDisplay (dpy); 268 return 1; 269 } 270 /* store the matched window name*/ 271 XFetchName (dpy, target_win, &windowname); 272 273 if (flag_verbose) 274 printf ("Selected 0x%x, trying to get top parent ... ", 275 (unsigned int) target_win); 276 277 target_win = Get_Top_Window (dpy, target_win); 278 if (flag_verbose) 279 printf ("found 0x%x\n", (unsigned int) target_win); 280 281 break; 282 283 case SELECT_METHOD_FOCUSED_WINDOW: 284 target_win = Get_Actual_Window (dpy); 285 break; 286 287 default: 288 /* grab mouse and return window that is next clicked */ 289 target_win = Select_Window (dpy); 290 break; 291 } 292 293 /* get property */ 294 if ((XGetWindowProperty (dpy, target_win, XInternAtom (dpy, OPACITY, False), 295 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, 296 &left, &data) == Success) 297 && (data != None)) { 298 memcpy (¤t_opacity, data, sizeof (unsigned int)); 299 XFree ((void *) data); 300 if (flag_verbose) 301 printf ("Found transparency: %g\n", 302 (double) current_opacity / OPAQUE); 303 } else 304 current_opacity = OPAQUE; 305 306 if (flag_increase) 307 d = (double) current_opacity / OPAQUE + d; 308 else if (flag_decrease) 309 d = (double) current_opacity / OPAQUE - d; 310 311 /* check min and max */ 312 if (d < min) 313 d = min; 314 if (d > max) 315 d = max; 316 317 opacity = (unsigned int) (d * OPAQUE); 318 319 /* for user-compatibility with transset */ 320 if (!gotd) 321 flag_toggle = True; 322 323 /* toggle */ 324 if (flag_toggle) 325 if (current_opacity != OPAQUE) 326 opacity = OPAQUE; 327 328 if (opacity == OPAQUE) 329 XDeleteProperty (dpy, target_win, XInternAtom (dpy, OPACITY, False)); 330 /* set it */ 331 else 332 XChangeProperty (dpy, target_win, XInternAtom (dpy, OPACITY, False), 333 XA_CARDINAL, 32, PropModeReplace, 334 (unsigned char *) &opacity, 1L); 335 XSync (dpy, False); 336 337 printf ("Set Property to %g", (double) opacity / OPAQUE); 338 if (windowname) 339 printf (" on \n%s\n", windowname); 340 else 341 printf ("\n"); 342 343 if (flag_verbose) 344 printf ("Property set on: 0x%x\n", (unsigned int) target_win); 345 346 XCloseDisplay (dpy); 347 return 0; 348} 349