xqueryptr.c: Add new program to interrogate the pointer position.
[xtoys] / xrepaint.c
CommitLineData
dd6d43a6
MW
1/* -*-c-*-
2 *
3 * Redraw the screen in case it's been trashed somehow
4 *
5 * (c) 2016 Straylight/Edgeware
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the Edgeware X tools collection.
11 *
12 * X tools is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * X tools is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with X tools; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27/*----- Header files ------------------------------------------------------*/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <sys/time.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37#include <X11/Xlib.h>
38
69353127 39#include <mLib/alloc.h>
dd6d43a6
MW
40#include <mLib/mdwopt.h>
41#include <mLib/quis.h>
42#include <mLib/report.h>
43
44/*----- Global variables --------------------------------------------------*/
45
46static Display *dpy;
47
48/*----- Main code ---------------------------------------------------------*/
49
50static void version(FILE *fp)
51 { pquis(fp, "$ (xtoys version " VERSION ")\n"); }
52
53static void usage(FILE *fp)
54 { pquis(fp, "Usage: $ [-as] [-d display]\n"); }
55
56static void help(FILE *fp)
57{
58 version(fp);
59 fputc('\n', fp);
60 usage(stdout);
61 fputs("\n\
62Repaint the X display (or just one screen).\n\
63\n\
64Options:\n\
65\n\
66-h, --help Display this help text\n\
67-u, --usage Display a short usage summary\n\
68-v, --version Display the program's version number\n\
69\n\
70-a, --all Repaint all of the screens on the display\n\
71-d, --display=DISPLAY Choose X display to connect to\n\
72-s, --screen Only repaint the selected screen\n",
73 fp);
74}
75
69353127 76static Window cover_screen(Screen *sc)
dd6d43a6 77{
69353127 78 /* Make, map, and return a window completely covering the screen SC. */
dd6d43a6
MW
79
80 Window w;
81 XSetWindowAttributes attr;
dd6d43a6
MW
82
83 attr.background_pixel = 0;
c3d5f88d
MW
84 attr.event_mask =
85 StructureNotifyMask | VisibilityChangeMask | ExposureMask |
86 KeyPressMask | ButtonPressMask;
dd6d43a6
MW
87 attr.override_redirect = True;
88 w = XCreateWindow(dpy, RootWindowOfScreen(sc),
89 0, 0, WidthOfScreen(sc), HeightOfScreen(sc),
90 0, CopyFromParent, InputOutput,
91 DefaultVisualOfScreen(sc),
92 CWBackPixel | CWEventMask | CWOverrideRedirect, &attr);
93 XMapWindow(dpy, w);
69353127 94 return (w);
dd6d43a6
MW
95}
96
97int main(int argc, char *argv[])
98{
99 const char *display = 0;
100 unsigned f = 0;
101 struct timeval tv;
69353127
MW
102 XEvent ev;
103 Window *win, w;
104 int i, n;
dd6d43a6
MW
105
106#define f_only 1u
107#define f_bogus 2u
108
109 /* Parse command line options. */
110 ego(argv[0]);
111 for (;;) {
112 static struct option opt[] = {
113 { "help", 0, 0, 'h' },
114 { "usage", 0, 0, 'u' },
115 { "version", 0, 0, 'v' },
116 { "all", 0, 0, 'a' },
117 { "display", OPTF_ARGREQ, 0, 'd' },
118 { "screen", 0, 0, 's' },
119 { 0, 0, 0, 0 }
120 };
121 int i = getopt_long(argc, argv, "huv" "ad:s", opt, 0);
122 if (i < 0) break;
123 switch (i) {
124 case 'h': help(stdout); exit(0); break;
125 case 'u': usage(stdout); exit(0); break;
126 case 'v': version(stdout); exit(0); break;
127 case 'a': f &= ~f_only; break;
128 case 'd': display = optarg; break;
129 case 's': f |= f_only; break;
130 default: f |= f_bogus; break;
131 }
132 }
133 if (optind < argc) f |= f_bogus;
134 if (f & f_bogus) { usage(stderr); exit(EXIT_FAILURE); }
135
136 /* Open the display. */
137 dpy = XOpenDisplay(display);
138 if (!dpy) { die(EXIT_FAILURE, "couldn't open display"); }
139
69353127
MW
140 /* Annoyingly, `XClearWindow' uses `ClipByChildren' semantics, and there's
141 * no way to change that. The best idea I can come up with is to drop
142 * windows over the top of each screen and take them away again. The
143 * latter part is easy because they'll disappear when we close the
144 * display.
145 *
146 * Start by making and mapping the windows.
147 */
148 n = f&f_only ? 1 : ScreenCount(dpy);
149 win = xmalloc(n*sizeof(Window));
150 if (f&f_only)
151 win[0] = cover_screen(DefaultScreenOfDisplay(dpy));
152 else for (i = 0; i < n; i++)
153 win[i] = cover_screen(ScreenOfDisplay(dpy, i));
154
155 /* Now we wait until they're all obviously mapped. */
156 while (n) {
157 XNextEvent(dpy, &ev);
158 switch (ev.type) {
88e87d2a
MW
159 case MapNotify:
160 w = ev.xmap.window; goto window_visible;
161 case VisibilityNotify: case Expose: case KeyPress: case ButtonPress:
69353127
MW
162 w = ev.xany.window; goto window_visible;
163 window_visible:
164 for (i = 0; i < n; i++)
165 if (w == win[i]) { win[i] = win[--n]; break; }
166 break;
167 }
dd6d43a6
MW
168 }
169
69353127 170 /* Finally, we must wait for a bit longer. This is an awful hack. */
dd6d43a6
MW
171 tv.tv_sec = 0; tv.tv_usec = 50*1000;
172 select(0, 0, 0, 0, &tv);
173
174 /* All done. */
75d55b66 175 XCloseDisplay(dpy);
dd6d43a6
MW
176 return (0);
177}
178
179/*----- That's all, folks -------------------------------------------------*/