]> git.draconx.ca Git - rrace.git/commitdiff
Implement window icons.
authorNick Bowler <nbowler@draconx.ca>
Tue, 8 Mar 2022 03:47:18 +0000 (22:47 -0500)
committerNick Bowler <nbowler@draconx.ca>
Tue, 8 Mar 2022 03:47:18 +0000 (22:47 -0500)
Makefile.am
src/ewmhicon.c [new file with mode: 0644]
src/motif.c
src/motif.h
src/motifopt.opt
src/x11.c
t/.gitignore
t/ewmhicon.c [new file with mode: 0644]
tests/game.at
tests/gui.at [new file with mode: 0644]
testsuite.at

index 0ce64bc7791d72f1dc33590e5b70dbc26c5e9603..e9dd395ed358245c8afa1d8f4abd7b3270cb2b27 100644 (file)
@@ -19,7 +19,8 @@ AM_CFLAGS = $(MOTIF_CFLAGS)
 
 bin_PROGRAMS = rrace-motif
 
-rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h
+rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h \
+                      src/ewmhicon.c
 rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \
                     $(libglohelp_a_OBJECTS) libgnu.a $(MOTIF_LIBS)
 $(rrace_motif_OBJECTS): $(gnulib_headers)
@@ -64,11 +65,17 @@ $(GUIFILES:.dat=.h): $(DX_BASEDIR)/scripts/gen-tree.awk
 DISTCLEANFILES += $(GUIFILES:.dat=.h)
 EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-tree.awk $(GUIFILES)
 
-check_PROGRAMS = t/boardmove t/rng-test
+check_PROGRAMS = t/boardmove t/ewmhicon t/rng-test
 EXTRA_DIST += t/xos256ss.c
 
 t_boardmove_LDADD = src/game.$(OBJEXT) libgnu.a
 $(t_boardmove_OBJECTS): $(gnulib_headers)
 
+t_ewmhicon_LDADD = src/ewmhicon.$(OBJEXT) libgnu.a $(MOTIF_LIBS)
+$(t_ewmhicon_OBJECTS): $(gnulib_headers)
+
+t_rng_test_LDADD = libgnu.a
+$(t_rng_test_OBJECTS): $(gnulib_headers)
+
 include $(top_srcdir)/lib/gnulib.mk
 include $(top_srcdir)/common/snippet/autotest.mk
