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 */
<<attachment: before.jpg>>
<<attachment: after.jpg>>