Subject: [Patch] MinIconSize/MaxIconSize

From: Steve Talley <[email-masked]>
Date: Sat, 22 Jun 2002 16:25:27 -0600

One of the things I liked about MWM (CDE actually) was that the size
of the icons could be limited/controlled.  In FVWM this isn't
possible, short of specifying an icon image for each app.  The result
is that people who use IconBox/IconGrid may have icons that are too
big for the grid spot.  The FVWM man page mentions FVWM's inability to
clip icons in this case.

Another issue that is mildly bothersome is that the width of the icon
title bar is determined by the width of the icon image.  So small
icons result in a smaller area to click on.

The attached patch addresses both of these issues.  It provides
support for two new Style subcommands:

    MinIconSize width height
    MaxIconSize width height

These allow you to limit/control the size of both user-provided and
application-provided icon images.  Icon images that are smaller than
MaxIconSize are clipped.  Icon images that are bigger than MinIconSize
are padded.

Setting both MinIconSize and MaxIconSize to the same dimensions has
the effect of enforcing a rigid size for the icon image.  For example:

    Style * MaxIconSize 64 50
    Style * MinIconSize 64 50

This results in the same behavior as MWM/CDE.  See the attached
before/after images to see the efect of the patch and the above
settings.  The same IconBox/IconGrid settings are used in each case.

Please take a look at the attached patch and let me know if there are
any questions/suggestions/etc.  It is based on the latest CVS
snapshot.

Thanks,

Steve
Index: fvwm/add_window.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/add_window.c,v
retrieving revision 1.295
diff -u -u -r1.295 add_window.c
--- fvwm/add_window.c	2002/06/17 00:33:06	1.295
+++ fvwm/add_window.c	2002/06/22 21:48:17
@@ -1057,6 +1057,25 @@
 	return;
 }
 
+/*
+ * Copy icon size limits from window_style structure to FvwmWindow
+ * structure.
+ */
+void setup_icon_size_limits(FvwmWindow *fw, window_style *pstyle)
+{
+	fw->min_icon_width = SHAS_MIN_ICON_WIDTH(&pstyle->flags) ?
+		SGET_MIN_ICON_WIDTH(*pstyle) : MIN_ALLOWABLE_ICON_WIDTH;
+
+	fw->max_icon_width = SHAS_MAX_ICON_WIDTH(&pstyle->flags) ?
+		SGET_MAX_ICON_WIDTH(*pstyle) : MAX_ALLOWABLE_ICON_WIDTH;
+
+	fw->min_icon_height = SHAS_MIN_ICON_HEIGHT(&pstyle->flags) ?
+		SGET_MIN_ICON_HEIGHT(*pstyle) : MIN_ALLOWABLE_ICON_HEIGHT;
+
+	fw->max_icon_height = SHAS_MAX_ICON_HEIGHT(&pstyle->flags) ?
+		SGET_MAX_ICON_HEIGHT(*pstyle) : MAX_ALLOWABLE_ICON_HEIGHT;
+}
+
 Bool setup_window_placement(
 	FvwmWindow *fw, window_style *pstyle, rectangle *attr_g,
 	initial_window_options_type *win_opts)
@@ -2074,6 +2093,9 @@
 
 	/****** border width ******/
 	XSetWindowBorderWidth(dpy, FW_W(fw), 0);
+
+	/****** icon size limits ******/
+	setup_icon_size_limits(fw, &style);
 
 	/***** placement penalities *****/
 	setup_placement_penalty(fw, &style);
Index: fvwm/add_window.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/add_window.h,v
retrieving revision 1.26
diff -u -u -r1.26 add_window.h
--- fvwm/add_window.h	2002/03/24 19:19:24	1.26
+++ fvwm/add_window.h	2002/06/22 21:48:17
@@ -57,6 +57,8 @@
 	FvwmWindow *fw);
 void setup_frame_size_limits(
 	FvwmWindow *fw, window_style *pstyle);
