From ec3e2e8fb9d6ba46b3ffb8db5a7ba38482c53300 Mon Sep 17 00:00:00 2001 From: Jaimos Skriletz Date: Sat, 19 Nov 2022 16:33:00 -0700 Subject: [PATCH] Add Style CornerLength Adds a style to set the length of the corners of a window. This style takes a single numerical argument and sets the length of the corner in number of pixels beyond the edge of the boundary. If the argument has a '%' suffix, the number will be treated as a percent of the window size instead of a pixel length. Note: Corner percent flag is stored as a negative value, due to not being able to get flag states to work correctly. --- doc/fvwm3_manpage_source.adoc | 20 ++++++++++++----- fvwm/add_window.c | 11 ++++++++- fvwm/borders.c | 11 +++++---- fvwm/frame.c | 42 ++++++++++++++++++++++++++++++----- fvwm/frame.h | 2 ++ fvwm/fvwm.h | 5 +++-- fvwm/style.c | 33 +++++++++++++++++++++++++++ fvwm/style.h | 6 +++++ 8 files changed, 111 insertions(+), 19 deletions(-) diff --git a/doc/fvwm3_manpage_source.adoc b/doc/fvwm3_manpage_source.adoc index 1e8eeb079..1dc83a161 100644 --- a/doc/fvwm3_manpage_source.adoc +++ b/doc/fvwm3_manpage_source.adoc @@ -4990,10 +4990,11 @@ style. _options_ is a comma separated list containing one or more of the following keywords. Each group of style names is separated by slashes ('/'). The last style in these groups is the default. _BorderWidth_, -_HandleWidth_, _!Icon_ / _Icon_, _MiniIcon_, _IconBox_, _IconGrid_, -_IconFill_, _IconSize_, _!Title_ / _Title_, _TitleAtBottom_ / -_TitleAtLeft_ / _TitleAtRight_ / _TitleAtTop_, _LeftTitleRotatedCW_ / -_LeftTitleRotatedCCW_, _RightTitleRotatedCCW_ / _RightTitleRotatedCW_, +_HandleWidth_, _CornerLength_, _!Icon_ / _Icon_, _MiniIcon_, +_IconBox_, _IconGrid_, _IconFill_, _IconSize_, _!Title_ / _Title_, +_TitleAtBottom_ / _TitleAtLeft_ / _TitleAtRight_ / +_TitleAtTop_, _LeftTitleRotatedCW_ / _LeftTitleRotatedCCW_, +_RightTitleRotatedCCW_ / _RightTitleRotatedCW_, _TopTitleRotated_ / _TopTitleNotRotated_, _BottomTitleRotated_ / _BottomTitleNotRotated_, _!UseTitleDecorRotation_ / _UseTitleDecorRotation_, _StippledTitle_ / _!StippledTitle_, @@ -5474,12 +5475,19 @@ but is deprecated. + _HandleWidth_ takes a numeric argument which is the width of the border to place the window if it does have resize-handles. Using -HandleWidth without an argument restores the default. +_HandleWidth_ without an argument restores the default. ++ +_CornerLength_ takes a numeric argument which is the length the +corners extend beyond the edge of the border. If the numeric argument +has a suffix of '%', the length will be treated as a percent of the +window size. If the _CornerLength_ exceeds a third of the window length, +it will be reduced to be one third the window length. Using _CornerLength_ +without an argument restores the default. + _BorderWidth_ takes a numeric argument which is the width of the border to place the window if it does not have resize-handles. It is used only if the _!Handles_ style is specified too. Using -BorderWidth without an argument restores the default. +_BorderWidth_ without an argument restores the default. + _DepressableBorder_ makes the border parts of the window decoration look sunken in when a button is pressed over them. This can be diff --git a/fvwm/add_window.c b/fvwm/add_window.c index 0cf88990f..4819a24f8 100644 --- a/fvwm/add_window.c +++ b/fvwm/add_window.c @@ -1659,6 +1659,7 @@ void setup_title_geometry( { int width; int offset; + style_flags *sflags = &(pstyle->flags); get_title_font_size_and_offset( fw, S_TITLE_DIR(SCF(*pstyle)), @@ -1669,7 +1670,15 @@ void setup_title_geometry( &width, &offset); fw->title_thickness = width; fw->title_text_offset = offset; - fw->corner_width = fw->title_thickness + fw->boundary_width; + fw->corner_length = fw->title_thickness + fw->boundary_width; + if (SHAS_CORNER_LENGTH(sflags)) + { + fw->corner_length = SGET_CORNER_LENGTH(*pstyle); + if (fw->corner_length > 0) + { + fw->corner_length += fw->boundary_width; + } + } if (!HAS_TITLE(fw)) { fw->title_thickness = 0; diff --git a/fvwm/borders.c b/fvwm/borders.c index be54260ca..e8aa6479f 100644 --- a/fvwm/borders.c +++ b/fvwm/borders.c @@ -1765,6 +1765,7 @@ static void border_draw_one_border_part( Pixmap p; Window w; Bool free_bg_pixmap = False; + int corner_w, corner_h; /* make a pixmap */ border_get_part_geometry(fw, part, sidebar_g, &part_g, &w); @@ -1780,6 +1781,8 @@ static void border_draw_one_border_part( relative_g.y = part_g.y; border_get_border_background( &bg, cd, &part_g, &relative_g, &free_bg_pixmap, w, part); + frame_set_corner_length( + fw, &corner_w, &corner_h, frame_g->width, frame_g->height); if (cd->texture_pixmap) { switch (part) @@ -1789,11 +1792,11 @@ static void border_draw_one_border_part( break; case PART_BORDER_NE: case PART_BORDER_SE: - bg.pixmap.g.x = frame_g->width - fw->corner_width; + bg.pixmap.g.x = frame_g->width - corner_w; break; case PART_BORDER_N: case PART_BORDER_S: - bg.pixmap.g.x = fw->corner_width; + bg.pixmap.g.x = corner_w; break; default: bg.pixmap.g.x = 0; @@ -1806,11 +1809,11 @@ static void border_draw_one_border_part( break; case PART_BORDER_SW: case PART_BORDER_SE: - bg.pixmap.g.y = frame_g->height - fw->corner_width; + bg.pixmap.g.y = frame_g->height - corner_h; break; case PART_BORDER_W: case PART_BORDER_E: - bg.pixmap.g.y = fw->corner_width; + bg.pixmap.g.y = corner_h; break; default: bg.pixmap.g.y = 0; diff --git a/fvwm/frame.c b/fvwm/frame.c index 00a03a14b..36d1f911e 100644 --- a/fvwm/frame.c +++ b/fvwm/frame.c @@ -1531,11 +1531,40 @@ void frame_get_titlebar_dimensions( return; } +#define MIN_SIZE 4 +void frame_set_corner_length( + FvwmWindow *fw, int *width, int *height, int frame_w, int frame_h) +{ + *width = fw->corner_length; + *height = fw->corner_length; + + /* Negative values mean treat as a percent length. */ + if (*width < 0) { + *width *= -frame_w / 100; + *height *= -frame_h / 100; + } + + /* Ensure a minimum/maximize size. */ + int min_l = fw->title_thickness + fw->boundary_width; + if (frame_w > MIN_SIZE && *width > frame_w / 2 - MIN_SIZE) { + *width = frame_w / 2 - MIN_SIZE; + } + if (*width < min_l) { + *width = min_l; + } + if (frame_h > MIN_SIZE && *height > frame_h / 2 - MIN_SIZE) { + *height = frame_h / 2 - MIN_SIZE; + } + if (*height < min_l) { + *height = min_l; + } +} + void frame_get_sidebar_geometry( FvwmWindow *fw, DecorFaceStyle *borderstyle, rectangle *frame_g, rectangle *ret_g, Bool *ret_has_x_marks, Bool *ret_has_y_marks) { - int min_w; + int min_l; size_borders b; ret_g->x = 0; @@ -1570,16 +1599,16 @@ void frame_get_sidebar_geometry( *ret_has_x_marks = True; *ret_has_y_marks = True; } - ret_g->x = fw->corner_width; - ret_g->y = fw->corner_width; - min_w = 2 * fw->corner_width + 4; + frame_set_corner_length( + fw, &ret_g->x, &ret_g->y, frame_g->width, frame_g->height); /* limit by available space, remove handle marks if necessary */ - if (frame_g->width < min_w) + min_l = 2*(fw->title_thickness + fw->boundary_width) + MIN_SIZE; + if (frame_g->width < min_l) { ret_g->x = frame_g->width / 3; *ret_has_y_marks = False; } - if (frame_g->height < min_w) + if (frame_g->height < min_l) { ret_g->y = frame_g->height / 3; *ret_has_x_marks = False; @@ -1599,6 +1628,7 @@ void frame_get_sidebar_geometry( return; } +#undef MIN_SIZE int frame_window_id_to_context( FvwmWindow *fw, Window w, int *ret_num) diff --git a/fvwm/frame.h b/fvwm/frame.h index 984563819..0b6d090e9 100644 --- a/fvwm/frame.h +++ b/fvwm/frame.h @@ -55,6 +55,8 @@ void frame_free_move_resize_args( void frame_get_titlebar_dimensions( FvwmWindow *fw, rectangle *frame_g, rectangle *diff_g, frame_title_layout_t *title_layout); +void frame_set_corner_length( + FvwmWindow *fw, int *width, int *height, int frame_w, int frame_h); void frame_get_sidebar_geometry( FvwmWindow *fw, DecorFaceStyle *borderstyle, rectangle *frame_g, rectangle *ret_g, Bool *ret_has_x_marks, Bool *ret_has_y_marks); diff --git a/fvwm/fvwm.h b/fvwm/fvwm.h index 0f5f8d47b..9662ce4f2 100644 --- a/fvwm/fvwm.h +++ b/fvwm/fvwm.h @@ -513,6 +513,7 @@ typedef struct style_flags unsigned has_edge_resistance_move : 1; unsigned has_edge_resistance_screen_move : 1; unsigned has_handle_width : 1; + unsigned has_corner_length : 1; unsigned has_icon : 1; unsigned has_icon_boxes : 1; unsigned has_icon_size_limits : 1; @@ -637,6 +638,7 @@ typedef struct window_style short border_width; /* resize handle width */ short handle_width; + short corner_length; int layer; int start_desk; int start_page_x; @@ -764,8 +766,7 @@ typedef struct FvwmWindow * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h too! */ short boundary_width; short unshaped_boundary_width; - short corner_width; - short visual_corner_width; + short corner_length; /* title font */ FlocaleFont *title_font; diff --git a/fvwm/style.c b/fvwm/style.c index 13b0910b3..e8b9fc3eb 100644 --- a/fvwm/style.c +++ b/fvwm/style.c @@ -470,6 +470,11 @@ static void merge_styles( SSET_HANDLE_WIDTH( *merged_style, SGET_HANDLE_WIDTH(*add_style)); } + if (add_style->flags.has_corner_length) + { + SSET_CORNER_LENGTH( + *merged_style, SGET_CORNER_LENGTH(*add_style)); + } if (add_style->flags.has_icon_size_limits) { SSET_MIN_ICON_WIDTH( @@ -2349,6 +2354,28 @@ static Bool style_parse_one_style_option( S_SET_IS_UNCLOSABLE(SCM(*ps), 1); S_SET_IS_UNCLOSABLE(SCC(*ps), 1); } + else if (StrEquals(token, "CornerLength")) + { + int num; + num = GetSuffixedIntegerArguments( + rest, &rest, val, 1, "%", tmpno); + + if (num > 0 && *val >= 0) + { + SSET_CORNER_LENGTH(*ps, (short)*val); + ps->flags.has_corner_length = 1; + /* Percent lengths are stored as negative values. */ + if (*tmpno == 1) { + SSET_CORNER_LENGTH(*ps, -(short)*val); + } + } + else + { + ps->flags.has_corner_length = 0; + } + ps->flag_mask.has_corner_length = 1; + ps->change_mask.has_corner_length = 1; + } else { found = False; @@ -4988,6 +5015,12 @@ void check_window_style_change( flags->do_update_modules_flags = 1; } + /* has_corner_length */ + if (ret_style->change_mask.has_corner_length) + { + flags->do_redecorate = 1; + } + if (ret_style->change_mask.do_save_under || ret_style->change_mask.use_backing_store || ret_style->change_mask.use_parent_relative) diff --git a/fvwm/style.h b/fvwm/style.h index 4381858e1..3db1a934c 100644 --- a/fvwm/style.h +++ b/fvwm/style.h @@ -20,6 +20,8 @@ ((sf)->has_border_width) #define SHAS_HANDLE_WIDTH(sf) \ ((sf)->has_handle_width) +#define SHAS_CORNER_LENGTH(sf) \ + ((sf)->has_corner_length) #define SHAS_ICON(sf) \ ((sf)->has_icon) #define SHAS_ICON_BOXES(sf) \ @@ -468,6 +470,10 @@ ((s).handle_width) #define SSET_HANDLE_WIDTH(s,x) \ ((s).handle_width = (x)) +#define SGET_CORNER_LENGTH(s) \ + ((s).corner_length) +#define SSET_CORNER_LENGTH(s,x) \ + ((s).corner_length = (x)) #define SGET_LAYER(s) \ ((s).layer) #define SSET_LAYER(s,x) \