diff --git a/src/ewmhicon.c b/src/ewmhicon.c
new file mode 100644 (file)
index 0000000..e071cec
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * _NET_WM_ICON helpers for slide puzzle game
+ * Copyright © 2022 Nick Bowler
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/Xatom.h>
+#include "motif.h"
+
+static unsigned long scale16to8(unsigned x)
+{
+       return x*0xfful / 0xffff;
+}
+
+static unsigned long wm_pixel(const XColor *c)
+{
+       return 0xff000000
+            | scale16to8(c->red) << 16
+            | scale16to8(c->green) << 8
+            | scale16to8(c->blue);
+}
+
+/*
+ * The 16x16 icon is drawn with 1px shadow, 6x6 tiles, with 1 pixel cropped off
+ * all the edge tiles
+ */
+void ewmh_tile16(unsigned long *icon, const XColor *c, int tile_x, int tile_y)
+{
+       int out_x, out_y, out_w, x, y;
+       unsigned long row[6];
+
+       out_x = tile_x * 11 / 2;
+       out_y = tile_y * 11 / 2;
+       out_w = (5 + (tile_x == 1)) * sizeof row[0];
+
+       for (y = 0+(tile_y == 0); y < 6-(tile_y == 2); y++) {
+               for (x = 0+(tile_x == 0); x < 6-(tile_x==2); x++) {
+                       if (x == 0 || y == 0)
+                               row[x] = wm_pixel(&c[COLOUR_LIGHT]);
+                       else if (x == 5 || y == 5)
+                               row[x] = wm_pixel(&c[COLOUR_DARK]);
+                       else
+                               row[x] = wm_pixel(&c[COLOUR_PRIMARY]);
+               }
+               memcpy(&icon[16 * out_y++ + out_x], &row[tile_x == 0], out_w);
+       }
+}
+
+/*
+ * The 24x24 icon is drawn with 1px shadow and 8x8 tiles.
+ */
+void ewmh_tile24(unsigned long *icon, const XColor *c, int tile_x, int tile_y)
+{
+       int out_x, out_y, x, y;
+       unsigned long row[8];
+
+       out_x = tile_x * 8;
+       out_y = tile_y * 8;
+
+       for (y = 0; y < 8; y++) {
+               for (x = 0; x < 8; x++) {
+                       if (x == 0 || y == 0)
+                               row[x] = wm_pixel(&c[COLOUR_LIGHT]);
+                       else if (x == 7 || y == 7)
+                               row[x] = wm_pixel(&c[COLOUR_DARK]);
+                       else
+                               row[x] = wm_pixel(&c[COLOUR_PRIMARY]);
+               }
+               memcpy(&icon[24 * out_y++ + out_x], row, sizeof row);
+       }
+}
+
+/*
+ * The 32x32 icon is drawn with 1px shadow with slightly uneven tiles on
+ * an 11-10-11 pixel grid.
+ */
+void ewmh_tile32(unsigned long *icon, const XColor *c, int tile_x, int tile_y)
+{
+       int out_x, out_y, out_w, out_h, x, y;
+       unsigned long row[11];
+
+       out_x = 10*tile_x + (tile_x > 0);
+       out_y = 10*tile_y + (tile_y > 0);
+       out_w = 10 + (tile_x != 1);
+       out_h = 10 + (tile_y != 1);
+
+       for (y = 0; y < out_h; y++) {
+               for (x = 0; x < out_w; x++) {
+                       if (x == 0 || y == 0)
+                               row[x] = wm_pixel(&c[COLOUR_LIGHT]);
+                       else if (x == out_w-1 || y == out_h-1)
+                               row[x] = wm_pixel(&c[COLOUR_DARK]);
+                       else
+                               row[x] = wm_pixel(&c[COLOUR_PRIMARY]);
+               }
+               memcpy(&icon[32 * out_y++ + out_x], row, out_w * sizeof row[0]);
+       }
+}
+
+/*
+ * The 48x48 icon is drawn with 2px shadow and 16x16 tiles.
+ */
+void ewmh_tile48(unsigned long *icon, const XColor *c, int tile_x, int tile_y)
+{
+       int out_x, out_y, x, y;
+       unsigned long row[16];
+
+       out_x = tile_x * 16;
+       out_y = tile_y * 16;
+
+       for (y = 0; y < 16; y++) {
+               for (x = 0; x < 16; x++) {
+                       if (x == 0 || y == 0)
+                               row[x] = wm_pixel(&c[COLOUR_LIGHT]);
+                       else if (x == 15 || y == 15)
+                               row[x] = wm_pixel(&c[COLOUR_DARK]);
+                       else if (x == 1 || y == 1)
+                               row[x] = wm_pixel(&c[COLOUR_LIGHT]);
+                       else if (x == 14 || y == 14)
+                               row[x] = wm_pixel(&c[COLOUR_DARK]);
+                       else
+                               row[x] = wm_pixel(&c[COLOUR_PRIMARY]);
+               }
+               memcpy(&icon[48 * out_y++ + out_x], row, sizeof row);
+       }
+}
+
+int ewmh_probe_wm_icon(Widget shell)
+{
+       Display *display = XtDisplay(shell);
+       Screen *screen = XtScreen(shell);
+       Window root = RootWindowOfScreen(screen);
+       Atom net_supported, net_wm_icon, type;
+
+       unsigned long offset = 0, i, nitems, bytes_after, *props;
+       unsigned char *prop_return;
+       int format;
+
+       net_wm_icon = XInternAtom(display, "_NET_WM_ICON", FALSE);
+       net_supported = XInternAtom(display, "_NET_SUPPORTED", FALSE);
+       do {
+               XGetWindowProperty(display, root, net_supported, offset, 10,
+                                           FALSE, XA_ATOM, &type,
+                                           &format, &nitems, &bytes_after,
+                                           &prop_return);
+
+               if (format != 32 || type != XA_ATOM)
+                       break;
+               offset += nitems;
+
+               props = (void *)prop_return;
+               for (i = 0; i < nitems; i++) {
+                       if (props[i] == net_wm_icon) {
+                               return 1;
+                       }
+               }
+       } while (nitems > 0 && bytes_after > 0);
+
+       return 0;
+}
+
+void *ewmh_icon_alloc(unsigned long **sizes)
+{
+       unsigned long *buf;
+
+       buf = calloc(sizeof *buf, EWMH_ICON_NELEM);
+       if (buf) {
+               sizes[ICON_16x16] = buf;
+               *sizes[ICON_16x16]++ = 16;
+               *sizes[ICON_16x16]++ = 16;
+
+               sizes[ICON_24x24] = sizes[ICON_16x16] + 16*16;
+               *sizes[ICON_24x24]++ = 24;
+               *sizes[ICON_24x24]++ = 24;
+
+               sizes[ICON_32x32] = sizes[ICON_24x24] + 24*24;
+               *sizes[ICON_32x32]++ = 32;
+               *sizes[ICON_32x32]++ = 32;
+
+               sizes[ICON_48x48] = sizes[ICON_32x32] + 32*32;
+               *sizes[ICON_48x48]++ = 48;
+               *sizes[ICON_48x48]++ = 48;
+       }
+
+       return buf;
+}
index f98b3078b2fbb5600a611df90907f25830f3e39f..52afaaecaf9ff2d89ac6be4fbc8103ed9854c214 100644 (file)
@@ -135,9 +135,15 @@ static void proc_exit(Widget w, XEvent *e, String *argv, Cardinal *argc)
 
 static void proc_new_game(Widget w, XEvent *e, String *argv, Cardinal *argc)
 {
+       Widget shell;
+
+       for (shell = w; !XtIsWMShell(shell);)
+               shell = XtParent(shell);
+
        game_reset(&state.board);
        x11_redraw_goal(&state);
        x11_redraw_game(&state);
+       x11_redraw_icon(&state, shell);
 }
 
 static const XtActionsRec menu_actions[] = {
@@ -158,8 +164,11 @@ static XtAppContext app_initialize(int argc, char **argv)
        ui_initialize(&state, shell);
        x11_initialize(&state, XtScreen(shell));
        game_reset(&state.board);
+       state.use_ewmh_icons = ewmh_probe_wm_icon(shell);
        XtRealizeWidget(shell);
 
+       x11_redraw_icon(&state, shell);
+
        return app;
 }
 
