diff --git a/doc/fvwm3/fvwm3.adoc b/doc/fvwm3/fvwm3.adoc index f8b07523d..f060a85ac 100644 --- a/doc/fvwm3/fvwm3.adoc +++ b/doc/fvwm3/fvwm3.adoc @@ -6140,22 +6140,27 @@ character size in many applications). This can be handy for broken applications that refuse to be resized. Do not use it if you do not need it. The default (opposite) style is _NoResizeOverride_. + -_MinWindowSize [ width [ p ] height [ p ] ]_ Tells fvwm the minimum -width and height of a window. The values are the percentage of the -total screen area. If the letter '_p_' is appended to either of the -values, the numbers are interpreted as pixels. This command is useful -for certain versions of xemacs which freak out if their windows become -too small. If you omit he parameters or their values are invalid, both -limits are set to 0 pixels (which is the default value). -+ -_MaxWindowSize [ width [ p ] height [ p ] ]_ Tells fvwm the maximum -width and height of a window. The values are the percentage of the -total screen area. If the letter '_p_' is appended to either of the -values, the numbers are interpreted as pixels. This command is useful -to force large application windows to be fully visible. Neither -_height_ nor _width_ may be less than 100 pixels. If you omit the -parameters or their values are invalid, both limits are set to 32767 -pixels (which is the default). +_MinWindowSize [ width [ p | c ] height [ p | c ] ]_ Tells fvwm the +minimum width and height of a window. The values are the percentage of +the total screen area. If the letter '_p_' is appended to either of the +values, the numbers are interpreted as pixels. If the letter '_c_' is +appended to either of the values, the numbers are in terms of the client +window's size hints, which can be useful for windows such as terminals to +specify the number of rows or columns. This command is useful to deal with +windows that freak out if their window becomes too small. If you omit the +parameters or their values are invalid, both limits are set to 0 pixels +(which is the default value). ++ +_MaxWindowSize [ width [ p | c ] height [ p | c ] ]_ Tells fvwm the +maximum width and height of a window. The values are the percentage of +the total screen area. If the letter '_p_' is appended to either of the +values, the numbers are interpreted as pixels. If the letter '_c_' is +appended to either of the values, the numbers are in terms of the client +window's size hints, which can be useful for windows such as terminals to +specify the number of rows or columns. This command is useful to force +large application windows to be fully visible. Neither _height_ nor _width_ +may be less than 100 pixels. If you omit the parameters or their values +are invalid, both limits are set to 32767 pixels (which is the default). + With _IconifyWindowGroups_ all windows in the same window group are iconified and deiconified at once when any window in the group is diff --git a/fvwm/add_window.c b/fvwm/add_window.c index 17002c69c..63900abc5 100644 --- a/fvwm/add_window.c +++ b/fvwm/add_window.c @@ -2095,7 +2095,13 @@ void setup_frame_size_limits(FvwmWindow *fw, window_style *pstyle) if (SHAS_MIN_WINDOW_SIZE(&pstyle->flags)) { fw->min_window_width = SGET_MIN_WINDOW_WIDTH(*pstyle); + if (SGET_MIN_WINDOW_WIDTH_IS_C(*pstyle)) + fw->min_window_width = fw->min_window_width * + fw->hints.width_inc + fw->hints.base_width; fw->min_window_height = SGET_MIN_WINDOW_HEIGHT(*pstyle); + if (SGET_MIN_WINDOW_HEIGHT_IS_C(*pstyle)) + fw->min_window_height = fw->min_window_width * + fw->hints.height_inc + fw->hints.base_height; } else { @@ -2105,7 +2111,23 @@ void setup_frame_size_limits(FvwmWindow *fw, window_style *pstyle) if (SHAS_MAX_WINDOW_SIZE(&pstyle->flags)) { fw->max_window_width = SGET_MAX_WINDOW_WIDTH(*pstyle); + if (SGET_MAX_WINDOW_WIDTH_IS_C(*pstyle)) + fw->max_window_width = fw->max_window_width * + fw->hints.width_inc + fw->hints.base_width; fw->max_window_height = SGET_MAX_WINDOW_HEIGHT(*pstyle); + if (SGET_MAX_WINDOW_HEIGHT_IS_C(*pstyle)) + fw->max_window_height = fw->max_window_height * + fw->hints.height_inc + fw->hints.base_height; + + /* Checking size now that the client window is known. */ + if (fw->max_window_width < DEFAULT_MIN_MAX_WINDOW_WIDTH) + fw->max_window_width = DEFAULT_MIN_MAX_WINDOW_WIDTH; + if (fw->max_window_width > DEFAULT_MAX_MAX_WINDOW_WIDTH) + fw->max_window_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; + if (fw->max_window_height < DEFAULT_MIN_MAX_WINDOW_HEIGHT) + fw->max_window_height = DEFAULT_MIN_MAX_WINDOW_HEIGHT; + if (fw->max_window_width > DEFAULT_MAX_MAX_WINDOW_HEIGHT) + fw->max_window_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } else { diff --git a/fvwm/fvwm.h b/fvwm/fvwm.h index 4998bde05..7026b0d98 100644 --- a/fvwm/fvwm.h +++ b/fvwm/fvwm.h @@ -680,6 +680,11 @@ typedef struct window_style int min_window_height; int max_window_width; int max_window_height; + /* sizes are in terms of client window size hints */ + bool min_window_width_is_c; + bool min_window_height_is_c; + bool max_window_width_is_c; + bool max_window_height_is_c; int shade_anim_steps; #if 1 /*!!!*/ snap_attraction_t snap_attraction; diff --git a/fvwm/geometry.c b/fvwm/geometry.c index acbc61010..b318ab4f7 100644 --- a/fvwm/geometry.c +++ b/fvwm/geometry.c @@ -827,6 +827,8 @@ void constrain_size( FvwmWindow *fw, const XEvent *e, int *widthp, int *heightp, int xmotion, int ymotion, int flags) { + int tmp; + window_style style; size_rect min; size_rect max; size_rect inc; @@ -863,28 +865,35 @@ void constrain_size( d.width -= b.total_size.width; d.height -= b.total_size.height; + /* Need to know if using client size for Min/Max WindowSize + * styles to decided if border width is included in the size. + */ + lookup_style(fw, &style); + min.width = fw->hints.min_width; min.height = fw->hints.min_height; - if (min.width < fw->min_window_width - b.total_size.width) + tmp = SGET_MIN_WINDOW_WIDTH_IS_C(style) ? 0 : b.total_size.width; + if (min.width < fw->min_window_width - tmp) { - min.width = fw->min_window_width - b.total_size.width; + min.width = fw->min_window_width - tmp; } - if (min.height < fw->min_window_height - b.total_size.height) + tmp = SGET_MIN_WINDOW_HEIGHT_IS_C(style) ? 0 : b.total_size.height; + if (min.height < fw->min_window_height - tmp) { - min.height = - fw->min_window_height - b.total_size.height; + min.height = fw->min_window_height - tmp; } max.width = fw->hints.max_width; max.height = fw->hints.max_height; - if (max.width > fw->max_window_width - b.total_size.width) + tmp = SGET_MAX_WINDOW_WIDTH_IS_C(style) ? 0 : b.total_size.width; + if (max.width > fw->max_window_width - tmp) { - max.width = fw->max_window_width - b.total_size.width; + max.width = fw->max_window_width - tmp; } - if (max.height > fw->max_window_height - b.total_size.height) + tmp = SGET_MAX_WINDOW_HEIGHT_IS_C(style) ? 0 : b.total_size.height; + if (max.height > fw->max_window_height - tmp) { - max.height = - fw->max_window_height - b.total_size.height; + max.height = fw->max_window_height - tmp; } if (min.width > max.width) diff --git a/fvwm/style.c b/fvwm/style.c index 3f0a16a07..59832ed73 100644 --- a/fvwm/style.c +++ b/fvwm/style.c @@ -551,15 +551,23 @@ static void merge_styles( { SSET_MIN_WINDOW_WIDTH( *merged_style, SGET_MIN_WINDOW_WIDTH(*add_style)); + SSET_MIN_WINDOW_WIDTH_IS_C( + *merged_style, SGET_MIN_WINDOW_WIDTH_IS_C(*add_style)); SSET_MIN_WINDOW_HEIGHT( *merged_style, SGET_MIN_WINDOW_HEIGHT(*add_style)); + SSET_MIN_WINDOW_HEIGHT_IS_C( + *merged_style, SGET_MIN_WINDOW_HEIGHT_IS_C(*add_style)); } if (add_style->flags.has_max_window_size) { SSET_MAX_WINDOW_WIDTH( *merged_style, SGET_MAX_WINDOW_WIDTH(*add_style)); + SSET_MAX_WINDOW_WIDTH_IS_C( + *merged_style, SGET_MAX_WINDOW_WIDTH_IS_C(*add_style)); SSET_MAX_WINDOW_HEIGHT( *merged_style, SGET_MAX_WINDOW_HEIGHT(*add_style)); + SSET_MAX_WINDOW_HEIGHT_IS_C( + *merged_style, SGET_MAX_WINDOW_HEIGHT_IS_C(*add_style)); } if (add_style->flags.has_icon_background_relief) { @@ -3426,76 +3434,105 @@ static Bool style_parse_one_style_option( } else if (StrEquals(token, "MinWindowSize")) { - int val1; - int val2; - int val1_unit; - int val2_unit; + int units[2] = {100, 100}; + int mondim[2]; + bool use_client[2] = {false, false}; - num = GetTwoArguments( - rest, &val1, &val2, &val1_unit, &val2_unit); - rest = SkipNTokens(rest, num); + mondim[0] = monitor_get_all_widths(); + mondim[1] = monitor_get_all_heights(); + + num = GetSuffixedIntegerArguments( + rest, &rest, val, 2, "pc", tmpno); if (num != 2) { - val1 = 0; - val2 = 0; + val[0] = 0; + val[1] = 0; } else { - val1 = val1 * val1_unit / 100; - val2 = val2 * val2_unit / 100; - } - if (val1 < 0) - { - val1 = 0; - } - if (val2 < 0) - { - val2 = 0; + for (i = 0; i < 2; i++) + { + switch (tmpno[i]) + { + case 0: /* no suffix */ + units[i] = mondim[i]; + break; + case 1: /* p suffix */ + break; + case 2: /* c suffix */ + use_client[i] = true; + break; + default: /* shouldn't happen */ + val[i] = 0; + break; + } + val[i] = val[i] * units[i] / 100; + if (val[i] < 0) + { + val[i] = 0; + use_client[i] = false; + } + } } - SSET_MIN_WINDOW_WIDTH(*ps, val1); - SSET_MIN_WINDOW_HEIGHT(*ps, val2); + SSET_MIN_WINDOW_WIDTH(*ps, val[0]); + SSET_MIN_WINDOW_WIDTH_IS_C(*ps, use_client[0]); + SSET_MIN_WINDOW_HEIGHT(*ps, val[1]); + SSET_MIN_WINDOW_HEIGHT_IS_C(*ps, use_client[1]); ps->flags.has_min_window_size = 1; ps->flag_mask.has_min_window_size = 1; ps->change_mask.has_min_window_size = 1; } else if (StrEquals(token, "MaxWindowSize")) { - int val1; - int val2; - int val1_unit; - int val2_unit; + int units[2] = {100, 100}; + int mondim[2]; + bool use_client[2] = {false, false}; + int maxsize[2] = {DEFAULT_MAX_MAX_WINDOW_WIDTH, + DEFAULT_MAX_MAX_WINDOW_HEIGHT}; + + mondim[0] = monitor_get_all_widths(); + mondim[1] = monitor_get_all_heights(); - num = GetTwoArguments( - rest, &val1, &val2, &val1_unit, &val2_unit); - rest = SkipNTokens(rest, num); + num = GetSuffixedIntegerArguments( + rest, &rest, val, 2, "pc", tmpno); if (num != 2) { - val1 = DEFAULT_MAX_MAX_WINDOW_WIDTH; - val2 = DEFAULT_MAX_MAX_WINDOW_HEIGHT; + val[0] = DEFAULT_MAX_MAX_WINDOW_WIDTH; + val[1] = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } else { - val1 = val1 * val1_unit / 100; - val2 = val2 * val2_unit / 100; - } - if (val1 < DEFAULT_MIN_MAX_WINDOW_WIDTH) - { - val1 = DEFAULT_MIN_MAX_WINDOW_WIDTH; - } - if (val1 > DEFAULT_MAX_MAX_WINDOW_WIDTH || val1 <= 0) - { - val1 = DEFAULT_MAX_MAX_WINDOW_WIDTH; - } - if (val2 < DEFAULT_MIN_MAX_WINDOW_HEIGHT) - { - val2 = DEFAULT_MIN_MAX_WINDOW_HEIGHT; - } - if (val2 > DEFAULT_MAX_MAX_WINDOW_HEIGHT || val2 <= 0) - { - val2 = DEFAULT_MAX_MAX_WINDOW_HEIGHT; + for (i = 0; i < 2; i++) + { + switch (tmpno[i]) + { + case 0: /* no suffix */ + units[i] = mondim[i]; + break; + case 1: /* p suffix */ + break; + case 2: /* c suffix */ + use_client[i] = true; + break; + default: /* shouldn't happen */ + val[i] = 0; + break; + } + val[i] = val[i] * units[i] / 100; + /* Actual check is done later once the + * size of the client window is known. + */ + if (val[i] < 1 || val[i] > maxsize[i]) + { + val[i] = maxsize[i]; + use_client[i] = false; + } + } } - SSET_MAX_WINDOW_WIDTH(*ps, val1); - SSET_MAX_WINDOW_HEIGHT(*ps, val2); + SSET_MAX_WINDOW_WIDTH(*ps, val[0]); + SSET_MAX_WINDOW_WIDTH_IS_C(*ps, use_client[0]); + SSET_MAX_WINDOW_HEIGHT(*ps, val[1]); + SSET_MAX_WINDOW_HEIGHT_IS_C(*ps, use_client[1]); ps->flags.has_max_window_size = 1; ps->flag_mask.has_max_window_size = 1; ps->change_mask.has_max_window_size = 1; diff --git a/fvwm/style.h b/fvwm/style.h index 9f02d7cb4..4391c69a8 100644 --- a/fvwm/style.h +++ b/fvwm/style.h @@ -546,20 +546,36 @@ ((s).icon_title_relief = (x)) #define SGET_MIN_WINDOW_WIDTH(s) \ ((s).min_window_width) +#define SGET_MIN_WINDOW_WIDTH_IS_C(s) \ + ((s).min_window_width_is_c) #define SSET_MIN_WINDOW_WIDTH(s,x) \ ((s).min_window_width = (x)) +#define SSET_MIN_WINDOW_WIDTH_IS_C(s,x) \ + ((s).min_window_width_is_c = (x)) #define SGET_MAX_WINDOW_WIDTH(s) \ ((s).max_window_width) +#define SGET_MAX_WINDOW_WIDTH_IS_C(s) \ + ((s).max_window_width_is_c) #define SSET_MAX_WINDOW_WIDTH(s,x) \ ((s).max_window_width = (x)) +#define SSET_MAX_WINDOW_WIDTH_IS_C(s,x) \ + ((s).max_window_width_is_c = (x)) #define SGET_MIN_WINDOW_HEIGHT(s) \ ((s).min_window_height) +#define SGET_MIN_WINDOW_HEIGHT_IS_C(s) \ + ((s).min_window_height_is_c) #define SSET_MIN_WINDOW_HEIGHT(s,x) \ ((s).min_window_height = (x)) +#define SSET_MIN_WINDOW_HEIGHT_IS_C(s,x) \ + ((s).min_window_height_is_c = (x)) #define SGET_MAX_WINDOW_HEIGHT(s) \ ((s).max_window_height) +#define SGET_MAX_WINDOW_HEIGHT_IS_C(s) \ + ((s).max_window_height_is_c) #define SSET_MAX_WINDOW_HEIGHT(s,x) \ ((s).max_window_height = (x)) +#define SSET_MAX_WINDOW_HEIGHT_IS_C(s,x) \ + ((s).max_window_height_is_c = (x)) #define SGET_WINDOW_SHADE_STEPS(s) \ ((s).shade_anim_steps) #define SSET_WINDOW_SHADE_STEPS(s,x) \