+void setup_icon_size_limits(
+	FvwmWindow *fw, window_style *pstyle);
 void increase_icon_hint_count(
 	FvwmWindow *fw);
 void change_icon(
Index: fvwm/fvwm.1
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.1,v
retrieving revision 1.23
diff -u -u -r1.23 fvwm.1
--- fvwm/fvwm.1	2002/06/21 14:32:34	1.23
+++ fvwm/fvwm.1	2002/06/22 21:48:25
@@ -5334,6 +5334,7 @@
 .IR BorderWidth ", " HandleWidth ,
 .IR NoIcon " / " Icon ", " MiniIcon ,
 .IR IconBox ", " IconGrid ", " IconFill ,
+.IR MinIconSize ", " MaxIconSize ", "
 .IR NoTitle " / " Title ,
 .IR TitleAtBottom " / " TitleAtLeft " / " TitleAtRight " / " TitleAtTop ,
 .IR LeftTitleRotatedCW " / " LeftTitleRotatedCCW,
@@ -5881,8 +5882,9 @@
 values for the icon grid, looking for a free space. The default
 grid is 3 by 3 pixels which gives a tightly packed appearance. To
 get a more regular appearance use a grid larger than your largest
-icon. Currently there is no way to clip an icon to a maximum
-size. An
+icon. Use the
+.I MaxIconSize
+definition to clip an icon to a maximum size. An
 .I IconGrid
 definition must follow the
 .B IconBox
@@ -5913,6 +5915,35 @@
 .EX
 Style * IconBox -80x240-1-1, IconFill b r
 .EE
+.I MinIconSize
+and
+.I MaxIconSize
+set limits on the size of an icon image.  Both user-provided
+and application-provided icon images are affected.
+.EX
+.RI MinIconSize " " width " [" height "]"
+.RI MaxIconSize " " width " [" height "]"
+.EE
+.I width
+and
+.I height
+are measured in pixels.  The value of "-1" can be used to specify the
+defualt value for either width or height.  Icon images that are
+smaller than
+.I MaxIconSize
+are clipped.  Icon images that are bigger than
+.I MinIconSize
+are padded.  Set
+.I MaxIconSize
+and
+.I MinIconSize
+to the same dimensions to enforce a rigid size for the icon image:
+.EX
+    Style * MaxIconSize 64 50
+    Style * MinIconSize 64 50
+.EE
+Note that application-provided icon windows are not affected.
+
 .I MiniIcon
 specifies a pixmap to use as the miniature icon for the
 window. This miniature icon can be drawn in a title-bar button
Index: fvwm/fvwm.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.h,v
retrieving revision 1.194
diff -u -u -r1.194 fvwm.h
--- fvwm/fvwm.h	2002/06/17 00:33:06	1.194
+++ fvwm/fvwm.h	2002/06/22 21:48:26
@@ -525,6 +525,10 @@
 	unsigned has_handle_width : 1;
 	unsigned has_icon : 1;
 	unsigned has_icon_boxes : 1;
+	unsigned has_min_icon_width : 1;
+	unsigned has_max_icon_width : 1;
+	unsigned has_min_icon_height : 1;
+	unsigned has_max_icon_height : 1;
 	unsigned has_max_window_size : 1;
 	unsigned has_window_shade_steps : 1;
 	unsigned has_mini_icon : 1;
@@ -576,6 +580,10 @@
 #ifdef USEDECOR
 	char *decor_name;
 #endif
+	int min_icon_width;
+	int max_icon_width;
+	int min_icon_height;
+	int max_icon_height;
 	char *icon_font;
 	char *window_font;
 	char *fore_color_name;
@@ -764,6 +772,10 @@
 
 	int default_layer;
 	int layer;
+	int min_icon_width;
+	int max_icon_width;
+	int min_icon_height;
+	int max_icon_height;
 	int max_window_width;
 	int max_window_height;
 	int shade_anim_steps;
Index: fvwm/icons.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/icons.c,v
retrieving revision 1.181
diff -u -u -r1.181 icons.c
--- fvwm/icons.c	2002/06/19 14:11:27	1.181
+++ fvwm/icons.c	2002/06/22 21:48:28
@@ -254,6 +254,107 @@
       break;
     }
   }
