From: Mark Wooding Date: Sun, 10 Jan 2016 13:47:45 +0000 (+0000) Subject: New tool `xrepaint'. X-Git-Tag: 1.5.0~1 X-Git-Url: https://git.distorted.org.uk/~mdw/xtoys/commitdiff_plain/dd6d43a6e256a061ecf9a5fcb43c5e45cc69f3fe New tool `xrepaint'. --- diff --git a/Makefile.am b/Makefile.am index 4b5312b..8b99a3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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. diff --git a/debian/control b/debian/control index c0767b5..efd7a45 100644 --- a/debian/control +++ b/debian/control @@ -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 diff --git a/debian/xtoys.install b/debian/xtoys.install index 595c141..445435a 100644 --- a/debian/xtoys.install +++ b/debian/xtoys.install @@ -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 index 0000000..6cfd9d9 --- /dev/null +++ b/xrepaint.1 @@ -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 diff --git a/xrepaint.c b/xrepaint.c new file mode 100644 index 0000000..166e238 --- /dev/null +++ b/xrepaint.c @@ -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 +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +/*----- 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 -------------------------------------------------*/