index 171739d9e1fcb0e804ba4ee0173542b64548754f..74893d15a2f2b4b07dc81d11ffb0260368968dac 100644 (file)
@@ -29,13 +29,49 @@ struct app_state {
 
        Widget game, goal;
 
+       /* Whether to set _NET_WM_ICON property on WMShell */
+       int use_ewmh_icons;
+
        GC tile_gc;
+       Pixmap icon_pixmap;
        uint_least32_t tile_colour[TILE_MAX-1][3];
 };
 
 void ui_initialize(struct app_state *state, Widget shell);
 void x11_initialize(struct app_state *state, Screen *screen);
+void x11_redraw_icon(struct app_state *state, Widget shell);
 void x11_redraw_goal(struct app_state *state);
 void x11_redraw_game(struct app_state *state);
 
+/*
+ * Helpers for drawing window icons in various sizes.  The tileXX functions
+ * draw one (out of 9) tiles at a particular size using a particular colour
+ * set.  Call for each tile position to draw a complete icon.
+ */
+
+enum { ICON_16x16, ICON_24x24, ICON_32x32, ICON_48x48, ICON_MAX };
+#define EWMH_ICON_NELEM (2+16*16 + 2+24*24 + 2+32*32 + 2+48*48)
+
+void ewmh_tile16(unsigned long *icon, const XColor *c, int tile_x, int tile_y);
+void ewmh_tile24(unsigned long *icon, const XColor *c, int tile_x, int tile_y);
+void ewmh_tile32(unsigned long *icon, const XColor *c, int tile_x, int tile_y);
+void ewmh_tile48(unsigned long *icon, const XColor *c, int tile_x, int tile_y);
+
+/*
+ * Allocate storage for the EWMH _NET_WM_ICON array.  The sizes array is
+ * populated with pointers to the beginning of each icon's pixel data.  For
+ * example, sizes[ICON_24x24] points to the first pixel of the 24x24 image.
+ *
+ * The returned value can then be passed to XChangeProperty to set the icon,
+ * (use EWMH_ICON_NELEM for the number of elements) and must be freed by the
+ * caller.
+ */
+void *ewmh_icon_alloc(unsigned long **sizes);
+
+/*
+ * Check if the root window indicates support for EWMH icons.  Returns 1 if
+ * supported, or 0 otherwise.
+ */
+int ewmh_probe_wm_icon(Widget shell);
+
 #endif