+
+  /* Resize icon if necessary */
+  if ((IS_ICON_OURS(fw)) &&
+    fw->icon_g.picture_w_g.height > 0 && fw->icon_g.picture_w_g.height > 0)
+  {
+    unsigned int newWidth = fw->icon_g.picture_w_g.width;
+    unsigned int newHeight = fw->icon_g.picture_w_g.height;
+    Boolean resize = False;
+
+    if(newWidth < fw->min_icon_width) {
+      newWidth = fw->min_icon_width;
+      resize = True;
+    } else
+
+    if(newWidth > fw->max_icon_width) {
+      newWidth = fw->max_icon_width;
+      resize = True;
+    }
+
+    if(newHeight < fw->min_icon_height) {
+      newHeight = fw->min_icon_height;
+      resize = True;
+    } else
+
+    if(newHeight > fw->max_icon_height) {
+      newHeight = fw->max_icon_height;
+      resize = True;
+    }
+
+    if(resize) {
+      ICON_DBG((stderr,"ciw: Changing icon (%s) from %dx%d to %dx%d\n",
+        fw->name,
+        fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height,
+        newWidth, newHeight));
+
+      /* Resize the icon Pixmap */
+      SetIconPixmapSize(&(fw->iconPixmap),
+        fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height,
+        fw->iconDepth, newWidth, newHeight,
+        (IS_PIXMAP_OURS(fw)));
+
+      /* Resize the icon mask Pixmap if one was defined */
+      if(fw->icon_maskPixmap) {
+        SetIconPixmapSize(&(fw->icon_maskPixmap),
+          fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height,
+          1, newWidth, newHeight, (IS_PIXMAP_OURS(fw)));
+      }
+
+      /* Set the new dimensions of the icon window */
+      fw->icon_g.picture_w_g.width = newWidth;
+      fw->icon_g.picture_w_g.height = newHeight;
+    }
+  }
+}
+
+/****************************************************************************
+ *
+ * Resizes the given icon Pixmap.
+ *
+ ****************************************************************************/
+static void SetIconPixmapSize(Pixmap *icon,
+    unsigned int width, unsigned int height, unsigned int depth,
+    unsigned int newWidth, unsigned int newHeight,
+    unsigned int freeOldPixmap)
+{
+    Pixmap oldPixmap;
+    GC gc;
+    XGCValues gc_init;
+
+    /* Check for invalid dimensions */
+    if(newWidth == 0 || newHeight == 0) {
+        return;
+    }
+
+    /* Save the existing Pixmap */
+    oldPixmap = *icon;
+
+    /* Create a new Pixmap with the new dimensions */
+    *icon = XCreatePixmap(
+        dpy, oldPixmap, newWidth, newHeight, depth);
+
+    /* Zero out new Pixmap */
+    gc = XCreateGC(dpy, *icon, 0, &gc_init);
+    XSetForeground(dpy, gc, 0);
+    XFillRectangle(dpy, *icon, gc, 0, 0, newWidth, newHeight);
+
+    /*
+     * Copy old Pixmap onto new.  Center horizontally.  Center
+     * vertically if the new height is smaller than the old.
+     * Otherwise, place the icon on the bottom, along the title
+     * bar.
+     */
+    XCopyArea(dpy, oldPixmap, *icon, gc, 0, 0, width, height,
+        (newWidth - width)/2, newHeight > height ?
+            newHeight - height : (newHeight - height)/2);
+
+    XFreeGC(dpy, gc);
+
+    if(freeOldPixmap) {
+        XFreePixmap(dpy, oldPixmap);
+    }
 }
 
 /****************************************************************************
Index: fvwm/icons.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/icons.h,v
retrieving revision 1.10
diff -u -u -r1.10 icons.h
--- fvwm/icons.h	2002/06/18 10:52:13	1.10
+++ fvwm/icons.h	2002/06/22 21:48:28
@@ -29,6 +29,10 @@
 void ChangeIconPixmap(FvwmWindow *fw);
 void RedoIconName(FvwmWindow *);
 void DrawIconWindow(FvwmWindow *);
+void SetIconPixmapSize(Pixmap *icon,
+    unsigned int width, unsigned int height, unsigned int depth,
+    unsigned int newWidth, unsigned int newHeight,
+    unsigned int freeOldPixmap);
 void CreateIconWindow(FvwmWindow *fw, int def_x, int def_y);
 void Iconify(FvwmWindow *fw, initial_window_options_type *win_opts);
 void DeIconify(FvwmWindow *);
Index: fvwm/style.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/style.c,v
retrieving revision 1.162
diff -u -u -r1.162 style.c
--- fvwm/style.c	2002/06/18 10:52:14	1.162
+++ fvwm/style.c	2002/06/22 21:48:32
@@ -446,6 +446,22 @@
 	{
 		SSET_HANDLE_WIDTH(*merged_style, SGET_HANDLE_WIDTH(*add_style));
 	}
+	if (add_style->flags.has_max_icon_width)
+	{
+		SSET_MAX_ICON_WIDTH(*merged_style, SGET_MAX_ICON_WIDTH(*add_style));
+	}
+	if (add_style->flags.has_min_icon_width)
+	{
+		SSET_MIN_ICON_WIDTH(*merged_style, SGET_MIN_ICON_WIDTH(*add_style));
+	}
+	if (add_style->flags.has_max_icon_height)
+	{
+		SSET_MAX_ICON_HEIGHT(*merged_style, SGET_MAX_ICON_HEIGHT(*add_style));
+	}
+	if (add_style->flags.has_min_icon_height)
+	{
+		SSET_MIN_ICON_HEIGHT(*merged_style, SGET_MIN_ICON_HEIGHT(*add_style));
+	}
 	if (add_style->flags.has_max_window_size)
 	{
 		SSET_MAX_WINDOW_WIDTH(
@@ -2147,6 +2163,68 @@
 	  SFSET_DO_IGNORE_MOUSE_FOCUS_CLICK_MOTION(*ptmpstyle, 0);
 	  SMSET_DO_IGNORE_MOUSE_FOCUS_CLICK_MOTION(*ptmpstyle, 1);
 	  SCSET_DO_IGNORE_MOUSE_FOCUS_CLICK_MOTION(*ptmpstyle, 1);
+	}
+	else if (StrEquals(token, "MINICONSIZE"))
+	{
+	  int vals[2];
+	  found = True;
+
+	  switch(GetIntegerArguments(rest, &rest, vals, 2)) {
+	    /* Min icon height */
+	    case 2:
+	        if(vals[1] != UNSPECIFIED_ICON_DIMENSION &&
+	           vals[1] >= MIN_ALLOWABLE_ICON_HEIGHT &&
+	           vals[1] <= MAX_ALLOWABLE_ICON_HEIGHT)
+	        {
+	            SSET_MIN_ICON_HEIGHT(*ptmpstyle, vals[1]);
+	            ptmpstyle->flags.has_min_icon_height = 1;
+	            ptmpstyle->flag_mask.has_min_icon_height = 1;
+	            ptmpstyle->change_mask.has_min_icon_height = 1;
+	        }
+	    /* Min icon width */
+	    case 1:
+	        if(vals[0] != UNSPECIFIED_ICON_DIMENSION &&
+	           vals[0] >= MIN_ALLOWABLE_ICON_WIDTH &&
+	           vals[0] <= MAX_ALLOWABLE_ICON_WIDTH)
+	        {
+	            SSET_MIN_ICON_WIDTH(*ptmpstyle, vals[0]);
+	            ptmpstyle->flags.has_min_icon_width = 1;
+	            ptmpstyle->flag_mask.has_min_icon_width = 1;
+	            ptmpstyle->change_mask.has_min_icon_width = 1;
+	        }
+	    break;
+	  }
+	}
+	else if (StrEquals(token, "MAXICONSIZE"))
+	{
+	  int vals[2];
+	  found = True;
+
+	  switch(GetIntegerArguments(rest, &rest, vals, 2)) {
+	    /* Max icon height */
+	    case 2:
+	        if(vals[1] != UNSPECIFIED_ICON_DIMENSION &&
+	           vals[1] >= MIN_ALLOWABLE_ICON_HEIGHT &&
+	           vals[1] <= MAX_ALLOWABLE_ICON_HEIGHT)
+	        {
+	            SSET_MAX_ICON_HEIGHT(*ptmpstyle, vals[1]);
+	            ptmpstyle->flags.has_max_icon_height = 1;
+	            ptmpstyle->flag_mask.has_max_icon_height = 1;
+	            ptmpstyle->change_mask.has_max_icon_height = 1;
+	        }
+	    /* Max icon width */
+	    case 1:
+	        if(vals[0] != UNSPECIFIED_ICON_DIMENSION &&
+	           vals[0] >= MIN_ALLOWABLE_ICON_WIDTH &&
+	           vals[0] <= MAX_ALLOWABLE_ICON_WIDTH)
+	        {
+	            SSET_MAX_ICON_WIDTH(*ptmpstyle, vals[0]);
+	            ptmpstyle->flags.has_max_icon_width = 1;
+	            ptmpstyle->flag_mask.has_max_icon_width = 1;
+	            ptmpstyle->change_mask.has_max_icon_width = 1;
+	        }
+	    break;
+	  }
 	}
 	else if (StrEquals(token, "MAXWINDOWSIZE"))
 	{
Index: fvwm/style.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/style.h,v
retrieving revision 1.58
diff -u -u -r1.58 style.h
--- fvwm/style.h	2002/05/26 21:47:31	1.58
+++ fvwm/style.h	2002/06/22 21:48:33
@@ -27,6 +27,10 @@
 #define SHAS_HANDLE_WIDTH(sf)	      ((sf)->has_handle_width)
 #define SHAS_ICON(sf)		      ((sf)->has_icon)
 #define SHAS_ICON_BOXES(sf)	      ((sf)->has_icon_boxes)
+#define SHAS_MAX_ICON_WIDTH(sf)       ((sf)->has_max_icon_width)
+#define SHAS_MAX_ICON_HEIGHT(sf)      ((sf)->has_max_icon_height)
+#define SHAS_MIN_ICON_WIDTH(sf)       ((sf)->has_min_icon_width)
+#define SHAS_MIN_ICON_HEIGHT(sf)      ((sf)->has_min_icon_height)
 #define SHAS_MAX_WINDOW_SIZE(sf)      ((sf)->has_max_window_size)
 #define SHAS_WINDOW_SHADE_STEPS(sf)   ((sf)->has_window_shade_steps)
 #define SHAS_MINI_ICON(sf)	      ((sf)->has_mini_icon)
@@ -528,6 +532,14 @@
 #define SSET_START_PAGE_Y(s,x)	      ((s).start_page_y = (x))
 #define SGET_START_SCREEN(s)	      ((s).start_screen)
 #define SSET_START_SCREEN(s,x)	      ((s).start_screen = (x))
+#define SGET_MIN_ICON_WIDTH(s)        ((s).min_icon_width)
+#define SSET_MIN_ICON_WIDTH(s,x)      ((s).min_icon_width = (x))
+#define SGET_MIN_ICON_HEIGHT(s)       ((s).min_icon_height)
+#define SSET_MIN_ICON_HEIGHT(s,x)     ((s).min_icon_height = (x))
+#define SGET_MAX_ICON_WIDTH(s)        ((s).max_icon_width)
+#define SSET_MAX_ICON_WIDTH(s,x)      ((s).max_icon_width = (x))
+#define SGET_MAX_ICON_HEIGHT(s)       ((s).max_icon_height)
+#define SSET_MAX_ICON_HEIGHT(s,x)     ((s).max_icon_height = (x))
 #define SGET_MAX_WINDOW_WIDTH(s)      ((s).max_window_width)
 #define SSET_MAX_WINDOW_WIDTH(s,x)    ((s).max_window_width = (x))
 #define SGET_MAX_WINDOW_HEIGHT(s)     ((s).max_window_height)
Index: libs/defaults.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/libs/defaults.h,v
retrieving revision 1.49
diff -u -u -r1.49 defaults.h
--- libs/defaults.h	2002/06/18 10:52:17	1.49
+++ libs/defaults.h	2002/06/22 21:48:34
@@ -152,6 +152,14 @@
 #define DEFAULT_MIN_MAX_WINDOW_HEIGHT	 100 /* pixels */
 #define DEFAULT_MAX_MAX_WINDOW_WIDTH   32767 /* pixels */
 #define DEFAULT_MAX_MAX_WINDOW_HEIGHT  32767 /* pixels */
+
+/*** icon geometry ***/
+#define UNSPECIFIED_ICON_DIMENSION   -1
+#define MIN_ALLOWABLE_ICON_WIDTH           0 /* pixels */
+#define MIN_ALLOWABLE_ICON_HEIGHT          0 /* pixels */
+#define MAX_ALLOWABLE_ICON_WIDTH       32767 /* pixels */
+#define MAX_ALLOWABLE_ICON_HEIGHT      32767 /* pixels */
+
 /* this value is used in a bugfix */
 #define WINDOW_FREAKED_OUT_SIZE	       65500 /* pixels */

---

From: Mikhael Goikhman <[email-masked]>
Date: Sun, 23 Jun 2002 06:46:12 +0000

> MaxIconSize are clipped.  Icon images that are bigger than MinIconSize

Seems like a good patch. Some notes.

Is it possible to replace int with unsigned char? This will save
12 * 500 = 6Kb for me. Icon sizes bigger than 1/4 of screen are bad.

>     Style * MinIconSize 64 50

Since this is the main usage, is this possible to change the syntax to:

  Style * IconSize x y[, x2 y2]

where one pair means both min and max values?

Another optimization would be to say that size 0 is invalid so it may be
used to switch the feature off. Any of the following 3:

  Style * IconSize
  Style * IconSize 0 0
  Style * IconSize 0 0, 0 0

may disable the feature completely. It would be possible to only partialy
disable it (IconSize 0 0, 48 0). This should save another 4 bits and seems
more consistent than the logic in the patch that allows one integer in the
pair (I don't think this should be allowed as ambiguous, use 0 instead).

> any questions/suggestions/etc.  It is based on the latest CVS

Regards,
Mikhael.
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Steve Talley <[email-masked]>
Date: Sun, 23 Jun 2002 22:30:25 -0600

Mikhael Goikhman wrote:

> > One of the things I liked about MWM (CDE actually) was that the
> > size of the icons could be limited/controlled.  In FVWM this isn't
> > possible, short of specifying an icon image for each app.  The
> > result is that people who use IconBox/IconGrid may have icons that
> > are too big for the grid spot.  The FVWM man page mentions FVWM's
> > inability to clip icons in this case.
> >
> > Another issue that is mildly bothersome is that the width of the
> > icon title bar is determined by the width of the icon image.  So
> > small icons result in a smaller area to click on.
> >
> > These allow you to limit/control the size of both user-provided
> > and application-provided icon images.  Icon images that are
> > smaller than MaxIconSize are clipped.  Icon images that are bigger
> > than MinIconSize are padded.
>

Thanks Mikhael.  I have implemented all of your suggestions in the
attached patch.  Comments inline:

> Is it possible to replace int with unsigned char? This will save 12
> * 500 = 6Kb for me.

Sure.  I just looked at a 256x256 icon on my desktop (at 1152x864),
and it was huge.  However, for *much* larger resolutions in the
future, 256x256 may not be all that big...

> Icon sizes bigger than 1/4 of screen are bad.
>
> > Setting both MinIconSize and MaxIconSize to the same dimensions
> > has the effect of enforcing a rigid size for the icon image.  For
> > example:
> >

Excellent idea.  Certainly simplifies the syntax.

> Another optimization would be to say that size 0 is invalid so it
> may be used to switch the feature off. Any of the following 3:
>
>   Style * IconSize
>   Style * IconSize 0 0
> may disable the feature completely. It would be possible to only
> partialy disable it (IconSize 0 0, 48 0). This should save another 4
> bits and seems more consistent than the logic in the patch that
> allows one integer in the pair (I don't think this should be allowed
> as ambiguous, use 0 instead).

Agreed.  However, I have made -1 the disable/default value, since 0 is
a valid maximum dimension.  Consider the setting:

    Style * IconSize 64 0

This will result in something like the attached zeroheight.jpg
(IconGrid is defined) or zeroheight2.jpg (IconGrid not defined),
effectively allowing the user to specify that no image is to be shown
but still be able size the icon title.

> > Please take a look at the attached patch and let me know if there
> > are any questions/suggestions/etc.  It is based on the latest CVS
> > snapshot.
>
> Regards, Mikhael.

Thanks again Mikhael.  Let me know if you have any other
suggestions/comments on the latest patch.

Steve
Index: fvwm/add_window.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/add_window.c,v
retrieving revision 1.295
diff -u -r1.295 add_window.c
--- fvwm/add_window.c	2002/06/17 00:33:06	1.295
+++ fvwm/add_window.c	2002/06/24 04:07:02
@@ -1057,6 +1057,25 @@
 	return;
 }
 
+/*
+ * Copy icon size limits from window_style structure to FvwmWindow
+ * structure.
+ */
+void setup_icon_size_limits(FvwmWindow *fw, window_style *pstyle)
+{
+    if (SHAS_ICON_SIZE_LIMITS(&pstyle->flags)) {
+        fw->min_icon_width = SGET_MIN_ICON_WIDTH(*pstyle);
+        fw->min_icon_height = SGET_MIN_ICON_HEIGHT(*pstyle);
+        fw->max_icon_width = SGET_MAX_ICON_WIDTH(*pstyle);
+        fw->max_icon_height = SGET_MAX_ICON_HEIGHT(*pstyle);
+    } else {
+        fw->min_icon_width = MIN_ALLOWABLE_ICON_DIMENSION;
+        fw->min_icon_height = MIN_ALLOWABLE_ICON_DIMENSION;
+        fw->max_icon_width = MAX_ALLOWABLE_ICON_DIMENSION;
+        fw->max_icon_height = MAX_ALLOWABLE_ICON_DIMENSION;
+    }
+}
+
 Bool setup_window_placement(
 	FvwmWindow *fw, window_style *pstyle, rectangle *attr_g,
 	initial_window_options_type *win_opts)
@@ -2074,6 +2093,9 @@

 	/***** placement penalities *****/
 	setup_placement_penalty(fw, &style);
Index: fvwm/add_window.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/add_window.h,v
retrieving revision 1.26
diff -u -r1.26 add_window.h
--- fvwm/add_window.h	2002/03/24 19:19:24	1.26
+++ fvwm/add_window.h	2002/06/24 04:07:05
@@ -57,6 +57,8 @@
 	FvwmWindow *fw);
 void setup_frame_size_limits(
 	FvwmWindow *fw, window_style *pstyle);
