From dd6d43a6e256a061ecf9a5fcb43c5e45cc69f3fe Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 10 Jan 2016 13:47:45 +0000 Subject: [PATCH 01/16] New tool `xrepaint'. --- Makefile.am | 5 ++ debian/control | 1 + debian/xtoys.install | 2 + xrepaint.1 | 47 +++++++++++++++ xrepaint.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 213 insertions(+) create mode 100644 xrepaint.1 create mode 100644 xrepaint.c 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 -------------------------------------------------*/ -- 2.11.0 From d57e8f14168e8f8cd56ce22ee97fd717f16ad847 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 10 Jan 2016 13:51:04 +0000 Subject: [PATCH 02/16] Release 1.5.0. --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index a3c9e93..dfdb22c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +xtoys (1.5.0) experimental; urgency=low + + * xrepaint: First new tool for ages. + + -- Mark Wooding Sun, 10 Jan 2016 14:25:44 +0000 + xtoys (1.4.2) experimental; urgency=low * xgetline: Mnemonic for the main entry box. -- 2.11.0 From 9535c380c525411eeed8af05a2270ea91b1ddbfa Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 09:40:53 +0100 Subject: [PATCH 03/16] debian/source/format: Apparently we're meant to have one of these. --- debian/source/format | 1 + 1 file changed, 1 insertion(+) create mode 100644 debian/source/format diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..d3827e7 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +1.0 -- 2.11.0 From acbef80b6b4f54ed2f67b576d696b28df5994986 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 09:41:10 +0100 Subject: [PATCH 04/16] debian/control: Fix Build-Depends. --- debian/control | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index efd7a45..49e6b1e 100644 --- a/debian/control +++ b/debian/control @@ -1,9 +1,10 @@ Source: xtoys Section: x11 Priority: extra -Build-Depends: - libx11-dev, mlib-dev (>= 2.0.4), debhelper (>= 8), - python-central, python (>= 2.4), python-gtk2 +Build-Depends: debhelper (>= 9), pkg-config, + libx11-dev, mlib-dev (>= 2.0.4) +Build-Depends-Indep: python-central, python (>= 2.4), + python-gtk2 Maintainer: Mark Wooding XS-Python-Version: >= 2.4 Standards-Version: 3.1.1 -- 2.11.0 From cd53187bae596ab6f3c865bf02122e180d50cc32 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 09:47:53 +0100 Subject: [PATCH 05/16] debian/xtoys-gtk.install: Actually distribute the manpages. This seems to have been broken for a long time. --- debian/xtoys-gtk.install | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/xtoys-gtk.install b/debian/xtoys-gtk.install index 4f6fd0f..79df130 100644 --- a/debian/xtoys-gtk.install +++ b/debian/xtoys-gtk.install @@ -1,4 +1,7 @@ debian/tmp/usr/bin/xcatch +debian/tmp/usr/share/man/man1/xcatch.1 debian/tmp/usr/bin/xgetline +debian/tmp/usr/share/man/man1/xgetline.1 debian/tmp/usr/bin/xmsg +debian/tmp/usr/share/man/man1/xmsg.1 debian/tmp/usr/lib/python* -- 2.11.0 From 443bbe89b13223ab8ee5af0cf7fed55508515e9b Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 09:54:53 +0100 Subject: [PATCH 06/16] Release 1.5.1. --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index dfdb22c..88f9bfb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +xtoys (1.5.1) experimental; urgency=low + + * xtoys-gtk: Distribute the manpages, which for some reason didn't make + it into the package. + * Debian packaging internal improvements. + + -- Mark Wooding Thu, 21 Apr 2016 09:52:53 +0100 + xtoys (1.5.0) experimental; urgency=low * xrepaint: First new tool for ages. -- 2.11.0 From a1bcaff7e13476a05a22427be28d47bb17f5c2fd Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 15:45:15 +0100 Subject: [PATCH 07/16] .cvsignore: Why was this still here? --- .cvsignore | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .cvsignore diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index 25ce188..0000000 --- a/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -Makefile.in -aclocal.m4 -build -configure -deb-build -- 2.11.0 From 3a4bdbcb848307f089c1dc06b63a0b7e3a43978b Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 17:18:01 +0100 Subject: [PATCH 08/16] xscsize.c: Publish the output-format flags globally. --- xscsize.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/xscsize.c b/xscsize.c index 19e5cca..0cd4cbd 100644 --- a/xscsize.c +++ b/xscsize.c @@ -35,6 +35,14 @@ #include #include +/*----- Static variables --------------------------------------------------*/ + +static unsigned int flags = 0; +#define F_SH 1u +#define F_CSH 2u +#define F_SHELL 3u +#define F_EXPORT 4u + /*----- Main code ---------------------------------------------------------*/ static void version(FILE *fp) @@ -75,11 +83,7 @@ int main(int argc, char *argv[]) unsigned long wd, ht; int sc; -#define f_sh 1u -#define f_csh 2u -#define f_shell 3u -#define f_export 4u -#define f_bogus 8u +#define f_bogus 1u /* --- Parse command line options --- */ @@ -104,9 +108,9 @@ int main(int argc, char *argv[]) case 'u': usage(stdout); exit(0); break; case 'v': version(stdout); exit(0); break; case 'd': display = optarg; break; - case 'b': f |= f_sh; break; - case 'c': f |= f_csh; break; - case 'x': f |= f_export; break; + case 'b': flags |= F_SH; break; + case 'c': flags |= F_CSH; break; + case 'x': flags |= F_EXPORT; break; default: f |= f_bogus; break; } } @@ -120,17 +124,14 @@ int main(int argc, char *argv[]) * Otherwise assume it's Bourne. This seems to work in practice. */ - if (!(f & f_shell)) { + if (!(flags & F_SHELL)) { s = getenv("SHELL"); - if (!s) - f |= f_sh; - if (strstr(s, "csh")) - f |= f_csh; - else - f |= f_sh; + if (!s) flags |= F_SH; + if (strstr(s, "csh")) flags |= F_CSH; + else flags |= F_SH; } - if ((f & f_sh) && (f & f_csh)) { + if ((flags & F_SH) && (flags & F_CSH)) { fprintf(stderr, "xscsize: make your mind up about your shell type\n"); exit(EXIT_FAILURE); } -- 2.11.0 From e5c4fa9dfaf1e867d13c5926c677e32eb4cb8e6b Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 21 Apr 2016 17:24:30 +0100 Subject: [PATCH 09/16] xscsize.c: Move reporting variables to a separate function. There are going to me more of them, and we won't know in advance how many, so it'll be handy to have the output formatting in just one place. This changes the detailed format of the output, but not in a way that any actual shells will care about. Specifically, each variable is now output on a separate line; and for Bourne shells, the `export' command is on the same line. --- xscsize.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/xscsize.c b/xscsize.c index 0cd4cbd..46d58f7 100644 --- a/xscsize.c +++ b/xscsize.c @@ -74,6 +74,23 @@ Options:\n\ fp); } +static void print_var(const char *name, unsigned long value) +{ + if (index >= 0) { + dstr_putf(&d, "XSCR%d_%s", index, name); + name = d.buf; + } + if (flags & F_SH) { + printf("%s=%lu", name, value); + if (flags & F_EXPORT) printf("; export %s", name); + } else if (flags & F_CSH) { + if (flags & F_EXPORT) printf("setenv %s %lu", name, value); + else printf("set %s=%lu", name, value); + } + putchar('\n'); + dstr_destroy(&d); +} + int main(int argc, char *argv[]) { Display *dpy; @@ -150,18 +167,8 @@ int main(int argc, char *argv[]) /* --- Do the output thing --- */ - if (f & f_sh) { - printf("XWIDTH=%lu XHEIGHT=%lu", wd, ht); - if (f & f_export) - printf("; export XWIDTH XHEIGHT"); - } - if (f & f_csh) { - if (f & f_export) - printf("setenv XWIDTH %lu; setenv XHEIGHT %lu", wd, ht); - else - printf("set XWIDTH=%lu XHEIGHT=%lu", wd, ht); - } - putchar('\n'); + print_var("XWIDTH", wd); + print_var("XHEIGHT", ht); /* --- Done --- */ -- 2.11.0 From c5f8baff93b1a66fd66136781db7a75a846e84e7 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Fri, 22 Apr 2016 18:51:36 +0100 Subject: [PATCH 10/16] xscsize.1: Add missing `.TP' requests in the `ENVIRONMENT' section. --- xscsize.1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xscsize.1 b/xscsize.1 index 764b542..0ba808c 100644 --- a/xscsize.1 +++ b/xscsize.1 @@ -52,8 +52,10 @@ by child processes. The default is to just set local shell variables. .TP .B XWIDTH Set to the width of the display in pixels. +.TP .B XHEIGHT Set to the height of the display in pixels. +.TP .B SHELL Used to decide the nature of the calling shell. If absent, a Bourne shell is assumed. -- 2.11.0 From 243654c4bf8293284640aedced9914680ea27f10 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Fri, 22 Apr 2016 18:53:01 +0100 Subject: [PATCH 11/16] xscsize.c, etc.: Report geometry of individual monitors. This is enabled by the new `-m' option. --- Makefile.am | 1 + configure.ac | 16 +++++++++ debian/control | 2 +- xscsize.1 | 95 +++++++++++++++++++++++++++++++++++++++++++++++-- xscsize.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 213 insertions(+), 11 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8b99a3a..676c52b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -50,6 +50,7 @@ LDADD = -lX11 $(X_LIBS) bin_PROGRAMS += xscsize dist_man_MANS += xscsize.1 xscsize_SOURCES = xscsize.c +xscsize_LDADD = $(LDADD) $(XRANDR_LIBS) ## xatom. bin_PROGRAMS += xatom diff --git a/configure.ac b/configure.ac index 7a635b3..ce290ec 100644 --- a/configure.ac +++ b/configure.ac @@ -40,6 +40,22 @@ AC_PROG_CC AX_CFLAGS_WARN_ALL AC_PATH_XTRA +mdw_LIBS=$LIBS LIBS= mdw_have_xrandr_p=nil +AC_SEARCH_LIBS([XRRGetScreenInfo], [Xrandr], [mdw_have_xrandr_p=t]) +case $mdw_have_xrandr_p in + t) + AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [], [mdw_have_xrandr_p=nil]) + ;; +esac +case $mdw_have_xrandr_p in + t) + XRANDR_LIBS=$LIBS + AC_DEFINE([HAVE_XRANDR], [1], [Define if libXrandr is installed.]) + ;; +esac +LIBS=$mdw_LIBS +AC_SUBST([XRANDR_LIBS]) + PKG_CHECK_MODULES([mLib], [mLib >= 2.0.4]) CFLAGS="$CFLAGS $mLib_CFLAGS" LIBS="$LIBS $mLib_LIBS" diff --git a/debian/control b/debian/control index 49e6b1e..8003ed0 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: xtoys Section: x11 Priority: extra Build-Depends: debhelper (>= 9), pkg-config, - libx11-dev, mlib-dev (>= 2.0.4) + libx11-dev, libxrandr-dev, mlib-dev (>= 2.0.4) Build-Depends-Indep: python-central, python (>= 2.4), python-gtk2 Maintainer: Mark Wooding diff --git a/xscsize.1 b/xscsize.1 index 0ba808c..c06ea8e 100644 --- a/xscsize.1 +++ b/xscsize.1 @@ -4,7 +4,7 @@ xscsize \- return size of an X display to a shell script .SH SYNOPSIS .B xscsize -.RB [ \-bcx ] +.RB [ \-bcmx ] .RB [ \-d .IR display ] .SH DESCRIPTION @@ -18,6 +18,13 @@ and .B XHEIGHT variables. .PP +With the +.B \-m +option (see below), +.B xscsize +instead reports the geometry of the individual monitors (CRTCs) of a +(possibly) multihead display. +.PP Command line options can be used to force output in either Bourne or C shell syntax. In the absence of any explicit instructions, .B xscsize @@ -45,16 +52,98 @@ POSIX, Korn, Z and Bourne Again shells). Output the assignments in C shell syntax (usable by C and Terminal C shells). .TP 5 +.B \-m, \-\-multiscreen +Output geometry information about the individual monitors of a +(possibly) multihead display, rather than the overall size of the root +window. This sets +.B XNSCR +to the number of monitors, and +.BI XSCR n _X \fR, +.BI XSCR n _Y \fR, +.BI XSCR n _WIDTH \fR, +and +.BI XSCR n _HEIGHT \fR +to the +.IR x - +and +.IR y -coordinates +of the pixel shown in the top-left of monitor +.I n +(starting from zero), and the width and height of monitor +.I n +in pixels. The monitors will be sorted in order of increasing +.IR y -coordinate +(i.e., top to bottom), with monitors with equal +.IR y -coordinates +sorted in order of increasing +.IR x -coordinate +(i.e., left to right). Usually, then, the first monitor will be at +(0, 0). +.IP +This requires that support libraries for the X RANDR extension were +available when +.B xscsize +was compiled, and that the display actually implements at least version +1.2 of the RANDR extension. If not, +.B xscsize +will still accept the +.B \-m +option, and produce appropriately formatted output, but will assume that +there is exactly one monitor, and that it shows the entire root window. +.TP 5 .B \-x, --export Output a variable export command, so that the screen size is inherited by child processes. The default is to just set local shell variables. .SH ENVIRONMENT .TP .B XWIDTH -Set to the width of the display in pixels. +Set to the width of the display in pixels (not in +.B \-m +mode). .TP .B XHEIGHT -Set to the height of the display in pixels. +Set to the height of the display in pixels (not in +.B \-m +mode). +.TP +.B XNSCR +The number of monitors attached to the display (only in +.B \-m +mode). +.TP +.BI XSCR n _X +The +.I x -coordinate +of the top-left pixel shown on monitor number +.I n +counting from zero (only in +.B \-m +mode). +.TP +.BI XSCR n _Y +The +.I y -coordinate +of the top-left pixel shown on monitor number +.I n +counting from zero (only in +.B \-m +mode). +.TP +.BI XSCR n _WIDTH +The width, in pixels, of the portion of the root window shown on monitor +number +.I n +counting from zero (only in +.B \-m +mode). +.TP +.BI XSCR n _HEIGHT +The height, in pixels, of the portion of the root window shown on monitor +number +.I n +counting from zero (only in +.B \-m +mode). .TP .B SHELL Used to decide the nature of the calling shell. If absent, a Bourne diff --git a/xscsize.c b/xscsize.c index 46d58f7..99d729f 100644 --- a/xscsize.c +++ b/xscsize.c @@ -31,10 +31,22 @@ #include #include +#ifdef HAVE_XRANDR +# include +#endif +#include +#include #include #include +/*----- Data structures ---------------------------------------------------*/ + +struct screen { + int x, y; + unsigned wd, ht; +}; + /*----- Static variables --------------------------------------------------*/ static unsigned int flags = 0; @@ -74,8 +86,10 @@ Options:\n\ fp); } -static void print_var(const char *name, unsigned long value) +static void print_var(const char *name, int index, unsigned long value) { + dstr d = DSTR_INIT; + if (index >= 0) { dstr_putf(&d, "XSCR%d_%s", index, name); name = d.buf; @@ -91,6 +105,14 @@ static void print_var(const char *name, unsigned long value) dstr_destroy(&d); } +static int compare_screen(const void *a, const void *b) +{ + const struct screen *s = a, *t = b; + if (s->y != t->y) return (s->y < t->y ? -1 : +1); + else if (s->x != t->x) return (s->x < t->x ? -1 : +1); + else return (0); +} + int main(int argc, char *argv[]) { Display *dpy; @@ -99,8 +121,18 @@ int main(int argc, char *argv[]) unsigned f = 0; unsigned long wd, ht; int sc; +#ifdef HAVE_XRANDR + Window root; + int rrev, rrerr, rrmaj, rrmin; + XRRScreenResources *res; + XRRCrtcInfo *crtc; + struct screen *scr; + size_t nscr, j; + int i; +#endif #define f_bogus 1u +#define f_multi 2u /* --- Parse command line options --- */ @@ -114,11 +146,12 @@ int main(int argc, char *argv[]) { "display", OPTF_ARGREQ, 0, 'd' }, { "bourne-shell", 0, 0, 'b' }, { "c-shell", 0, 0, 'c' }, + { "multiscreen", 0, 0, 'm' }, { "export", 0, 0, 'x' }, { 0, 0, 0, 0 } }; - int i = getopt_long(argc, argv, "huv" "d:bcx", opt, 0); + int i = getopt_long(argc, argv, "huv" "d:bcmx", opt, 0); if (i < 0) break; switch (i) { case 'h': help(stdout); exit(0); break; @@ -127,6 +160,7 @@ int main(int argc, char *argv[]) case 'd': display = optarg; break; case 'b': flags |= F_SH; break; case 'c': flags |= F_CSH; break; + case 'm': f |= f_multi; break; case 'x': flags |= F_EXPORT; break; default: f |= f_bogus; break; } @@ -153,22 +187,84 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - /* --- Get the important information --- */ + /* --- Open the display --- */ dpy = XOpenDisplay(display); if (!dpy) { fprintf(stderr, "xscsize: couldn't open display\n"); exit(EXIT_FAILURE); } + + /* --- Fetch the root window size --- * + * + * We might need this whatever happens, so go with the flow. + */ + sc = DefaultScreen(dpy); wd = DisplayWidth(dpy, sc); ht = DisplayHeight(dpy, sc); - XCloseDisplay(dpy); - /* --- Do the output thing --- */ + /* --- Calculate and produce the necessary output --- * + * + * If we're meant to report on individual screens then try to collect + * information about them using the RANDR extension. If that doesn't + * exist, or the version is too ancient, or its otherwise not going to + * work, then pretend there's just one screen that's the size of the root + * window. + */ + + if (f & f_multi) { +#ifdef HAVE_XRANDR + if (XRRQueryExtension(dpy, &rrev, &rrerr) && + XRRQueryVersion(dpy, &rrmaj, &rrmin) && + (rrmaj > 1 || (rrmaj == 1 && rrmin >= 2))) { + root = RootWindow(dpy, sc); + res = XRRGetScreenResources(dpy, root); + scr = xmalloc(res->ncrtc*sizeof(*scr)); j = 0; + for (i = 0; i < res->ncrtc; i++) { + crtc = XRRGetCrtcInfo(dpy, res, res->crtcs[i]); + if (crtc->mode) { + scr[j].x = crtc->x; scr[j].wd = crtc->width; + scr[j].y = crtc->y; scr[j].ht = crtc->height; + j++; + } + XRRFreeCrtcInfo(crtc); + } + nscr = j; + XRRFreeScreenResources(res); + } else +#endif + { + /* --- The RANDR extension isn't available --- */ + + nscr = 1; + scr = xmalloc(sizeof(*scr)); + scr->x = 0; scr->wd = wd; + scr->y = 0; scr->ht = ht; + } + + /* --- Sort and report the screens --- * + * + * The chances are good that the screens reported by RANDR aren't in any + * especially useful order. Sort them into (my) reading order. + */ - print_var("XWIDTH", wd); - print_var("XHEIGHT", ht); + qsort(scr, nscr, sizeof(*scr), compare_screen); + print_var("XNSCR", -1, nscr); + for (j = 0; j < nscr; j++) { + print_var("X", j, scr[j].x); + print_var("Y", j, scr[j].y); + print_var("WIDTH", j, scr[j].wd); + print_var("HEIGHT", j, scr[j].ht); + } + } else { + print_var("XWIDTH", -1, wd); + print_var("XHEIGHT", -1, ht); + } + + /* --- We're done with the display now --- */ + + XCloseDisplay(dpy); /* --- Done --- */ -- 2.11.0 From 4be8cb2b59106a6c55a235f713cc4ac2ba655df8 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 23 Apr 2016 14:47:03 +0100 Subject: [PATCH 12/16] Release 1.6.0. --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 88f9bfb..51a348b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +xtoys (1.6.0) experimental; urgency=low + + * xscsize: New option to provide detailed information about multiple + monitors. + + -- Mark Wooding Sat, 23 Apr 2016 14:46:28 +0100 + xtoys (1.5.1) experimental; urgency=low * xtoys-gtk: Distribute the manpages, which for some reason didn't make -- 2.11.0 From 577e53c6f2dcd0ea6ae4cf75accb31a49c4319fa Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 13 Aug 2017 01:42:37 +0100 Subject: [PATCH 13/16] xscsize.c: Fix build failure if we had no Xrandr. --- xscsize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xscsize.c b/xscsize.c index 99d729f..7c40de9 100644 --- a/xscsize.c +++ b/xscsize.c @@ -121,13 +121,13 @@ int main(int argc, char *argv[]) unsigned f = 0; unsigned long wd, ht; int sc; + struct screen *scr; + size_t nscr, j; #ifdef HAVE_XRANDR Window root; int rrev, rrerr, rrmaj, rrmin; XRRScreenResources *res; XRRCrtcInfo *crtc; - struct screen *scr; - size_t nscr, j; int i; #endif -- 2.11.0 From a2cfea891e714d4b10878318949639c3a2007331 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 13 Aug 2017 01:41:20 +0100 Subject: [PATCH 14/16] Makefile.am: Tweak `silent-rules' machinery. Since Automake 1.11, the advice for setting up custom silent-rules recipes has changed, so use the new machinery. Also, I'm no longer mainly working on wheezy, and Automake has made the operation field two spaces wider while I wasn't looking, so make the output line up properly. This means that xtoys now requires Automake 1.11.2 or later to build from the Git tree. --- Makefile.am | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 676c52b..825e8fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,9 +32,9 @@ CLEANFILES = confsubst = $(srcdir)/config/confsubst EXTRA_DIST += config/confsubst -V_SUBST = $(V_SUBST_$(V)) -V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY)) -V_SUBST_0 = @echo " SUBST $@"; +V_SUBST = $(V_SUBST_@AM_V@) +V_SUBST_ = $(V_SUBST_@AM_DEFAULT_V@) +V_SUBST_0 = @echo " SUBST $@"; SUBST = $(V_SUBST)$(confsubst) SUBSTITUTIONS = \ @@ -113,7 +113,6 @@ dist-hook:: EXTRA_DIST += config/auto-version - ###-------------------------------------------------------------------------- ### Debian. -- 2.11.0 From 5bdda4e19a428c5e337f94b7be5e38ede696535e Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 13 Aug 2017 01:41:41 +0100 Subject: [PATCH 15/16] debian/compat: Update to Debhelper 9 and `dh_python2'. Suspiciously, the control file already had a build-dependency on Debhelper 9. --- debian/compat | 2 +- debian/control | 3 +-- debian/rules | 4 +++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/debian/compat b/debian/compat index 45a4fb7..ec63514 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -8 +9 diff --git a/debian/control b/debian/control index 8003ed0..743330a 100644 --- a/debian/control +++ b/debian/control @@ -3,8 +3,7 @@ Section: x11 Priority: extra Build-Depends: debhelper (>= 9), pkg-config, libx11-dev, libxrandr-dev, mlib-dev (>= 2.0.4) -Build-Depends-Indep: python-central, python (>= 2.4), - python-gtk2 +Build-Depends-Indep: python (>= 2.6.6-3~), python-gtk2 Maintainer: Mark Wooding XS-Python-Version: >= 2.4 Standards-Version: 3.1.1 diff --git a/debian/rules b/debian/rules index cec98bb..d6037af 100755 --- a/debian/rules +++ b/debian/rules @@ -1,2 +1,4 @@ #! /usr/bin/make -f -%:; dh $@ --parallel -Bdebian/build + +ARGS_binary-indep = --with-python2 +%:; dh $@ --parallel -Bdebian/build $(ARGS_$@) -- 2.11.0 From 503ab5d91f475ea7a5259f61083271ee6166edbd Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 14 Aug 2017 00:11:47 +0100 Subject: [PATCH 16/16] Release 1.6.1. --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 51a348b..f49f4ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +xtoys (1.6.1) experimental; urgency=medium + + * debian: Use `dh_python2' for Python packaging. + * build: Fix build failure without Xrandr library. + + -- Mark Wooding Mon, 14 Aug 2017 00:11:38 +0100 + xtoys (1.6.0) experimental; urgency=low * xscsize: New option to provide detailed information about multiple -- 2.11.0