index 9fd8240e2ad5d15685ef65414f2326f5e9a735cb..b9c0aed0daa2e1397a564f5951ff9c47eeba1928 100644 (file)
@@ -4,6 +4,9 @@ X server DISPLAY name to use.
 --geometry=[W][xH][+X[+Y]]
 Set initial window size (W by H) and/or position (X, Y).
 
+--iconic
+Start iconified.
+
 --title=NAME
 Set window title to NAME.
 
index 611223f54b7ba888cafebd6cb547d5f3ba32cc24..95e0cf057646085d502929124552196118fb9b4d 100644 (file)
--- a/src/x11.c
+++ b/src/x11.c
 
 #include <config.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <assert.h>
 
 #include <X11/Intrinsic.h>
 #include <Xm/XmStrDefs.h>
+#include <X11/Xatom.h>
+#include <X11/Shell.h>
 #include "motif.h"
 
+/* Size of the traditional icon pixmap (multiple of 3) */
+#define ICON_SIZE 48
+
 /* TODO user-selectable colours */
 static const char * const colours[][3] = {
        /*primary    bottom      top */
@@ -61,6 +67,9 @@ void x11_initialize(struct app_state *state, Screen *screen)
 
        gcv.line_width = 1;
        state->tile_gc = XCreateGC(display, root, GCLineWidth, &gcv);
+
+       state->icon_pixmap = XCreatePixmap(display, root, ICON_SIZE, ICON_SIZE,
+                                          DefaultDepthOfScreen(screen));
 }
 
 static void draw_tile(struct app_state *state, Display *display, Drawable d,
@@ -94,7 +103,7 @@ static void draw_tile(struct app_state *state, Display *display, Drawable d,
        XFillRectangle(display, d, state->tile_gc, tx+2, ty+2, tw-4, th-4);
 }
 
-static void
+static int
 redraw_tile(struct app_state *state, Display *display, Drawable d,
             uint_fast32_t bit0, uint_fast32_t bit1, uint_fast32_t bit2,
             int x, int y, Dimension w, Dimension h)
@@ -112,24 +121,83 @@ redraw_tile(struct app_state *state, Display *display, Drawable d,
        } else {
                draw_tile(state, display, d, tile, x, y, w, h);
        }
+
+       return tile;
+}
+
+static int
+redraw_goal_tile(struct app_state *state, Display *display, Drawable d,
+                 int x, int y, Dimension w, Dimension h)
+{
+       uint_least16_t *gp = state->board.goal;
+
+       return redraw_tile(state, display, d, gp[0], gp[1], gp[2], x, y, w, h);
 }
 
 void x11_redraw_goal(struct app_state *state)
 {
        Display *display = XtDisplay(state->goal);
-       Window goal = XtWindow(state->goal);
+       Window window = XtWindow(state->goal);
        Dimension w, h;
        int i;
 
        XtVaGetValues(state->goal, XmNwidth, &w, XmNheight, &h, (char *)NULL);
-       w /= 3; h /= 3;
+       for (i = 0; i < 9; i++)
+               redraw_goal_tile(state, display, window, i%3, i/3, w/3, h/3);
+}
+
+/* Render the goal area as the window's icon */
+void x11_redraw_icon(struct app_state *state, Widget shell)
+{
+       Display *display = XtDisplay(shell);
+       Dimension tilesz = ICON_SIZE/3;
+       int i, j, tile;
+
+       XColor colours[(TILE_MAX-1)*COLOUR_MAX];
+       unsigned long *icons[ICON_MAX];
+       void *wm_icon = NULL;
+
+       if (state->use_ewmh_icons && (wm_icon = ewmh_icon_alloc(icons))) {
+               Colormap cmap = DefaultColormapOfScreen(XtScreen(shell));
+
+               for (i = 0; i < TILE_MAX-1; i++) {
+                       for (j = 0; j < COLOUR_MAX; j++) {
+                               XColor *c = &colours[i*COLOUR_MAX+j];
+                               c->pixel = state->tile_colour[i][j];
+                       }
+               }
+
+               XQueryColors(display, cmap, colours, i*j);
+       }
 
        for (i = 0; i < 9; i++) {
-               uint_least16_t *gp = state->board.goal;
+               tile = redraw_goal_tile(state, display, state->icon_pixmap,
+                                       i%3, i/3, tilesz, tilesz);
+
+               if (wm_icon) {
+                       XColor *c = &colours[(tile-1)*COLOUR_MAX];
+                       ewmh_tile16(icons[ICON_16x16], c, i%3, i/3);
+                       ewmh_tile24(icons[ICON_24x24], c, i%3, i/3);
+                       ewmh_tile32(icons[ICON_32x32], c, i%3, i/3);
+                       ewmh_tile48(icons[ICON_48x48], c, i%3, i/3);
+               }
+       }
 
-               redraw_tile(state, display, goal,
-                           gp[0], gp[1], gp[2],
-                           i%3, i/3, w, h);
+       /*
+        * Clear and reset XmNiconPixmap otherwise it seems dtwm will not
+        * notice the changed icon.
+        */
+       XtVaSetValues(shell, XmNiconPixmap, None, (char *)NULL);
+       XtVaSetValues(shell, XmNiconPixmap, state->icon_pixmap, (char *)NULL);
+
+       if (wm_icon) {
+               Atom net_wm_icon = XInternAtom(display, "_NET_WM_ICON", FALSE);
+
+               XChangeProperty(display, XtWindow(shell), net_wm_icon,
+                               XA_CARDINAL, 32, PropModeReplace,
+                               wm_icon, EWMH_ICON_NELEM);
+
+               free(wm_icon);
        }
 }
 