+void setup_icon_size_limits(
+	FvwmWindow *fw, window_style *pstyle);
 void increase_icon_hint_count(
 	FvwmWindow *fw);
 void change_icon(
Index: fvwm/fvwm.1
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.1,v
retrieving revision 1.23
diff -u -r1.23 fvwm.1
--- fvwm/fvwm.1	2002/06/21 14:32:34	1.23
+++ fvwm/fvwm.1	2002/06/24 04:07:13
@@ -5333,7 +5333,7 @@
 slashes ('/').  The last style in these groups is the default.
 .IR BorderWidth ", " HandleWidth ,
 .IR NoIcon " / " Icon ", " MiniIcon ,
-.IR IconBox ", " IconGrid ", " IconFill ,
+.IR IconBox ", " IconGrid ", " IconFill ", " IconSize ,
 .IR NoTitle " / " Title ,
 .IR TitleAtBottom " / " TitleAtLeft " / " TitleAtRight " / " TitleAtTop ,
 .IR LeftTitleRotatedCW " / " LeftTitleRotatedCCW,
@@ -5881,8 +5881,9 @@
 values for the icon grid, looking for a free space. The default
 grid is 3 by 3 pixels which gives a tightly packed appearance. To
 get a more regular appearance use a grid larger than your largest
-icon. Currently there is no way to clip an icon to a maximum
-size. An
+icon. Use the
+.I IconSize
+definition to clip an icon to a maximum size. An
 .I IconGrid
 definition must follow the
 .B IconBox
@@ -5913,6 +5914,39 @@
 .EX
 Style * IconBox -80x240-1-1, IconFill b r
 .EE
+.I IconSize
+sets limits on the size of an icon image.  Both user-provided
+and application-provided icon images are affected.
+.EX
+.RI IconSize " " width " " height " [ " maxwidth " " maxheight " ]"
+.EE
+All arguments are measured in pixels.  When all four arguments are
+passed to
+.I IconSize,
+.I width
+and
+.I height
+represent the minimum size of an icon, and
+.I maxwidth
+and
+.I maxheight
+represent the maximum size of an icon.  Icon images that are smaller
+than the minimum size are padded.  Icon images that are bigger than
+the maximum size are clipped.
+
+If only two arguments are passed to
+.I IconSize,
+.I width
+and
+.I height
+represent the absolute size of an icon.  Icons covered by this style
+will be padded or clipped to achieve the given size.
+
+The value of "-1" can be used in place of any of the arguments to
+specify the default value for that dimension.
+
+Note that application-provided icon windows are not affected.
+
 .I MiniIcon
 specifies a pixmap to use as the miniature icon for the
 window. This miniature icon can be drawn in a title-bar button
Index: fvwm/fvwm.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.h,v
retrieving revision 1.194
diff -u -r1.194 fvwm.h
--- fvwm/fvwm.h	2002/06/17 00:33:06	1.194
+++ fvwm/fvwm.h	2002/06/24 04:07:14
@@ -525,6 +525,7 @@
 	unsigned has_handle_width : 1;
 	unsigned has_icon : 1;
 	unsigned has_icon_boxes : 1;
+	unsigned has_icon_size_limits : 1;
 	unsigned has_max_window_size : 1;
 	unsigned has_window_shade_steps : 1;
 	unsigned has_mini_icon : 1;
@@ -576,6 +577,10 @@
 #ifdef USEDECOR
 	char *decor_name;
 #endif
+	unsigned char min_icon_width;
+	unsigned char max_icon_width;
+	unsigned char min_icon_height;
+	unsigned char max_icon_height;
 	char *icon_font;
 	char *window_font;
 	char *fore_color_name;
@@ -764,6 +769,10 @@
 
 	int default_layer;
 	int layer;
+	unsigned char min_icon_width;
+	unsigned char max_icon_width;
+	unsigned char min_icon_height;
+	unsigned char max_icon_height;
 	int max_window_width;
 	int max_window_height;
 	int shade_anim_steps;
Index: fvwm/icons.c
diff -u -r1.181 icons.c
+++ fvwm/icons.c	2002/06/24 04:07:16
 
 /****************************************************************************
Index: fvwm/icons.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/icons.h,v
retrieving revision 1.10
diff -u -r1.10 icons.h
--- fvwm/icons.h	2002/06/18 10:52:13	1.10
+++ fvwm/icons.h	2002/06/24 04:07:16
@@ -29,6 +29,10 @@
 void ChangeIconPixmap(FvwmWindow *fw);
 void RedoIconName(FvwmWindow *);
 void DrawIconWindow(FvwmWindow *);
+void SetIconPixmapSize(Pixmap *icon,
+    unsigned int width, unsigned int height, unsigned int depth,
+    unsigned int newWidth, unsigned int newHeight,
+    unsigned int freeOldPixmap);
 void CreateIconWindow(FvwmWindow *fw, int def_x, int def_y);
 void Iconify(FvwmWindow *fw, initial_window_options_type *win_opts);
 void DeIconify(FvwmWindow *);
Index: fvwm/style.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/style.c,v
retrieving revision 1.162
diff -u -r1.162 style.c
--- fvwm/style.c	2002/06/18 10:52:14	1.162
+++ fvwm/style.c	2002/06/24 04:07:19
@@ -446,6 +446,13 @@
 	{
 		SSET_HANDLE_WIDTH(*merged_style, SGET_HANDLE_WIDTH(*add_style));
 	}
+	if (add_style->flags.has_icon_size_limits)
+	{
+		SSET_MIN_ICON_WIDTH(*merged_style, SGET_MIN_ICON_WIDTH(*add_style));
+		SSET_MIN_ICON_HEIGHT(*merged_style, SGET_MIN_ICON_HEIGHT(*add_style));
+		SSET_MAX_ICON_WIDTH(*merged_style, SGET_MAX_ICON_WIDTH(*add_style));
+		SSET_MAX_ICON_HEIGHT(*merged_style, SGET_MAX_ICON_HEIGHT(*add_style));
+	}
 	if (add_style->flags.has_max_window_size)
 	{
 		SSET_MAX_WINDOW_WIDTH(
@@ -1686,6 +1693,67 @@
 	  SFSET_HAS_NO_ICON_TITLE(*ptmpstyle, 0);
 	  SMSET_HAS_NO_ICON_TITLE(*ptmpstyle, 1);
 	  SCSET_HAS_NO_ICON_TITLE(*ptmpstyle, 1);
+	}
+	else if (StrEquals(token, "IconSize"))
+	{
+	  int vals[4];
+      int i;
+	  found = True;
+
+	  switch(GetIntegerArguments(rest, &rest, vals, 4)) {
+	
+	    default:
+	      fvwm_msg(ERR, "CMD_Style",
+	        "IconSize requires exactly 2 or 4 numerical arguments");
+	    break;
+	
+	    /* No break is intentional */
+	    case 2:
+	      /* Max and min values are the same */
+	      vals[2] = vals[0];
+	      vals[3] = vals[1];
+	
+	    case 4:
+	
+	      /* Validate values */
+	      for(i = 0; i < 4; i++) {
+	        int use_default = 0;
+	
+	        if( vals[i] < MIN_ALLOWABLE_ICON_DIMENSION ||
+	          vals[i] > MAX_ALLOWABLE_ICON_DIMENSION)
+	        {
+	          fvwm_msg(ERR, "CMD_Style",
+	            "IconSize dimension (%d) not in valid range (%d-%d)",
+	            vals[i], MIN_ALLOWABLE_ICON_DIMENSION,
+	            MAX_ALLOWABLE_ICON_DIMENSION);
+
+	          use_default = 1;
+	        } else
+
+	        /* User requests default value for this dimension */
+	        if(vals[i] == UNSPECIFIED_ICON_DIMENSION) {
+	          use_default = 1;
+	        }
+
+	        if(use_default) {
+	          /* Set default value for this dimension.  The
+	           * first two indexes refer to min values, the
+	           * latter two to max values. */
+	          vals[i] = i < 2 ? MIN_ALLOWABLE_ICON_DIMENSION :
+	            MAX_ALLOWABLE_ICON_DIMENSION;
+	        }
+	      }
+
+	      SSET_MIN_ICON_WIDTH(*ptmpstyle, vals[0]);
+	      SSET_MIN_ICON_HEIGHT(*ptmpstyle, vals[1]);
+	      SSET_MAX_ICON_WIDTH(*ptmpstyle, vals[2]);
+	      SSET_MAX_ICON_HEIGHT(*ptmpstyle, vals[3]);
+
+	      ptmpstyle->flags.has_icon_size_limits = 1;
+	      ptmpstyle->flag_mask.has_icon_size_limits = 1;
+	      ptmpstyle->change_mask.has_icon_size_limits = 1;
+	    break;
+	  }
 	}
 	else if (StrEquals(token, "IconBox"))
 	{
Index: fvwm/style.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/style.h,v
retrieving revision 1.58
diff -u -r1.58 style.h
--- fvwm/style.h	2002/05/26 21:47:31	1.58
+++ fvwm/style.h	2002/06/24 04:07:21
@@ -27,6 +27,7 @@
 #define SHAS_HANDLE_WIDTH(sf)	      ((sf)->has_handle_width)
 #define SHAS_ICON(sf)		      ((sf)->has_icon)
 #define SHAS_ICON_BOXES(sf)	      ((sf)->has_icon_boxes)
+#define SHAS_ICON_SIZE_LIMITS(sf)     ((sf)->has_icon_size_limits)
 #define SHAS_MAX_WINDOW_SIZE(sf)      ((sf)->has_max_window_size)
 #define SHAS_WINDOW_SHADE_STEPS(sf)   ((sf)->has_window_shade_steps)
 #define SHAS_MINI_ICON(sf)	      ((sf)->has_mini_icon)
@@ -528,6 +529,14 @@
 #define SSET_START_PAGE_Y(s,x)	      ((s).start_page_y = (x))
 #define SGET_START_SCREEN(s)	      ((s).start_screen)
 #define SSET_START_SCREEN(s,x)	      ((s).start_screen = (x))
+#define SGET_MIN_ICON_WIDTH(s)        ((s).min_icon_width)
+#define SSET_MIN_ICON_WIDTH(s,x)      ((s).min_icon_width = (x))
+#define SGET_MIN_ICON_HEIGHT(s)       ((s).min_icon_height)
+#define SSET_MIN_ICON_HEIGHT(s,x)     ((s).min_icon_height = (x))
+#define SGET_MAX_ICON_WIDTH(s)        ((s).max_icon_width)
+#define SSET_MAX_ICON_WIDTH(s,x)      ((s).max_icon_width = (x))
+#define SGET_MAX_ICON_HEIGHT(s)       ((s).max_icon_height)
+#define SSET_MAX_ICON_HEIGHT(s,x)     ((s).max_icon_height = (x))
 #define SGET_MAX_WINDOW_WIDTH(s)      ((s).max_window_width)
 #define SSET_MAX_WINDOW_WIDTH(s,x)    ((s).max_window_width = (x))
 #define SGET_MAX_WINDOW_HEIGHT(s)     ((s).max_window_height)
Index: libs/defaults.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/libs/defaults.h,v
retrieving revision 1.49
diff -u -r1.49 defaults.h
--- libs/defaults.h	2002/06/18 10:52:17	1.49
+++ libs/defaults.h	2002/06/24 04:07:21
@@ -152,6 +152,12 @@
 #define DEFAULT_MIN_MAX_WINDOW_HEIGHT	 100 /* pixels */
 #define DEFAULT_MAX_MAX_WINDOW_WIDTH   32767 /* pixels */
 #define DEFAULT_MAX_MAX_WINDOW_HEIGHT  32767 /* pixels */
+
+/*** icon geometry ***/
+#define UNSPECIFIED_ICON_DIMENSION        -1
+#define MIN_ALLOWABLE_ICON_DIMENSION       0 /* pixels */
+#define MAX_ALLOWABLE_ICON_DIMENSION     255 /* pixels */
+
 /* this value is used in a bugfix */
 #define WINDOW_FREAKED_OUT_SIZE	       65500 /* pixels */

---

From: "Dmitry Yu. Bolkhovityanov" <[email-masked]>
Date: Mon, 24 Jun 2002 11:43:15 +0700

> Excellent idea.  Certainly simplifies the syntax.

	A small comment: "IconSize" suggests that icons fill be somehow
forced (shrinked/grown) to specified size.  Isn't "IconSizeLimits" a more
intuitive name?

	_________________________________________
	  Dmitry Yu. Bolkhovityanov
	  The Budker Institute of Nuclear Physics
	  Novosibirsk, Russia

---

From: Mikhael Goikhman <[email-masked]>
Date: Mon, 24 Jun 2002 08:06:02 +0000

> but still be able size the icon title.

Hmm, ok.

Can IconSize receive 0 arguments (not just 2 or 4) for disabling too?

Regards,
Mikhael.

---

From: Steve Talley <[email-masked]>
Date: Mon, 24 Jun 2002 09:36:09 -0600

> Can IconSize receive 0 arguments (not just 2 or 4) for disabling too?

Oops.  Yes, I have added this feature to the attached patch.

Steve
Index: fvwm/add_window.c
+++ fvwm/add_window.c	2002/06/24 15:29:52
@@ -1057,6 +1057,25 @@
 	return;
 }
 
