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 (&current_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