index 46a482fddc6b7ce8692c806c2b861990a3dbb566..8221c2990df93191b4c504ae1791203ea1892e93 100644 (file)
@@ -1,2 +1,3 @@
 /boardmove
+/ewmhicon
 /rng-test
diff --git a/t/ewmhicon.c b/t/ewmhicon.c
new file mode 100644 (file)
index 0000000..e088d41
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Test app for _NET_WM_ICON formatting.
+ * Copyright © 2022 Nick Bowler
+ *
+ * Use a fake colour scheme to generate an icon of the chosen size (16x16,
+ * 24x24, 32x32 or 48x48) and display the pixels as characters.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <X11/Intrinsic.h>
+#include "motif.h"
+
+static const char *progname = "ewmhicon";
+
+static void print_usage(FILE *f)
+{
+       fprintf(f, "Usage: %s size\n", progname);
+}
+
+static const char sizes[][6] = {
+       "16x16", "24x24", "32x32", "48x48"
+};
+
+int to_size_enum(const char *arg)
+{
+       char buf[8];
+       unsigned i;
+
+       if (!strchr(arg, 'x')) {
+               sprintf(buf, "%.3sx%.3s", arg, arg);
+               arg = buf;
+       }
+
+       for (i = 0; i < sizeof sizes / sizeof sizes[0]; i++) {
+               if (!strcmp(arg, sizes[i]))
+                       return i;
+       }
+
+       return -1;
+}
+
+static unsigned long icon_buf[48*48];
+
+int main(int argc, char **argv)
+{
+       void (*tilefunc)(unsigned long *, const XColor *, int, int);
+       XColor c[COLOUR_MAX] = {0};
+       int size, x, y, w, h;
+
+       if (argc > 0)
+               progname = argv[0];
+
+       if (argc != 2) {
+               print_usage(stderr);
+               return EXIT_FAILURE;
+       }
+
+       size = to_size_enum(argv[1]);
+       if (size < 0) {
+               printf("%s: error: invalid size %s\n", progname, argv[1]);
+               return EXIT_FAILURE;
+       }
+
+       switch (size) {
+       case ICON_16x16: tilefunc = ewmh_tile16; w = h = 16; break;
+       case ICON_24x24: tilefunc = ewmh_tile24; w = h = 24; break;
+       case ICON_32x32: tilefunc = ewmh_tile32; w = h = 32; break;
+       case ICON_48x48: tilefunc = ewmh_tile48; w = h = 48; break;
+       default: assert(0);
+       }
+
+       c[COLOUR_PRIMARY].red = 0xffff;
+       c[COLOUR_DARK].green  = 0xffff;
+       c[COLOUR_LIGHT].blue  = 0xffff;
+
+       for (x = 0; x < 3; x++) {
+               for (y = 0; y < 3; y++) {
+                       tilefunc(icon_buf, c, x, y);
+               }
+       }
+
+       for (y = 0; y < h; y++) {
+               for (x = 0; x < w; x++) {
+                       unsigned long val = icon_buf[y*h+x];
+                       int c = ' ';
+
+                       if      (val == 0xffff0000) c = '.'; // primary
+                       else if (val == 0xff00ff00) c = '%'; // dark
+                       else if (val == 0xff0000ff) c = '+'; // light
+
+                       putchar(c);
+               }
+               putchar('\n');
+       }
+
+       return 0;
+}
index 9cfc7afde2c95bdd18718a886f4d823386821871..bfd98190aec8e465cd85a8cea9bd236425babe4b 100644 (file)
@@ -1,3 +1,18 @@
+# Copyright © 2022 Nick Bowler
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
 AT_SETUP([game_do_move zigzag])
 
 AT_CHECK([boardmove m4_do(
diff --git a/tests/gui.at b/tests/gui.at
new file mode 100644 (file)
index 0000000..95d33fd
--- /dev/null
@@ -0,0 +1,162 @@
+# Copyright © 2022 Nick Bowler
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+AT_SETUP([_NET_WM_ICON tiles (16x16)])
+
+AT_CHECK([ewmhicon 16x16], [0], [dnl
+....%+....%+....
+....%+....%+....
+....%+....%+....
+....%+....%+....
+%%%%%+%%%%%+%%%%
+++++++++++++++++
+....%+....%+....
+....%+....%+....
+....%+....%+....
+....%+....%+....
+%%%%%+%%%%%+%%%%
+++++++++++++++++
+....%+....%+....
+....%+....%+....
+....%+....%+....
+....%+....%+....
+])
+
+AT_CLEANUP
+
+AT_SETUP([_NET_WM_ICON tiles (24x24)])
+
+AT_CHECK([ewmhicon 24x24], [0], [dnl
+++++++++++++++++++++++++
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++%%%%%%%+%%%%%%%+%%%%%%%
+++++++++++++++++++++++++
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++%%%%%%%+%%%%%%%+%%%%%%%
+++++++++++++++++++++++++
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++......%+......%+......%
++%%%%%%%+%%%%%%%+%%%%%%%
+])
+
+AT_CLEANUP
+
+AT_SETUP([_NET_WM_ICON tiles (32x32)])
+
+AT_CHECK([ewmhicon 32x32], [0], [dnl
+++++++++++++++++++++++++++++++++
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++%%%%%%%%%%+%%%%%%%%%+%%%%%%%%%%
+++++++++++++++++++++++++++++++++
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++%%%%%%%%%%+%%%%%%%%%+%%%%%%%%%%
+++++++++++++++++++++++++++++++++
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++.........%+........%+.........%
++%%%%%%%%%%+%%%%%%%%%+%%%%%%%%%%
+])
+
+AT_CLEANUP
+
+AT_SETUP([_NET_WM_ICON tiles (48x48)])
+
+AT_CHECK([ewmhicon 48x48], [0], [dnl
+++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++%+++++++++++++++%+++++++++++++++%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%
++%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%
+++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++%+++++++++++++++%+++++++++++++++%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%
++%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%
+++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++%+++++++++++++++%+++++++++++++++%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++............%%++............%%++............%%
+++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%++%%%%%%%%%%%%%%
++%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%+%%%%%%%%%%%%%%%
+])
+
+AT_CLEANUP
index 7e8855ec3fa599d7a36dbf0f29bedeb09d2ae97f..104f7822f34039698595b24c782fd633c22e2afe 100644 (file)
@@ -17,3 +17,4 @@ AT_INIT
 AT_COLOR_TESTS
 
 m4_include([tests/game.at])
+m4_include([tests/gui.at])