+/*

+++ fvwm/add_window.h	2002/06/24 15:29:53
+++ fvwm/fvwm.1	2002/06/24 15:30:04
@@ -5913,6 +5914,42 @@
+.RI IconSize " [ " width " " height " [ " maxwidth " " maxheight " ] ]"
+If no arguments are specified, the default values are used for each
+dimension.  This effectively places no limits on the size of an icon.
+++ fvwm/fvwm.h	2002/06/24 15:30:05
 
 	int default_layer;
 	int layer;
+++ fvwm/icons.c	2002/06/24 15:30:07
 
+++ fvwm/icons.h	2002/06/24 15:30:07
+++ fvwm/style.c	2002/06/24 15:30:11
@@ -1686,6 +1693,72 @@
+	        "IconSize requires exactly 0, 2 or 4 numerical arguments");
+	    case 0:
+	      /* No arguments results in default values */
+	      vals[0] = vals[1] = UNSPECIFIED_ICON_DIMENSION;
+++ fvwm/style.h	2002/06/24 15:30:12
+++ libs/defaults.h	2002/06/24 15:30:13

---

From: Steve Talley <[email-masked]>
Date: Mon, 24 Jun 2002 09:42:59 -0600

Dmitry Yu. Bolkhovityanov wrote:

> forced (shrinked/grown) to specified size.  Isn't "IconSizeLimits" a
> more intuitive name?

Hi Dmitry,

When IconSize is only passed two arguments (which is likely the most
common scenario), all icons are indeed forced to the given size.  So I
think the name "IconSize" makes sense.

Thanks,

Steve

---

From: Mikhael Goikhman <[email-masked]>
Date: Mon, 24 Jun 2002 16:49:38 +0000

Ok, I have applied the patch with some reindentation.
Also fixed a gcc warning and an error message when disabling the feature.

Just a note, IconSize requires Recapture as of now.

Please include ChangeLog, AUTHORS and NEWS changes in the next patch.

Regards,
Mikhael.