Mikhael Goikhman wrote:

> On 22 Jun 2002 16:25:27 -0600, Steve Talley 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.
> >
> > 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.
>
> Seems like a good patch.  Some notes.

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:
> >
> >     Style * MaxIconSize 64 50
> >     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?

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
>   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).

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.

> > 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.
>
> 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 @@
 
        /****** 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 -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
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/icons.c,v
retrieving revision 1.181
diff -u -r1.181 icons.c
--- fvwm/icons.c        2002/06/19 14:11:27     1.181
+++ fvwm/icons.c        2002/06/24 04:07:16
@@ -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 -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 */
 

<<attachment: zeroheight.jpg>>

<<attachment: zeroheight2.jpg>>

Reply via email to