chiark / gitweb /
debian/source/format: Apparently we're meant to have one of these.
[xtoys] / xrepaint.c
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
39 #include <mLib/mdwopt.h>
40 #include <mLib/quis.h>
41 #include <mLib/report.h>
42
43 /*----- Global variables --------------------------------------------------*/
44
45 static Display *dpy;
46
47 /*----- Main code ---------------------------------------------------------*/
48
49 static void version(FILE *fp)
50   { pquis(fp, "$ (xtoys version " VERSION ")\n"); }
51
52 static void usage(FILE *fp)
53   { pquis(fp, "Usage: $ [-as] [-d display]\n"); }
54
55 static void help(FILE *fp)
56 {
57   version(fp);
58   fputc('\n', fp);
59   usage(stdout);
60   fputs("\n\
61 Repaint the X display (or just one screen).\n\
62 \n\
63 Options:\n\
64 \n\
65 -h, --help              Display this help text\n\
66 -u, --usage             Display a short usage summary\n\
67 -v, --version           Display the program's version number\n\
68 \n\
69 -a, --all               Repaint all of the screens on the display\n\
70 -d, --display=DISPLAY   Choose X display to connect to\n\
71 -s, --screen            Only repaint the selected screen\n",
72         fp);
73 }
74
75 static void repaint(Screen *sc)
76 {
77   /* Repaint the screen SC.
78    *
79    * Annoyingly, `XClearWindow' uses `ClipByChildren' semantics, and there's
80    * no way to change that.  The best idea I can come up with is to drop
81    * another window in front and take it away again.
82    */
83
84   Window w;
85   XSetWindowAttributes attr;
86   XEvent ev;
87
88   attr.background_pixel = 0;
89   attr.event_mask = StructureNotifyMask | VisibilityChangeMask | ExposureMask | KeyPressMask | ButtonPressMask;
90   attr.override_redirect = True;
91   w = XCreateWindow(dpy, RootWindowOfScreen(sc),
92                     0, 0, WidthOfScreen(sc), HeightOfScreen(sc),
93                     0, CopyFromParent, InputOutput,
94                     DefaultVisualOfScreen(sc),
95                     CWBackPixel | CWEventMask | CWOverrideRedirect, &attr);
96   XMapWindow(dpy, w);
97   do XNextEvent(dpy, &ev);
98   while (ev.type != Expose && ev.type != KeyPress && ev.type != ButtonPress);
99 }
100
101 int main(int argc, char *argv[])
102 {
103   const char *display = 0;
104   unsigned f = 0;
105   struct timeval tv;
106   int i;
107
108 #define f_only 1u
109 #define f_bogus 2u
110
111   /* Parse command line options. */
112   ego(argv[0]);
113   for (;;) {
114     static struct option opt[] = {
115       { "help",         0,              0,      'h' },
116       { "usage",        0,              0,      'u' },
117       { "version",      0,              0,      'v' },
118       { "all",          0,              0,      'a' },
119       { "display",      OPTF_ARGREQ,    0,      'd' },
120       { "screen",       0,              0,      's' },
121       { 0,              0,              0,      0 }
122     };
123     int i = getopt_long(argc, argv, "huv" "ad:s", opt, 0);
124     if (i < 0) break;
125     switch (i) {
126       case 'h': help(stdout); exit(0); break;
127       case 'u': usage(stdout); exit(0); break;
128       case 'v': version(stdout); exit(0); break;
129       case 'a': f &= ~f_only; break;
130       case 'd': display = optarg; break;
131       case 's': f |= f_only; break;
132       default: f |= f_bogus; break;
133     }
134   }
135   if (optind < argc) f |= f_bogus;
136   if (f & f_bogus) { usage(stderr); exit(EXIT_FAILURE); }
137
138   /* Open the display. */
139   dpy = XOpenDisplay(display);
140   if (!dpy) { die(EXIT_FAILURE, "couldn't open display"); }
141
142   /* Do the repainting thing. */
143   if (f & f_only)
144     repaint(DefaultScreenOfDisplay(dpy));
145   else {
146     for (i = 0; i < ScreenCount(dpy); i++)
147       repaint(ScreenOfDisplay(dpy, i));
148   }
149
150   /* Wait for a bit.  This is an awful hack. */
151   tv.tv_sec = 0; tv.tv_usec = 50*1000;
152   select(0, 0, 0, 0, &tv);
153
154   /* All done. */
155   return (0);
156 }
157
158 /*----- That's all, folks -------------------------------------------------*/