New tool `xrepaint'.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 10 Jan 2016 13:47:45 +0000 (13:47 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 10 Jan 2016 14:24:10 +0000 (14:24 +0000)
Makefile.am
debian/control
debian/xtoys.install
xrepaint.1 [new file with mode: 0644]
xrepaint.c [new file with mode: 0644]

index 4b5312b..8b99a3a 100644 (file)
@@ -57,6 +57,11 @@ dist_man_MANS                += xatom.1
 xatom_SOURCES           = xatom.c
 xatom_SOURCES          += libxatom.h libxatom.c
 
+## xrepaint.
+bin_PROGRAMS           += xrepaint
+dist_man_MANS          += xrepaint.1
+xrepaint_SOURCES        = xrepaint.c
+
 ###--------------------------------------------------------------------------
 ### Graphical tools in Python.
 
index c0767b5..efd7a45 100644 (file)
@@ -15,6 +15,7 @@ Description: A collection of small X11 tools
  We have:
  xscsize -- reports the display size as shell variables
  xatom -- inspect properties on windows, and wait for changes
+ xrepaint -- repaint the display, or just a single screen
 
 Package: xtoys-gtk
 Architecture: all
index 595c141..445435a 100644 (file)
@@ -2,3 +2,5 @@ debian/tmp/usr/bin/xatom
 debian/tmp/usr/share/man/man1/xatom.1
 debian/tmp/usr/bin/xscsize
 debian/tmp/usr/share/man/man1/xscsize.1
+debian/tmp/usr/bin/xrepaint
+debian/tmp/usr/share/man/man1/xrepaint.1
diff --git a/xrepaint.1 b/xrepaint.1
new file mode 100644 (file)
index 0000000..6cfd9d9
--- /dev/null
@@ -0,0 +1,47 @@
+.\" -*-nroff-*-
+.TH xrepaint 1 "10 January 2016" "Straylight/Edgeware" "xtoys"
+.SH NAME
+xrepaint \- force repainting of X display, or just one screen
+.SH SYNOPSIS
+.B xrepaint
+.RB [ \-as ]
+.RB [ \-d
+.IR display ]
+.SH DESCRIPTION
+The
+.B xrepaint
+program forces a repaint of the entire X display,
+or maybe just a single screen.
+.PP
+Options are as follows.
+.TP
+.B "\-a, \-\-all"
+Repaint all of the screens on the display.
+This is the default.
+.TP
+.BI "\-d, \-\-display=" display
+Sets the X display to connect to.
+The default comes from the
+.B DISPLAY
+environment variable,
+as usual.
+.TP
+.B "\-s, \-\-screen"
+Repaint only the default screen selected by
+.IR display .
+The default is to repaint all of the screens.
+.SH BUGS
+If a compositing manager is present,
+then
+.B xrepaint
+forces recompositing of the screen,
+but if some client has painted rubbish into its window,
+it won't be forced to repaint it.
+.PP
+The current approach is fundamentally incorrect.
+It doesn't seem possible to know when I've actually succeeded
+in forcing a repaint of the display.
+.PP
+The current behaviour seems to be good enough for the author's purposes.
+.SH AUTHOR
+Mark Wooding <mdw@distorted.org.uk>
diff --git a/xrepaint.c b/xrepaint.c
new file mode 100644 (file)
index 0000000..166e238
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*-c-*-
+ *
+ * Redraw the screen in case it's been trashed somehow
+ *
+ * (c) 2016 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Edgeware X tools collection.
+ *
+ * X tools is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * X tools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with X tools; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+
+/*----- Global variables --------------------------------------------------*/
+
+static Display *dpy;
+
+/*----- Main code ---------------------------------------------------------*/
+
+static void version(FILE *fp)
+  { pquis(fp, "$ (xtoys version " VERSION ")\n"); }
+
+static void usage(FILE *fp)
+  { pquis(fp, "Usage: $ [-as] [-d display]\n"); }
+
+static void help(FILE *fp)
+{
+  version(fp);
+  fputc('\n', fp);
+  usage(stdout);
+  fputs("\n\
+Repaint the X display (or just one screen).\n\
+\n\
+Options:\n\
+\n\
+-h, --help             Display this help text\n\
+-u, --usage            Display a short usage summary\n\
+-v, --version          Display the program's version number\n\
+\n\
+-a, --all              Repaint all of the screens on the display\n\
+-d, --display=DISPLAY  Choose X display to connect to\n\
+-s, --screen           Only repaint the selected screen\n",
+       fp);
+}
+
+static void repaint(Screen *sc)
+{
+  /* Repaint the screen SC.
+   *
+   * Annoyingly, `XClearWindow' uses `ClipByChildren' semantics, and there's
+   * no way to change that.  The best idea I can come up with is to drop
+   * another window in front and take it away again.
+   */
+
+  Window w;
+  XSetWindowAttributes attr;
+  XEvent ev;
+
+  attr.background_pixel = 0;
+  attr.event_mask = StructureNotifyMask | VisibilityChangeMask | ExposureMask | KeyPressMask | ButtonPressMask;
+  attr.override_redirect = True;
+  w = XCreateWindow(dpy, RootWindowOfScreen(sc),
+                   0, 0, WidthOfScreen(sc), HeightOfScreen(sc),
+                   0, CopyFromParent, InputOutput,
+                   DefaultVisualOfScreen(sc),
+                   CWBackPixel | CWEventMask | CWOverrideRedirect, &attr);
+  XMapWindow(dpy, w);
+  do XNextEvent(dpy, &ev);
+  while (ev.type != Expose && ev.type != KeyPress && ev.type != ButtonPress);
+}
+
+int main(int argc, char *argv[])
+{
+  const char *display = 0;
+  unsigned f = 0;
+  struct timeval tv;
+  int i;
+
+#define f_only 1u
+#define f_bogus 2u
+
+  /* Parse command line options. */
+  ego(argv[0]);
+  for (;;) {
+    static struct option opt[] = {
+      { "help",                0,              0,      'h' },
+      { "usage",       0,              0,      'u' },
+      { "version",     0,              0,      'v' },
+      { "all",         0,              0,      'a' },
+      { "display",     OPTF_ARGREQ,    0,      'd' },
+      { "screen",      0,              0,      's' },
+      {        0,              0,              0,      0 }
+    };
+    int i = getopt_long(argc, argv, "huv" "ad:s", opt, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'h':        help(stdout); exit(0); break;
+      case 'u':        usage(stdout); exit(0); break;
+      case 'v': version(stdout); exit(0); break;
+      case 'a': f &= ~f_only; break;
+      case 'd': display = optarg; break;
+      case 's': f |= f_only; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (optind < argc) f |= f_bogus;
+  if (f & f_bogus) { usage(stderr); exit(EXIT_FAILURE); }
+
+  /* Open the display. */
+  dpy = XOpenDisplay(display);
+  if (!dpy) { die(EXIT_FAILURE, "couldn't open display"); }
+
+  /* Do the repainting thing. */
+  if (f & f_only)
+    repaint(DefaultScreenOfDisplay(dpy));
+  else {
+    for (i = 0; i < ScreenCount(dpy); i++)
+      repaint(ScreenOfDisplay(dpy, i));
+  }
+
+  /* Wait for a bit.  This is an awful hack. */
+  tv.tv_sec = 0; tv.tv_usec = 50*1000;
+  select(0, 0, 0, 0, &tv);
+
+  /* All done. */
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/