From c10ee955bd81d369034af47335a8ce7a7d1de52b Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Tue, 7 Sep 2021 19:40:07 +0200 Subject: [PATCH] #1437 - Fix sizing logic for widgets and textboxes. (#1444) * [I1437] Textbox make get_desired_width depend on width. Should fix some weird sizing issues on creation of widgest. * [i1437] [View] Do the sizing based on the desired window width. issue: #1437 * [i1437] Fix header documentation. --- include/widgets/textbox.h | 3 ++- include/widgets/widget-internal.h | 4 ++-- include/widgets/widget.h | 6 ++++-- source/view.c | 11 +++-------- source/widgets/box.c | 19 ++++++++++--------- source/widgets/container.c | 4 ++-- source/widgets/icon.c | 6 ++++-- source/widgets/listview.c | 14 +++++++++----- source/widgets/scrollbar.c | 3 ++- source/widgets/textbox.c | 12 ++++++++++-- source/widgets/widget.c | 8 ++++---- 11 files changed, 52 insertions(+), 38 deletions(-) diff --git a/include/widgets/textbox.h b/include/widgets/textbox.h index 3386557c..d9320391 100644 --- a/include/widgets/textbox.h +++ b/include/widgets/textbox.h @@ -314,12 +314,13 @@ PangoAttrList *textbox_get_pango_attributes(textbox *tb); const char *textbox_get_visible_text(const textbox *tb); /** * @param wid The handle to the textbox. + * @param height The height we want the desired width for * * TODO: is this deprecated by widget::get_desired_width * * @returns the desired width of the textbox. */ -int textbox_get_desired_width(widget *wid); +int textbox_get_desired_width(widget *wid, const int height); /** * @param tb Handle to the textbox diff --git a/include/widgets/widget-internal.h b/include/widgets/widget-internal.h index 159c80f2..91c3a8d9 100644 --- a/include/widgets/widget-internal.h +++ b/include/widgets/widget-internal.h @@ -80,8 +80,8 @@ struct _widget { /** Handle mouse motion, used for dragging */ gboolean (*motion_notify)(struct _widget *, gint x, gint y); - int (*get_desired_height)(struct _widget *); - int (*get_desired_width)(struct _widget *); + int (*get_desired_height)(struct _widget *, const int width); + int (*get_desired_width)(struct _widget *, const int height); void (*set_state)(struct _widget *, const char *); diff --git a/include/widgets/widget.h b/include/widgets/widget.h index c3aac979..e4139d02 100644 --- a/include/widgets/widget.h +++ b/include/widgets/widget.h @@ -318,21 +318,23 @@ gboolean widget_motion_notify(widget *wid, gint x, gint y); /** * @param wid The widget handle + * @param width The Widget width to get height for * * Get the desired height of this widget recursively. * * @returns the desired height of the widget in pixels. */ -int widget_get_desired_height(widget *wid); +int widget_get_desired_height(widget *wid, const int width); /** * @param wid The widget handle + * @param height The Widget height to get height for * * Get the desired width of this widget recursively. * * @returns the desired width of the widget in pixels. */ -int widget_get_desired_width(widget *wid); +int widget_get_desired_width(widget *wid, const int height); /** * @param wid The widget handle * diff --git a/source/view.c b/source/view.c index 52b75754..51e4437f 100644 --- a/source/view.c +++ b/source/view.c @@ -1026,7 +1026,7 @@ static void update_callback(textbox *t, icon *ico, unsigned int index, list = pango_attr_list_new(); } if (ico) { - int icon_height = widget_get_desired_height(WIDGET(ico)); + int icon_height = widget_get_desired_height(WIDGET(ico), WIDGET(ico)->w); cairo_surface_t *icon = mode_get_icon(state->sw, state->line_map[index], icon_height); icon_set_surface(ico, icon); @@ -1667,7 +1667,7 @@ static int rofi_view_calculate_height(RofiViewState *state) { } // Autosize based on widgets. widget *main_window = WIDGET(state->main_window); - return widget_get_desired_height(main_window); + return widget_get_desired_height(main_window, state->width); } static WidgetTriggerActionResult textbox_button_trigger_action( @@ -1994,8 +1994,6 @@ RofiViewState *rofi_view_create(Mode *sw, const char *input, state->distance = (int *)g_malloc0_n(state->num_lines, sizeof(int)); rofi_view_calculate_window_width(state); - // Need to resize otherwise calculated desired height is wrong. - widget_resize(WIDGET(state->main_window), state->width, 100); // Only needed when window is fixed size. if ((CacheState.flags & MENU_NORMAL_WINDOW) == MENU_NORMAL_WINDOW) { listview_set_fixed_num_lines(state->list_view); @@ -2048,10 +2046,7 @@ int rofi_view_error_dialog(const char *msg, int markup) { listview_set_fixed_num_lines(state->list_view); } rofi_view_calculate_window_width(state); - // Need to resize otherwise calculated desired height is wrong. - widget_resize(WIDGET(state->main_window), state->width, 100); - // resize window vertically to suit - state->height = widget_get_desired_height(WIDGET(state->main_window)); + state->height = rofi_view_calculate_height(state); // Calculate window position. rofi_view_calculate_window_position(state); diff --git a/source/widgets/box.c b/source/widgets/box.c index d1d05ab8..1b5e2933 100644 --- a/source/widgets/box.c +++ b/source/widgets/box.c @@ -49,7 +49,7 @@ struct _box { static void box_update(widget *wid); -static int box_get_desired_width(widget *wid) { +static int box_get_desired_width(widget *wid, const int height) { box *b = (box *)wid; int spacing = distance_get_pixel(b->spacing, b->type); int width = 0; @@ -71,10 +71,10 @@ static int box_get_desired_width(widget *wid) { } active_widgets++; if (child->expand == TRUE) { - width += widget_get_desired_width(child); + width += widget_get_desired_width(child, height); continue; } - width += widget_get_desired_width(child); + width += widget_get_desired_width(child, height); } if (active_widgets > 0) { width += (active_widgets - 1) * spacing; @@ -86,13 +86,13 @@ static int box_get_desired_width(widget *wid) { if (!child->enabled) { continue; } - width = MAX(widget_get_desired_width(child), width); + width = MAX(widget_get_desired_width(child, height), width); } } width += widget_padding_get_padding_width(wid); return width; } -static int box_get_desired_height(widget *wid) { +static int box_get_desired_height(widget *wid, const int width) { box *b = (box *)wid; int spacing = distance_get_pixel(b->spacing, b->type); int height = 0; @@ -105,7 +105,7 @@ static int box_get_desired_height(widget *wid) { continue; } active_widgets++; - height += widget_get_desired_height(child); + height += widget_get_desired_height(child, width); } if (active_widgets > 0) { height += (active_widgets - 1) * spacing; @@ -117,7 +117,7 @@ static int box_get_desired_height(widget *wid) { if (!child->enabled) { continue; } - height = MAX(widget_get_desired_height(child), height); + height = MAX(widget_get_desired_height(child, width), height); } } height += widget_padding_get_padding_height(wid); @@ -134,7 +134,8 @@ static void vert_calculate_size(box *b) { iter = g_list_next(iter)) { widget *child = (widget *)iter->data; if (child->enabled && child->expand == FALSE) { - widget_resize(child, rem_width, widget_get_desired_height(child)); + widget_resize(child, rem_width, + widget_get_desired_height(child, rem_width)); } } b->max_size = 0; @@ -201,7 +202,7 @@ static void hori_calculate_size(box *b) { widget *child = (widget *)iter->data; if (child->enabled && child->expand == FALSE) { widget_resize(child, - widget_get_desired_width(child), // child->w, + widget_get_desired_width(child, rem_height), // child->w, rem_height); } } diff --git a/source/widgets/container.c b/source/widgets/container.c index 725a1a46..50672267 100644 --- a/source/widgets/container.c +++ b/source/widgets/container.c @@ -41,11 +41,11 @@ struct _container { static void container_update(widget *wid); -static int container_get_desired_height(widget *widget) { +static int container_get_desired_height(widget *widget, const int width) { container *b = (container *)widget; int height = 0; if (b->child) { - height += widget_get_desired_height(b->child); + height += widget_get_desired_height(b->child, width); } height += widget_padding_get_padding_height(widget); return height; diff --git a/source/widgets/icon.c b/source/widgets/icon.c index 99fa1cb0..a669d220 100644 --- a/source/widgets/icon.c +++ b/source/widgets/icon.c @@ -52,7 +52,8 @@ struct _icon { cairo_surface_t *icon; }; -static int icon_get_desired_height(widget *widget) { +static int icon_get_desired_height(widget *widget, + G_GNUC_UNUSED const int width) { icon *b = (icon *)widget; int height = b->size; if (b->squared == FALSE) { @@ -67,7 +68,8 @@ static int icon_get_desired_height(widget *widget) { height += widget_padding_get_padding_height(widget); return height; } -static int icon_get_desired_width(widget *widget) { +static int icon_get_desired_width(widget *widget, + G_GNUC_UNUSED const int height) { icon *b = (icon *)widget; int width = b->size; if (b->squared == FALSE) { diff --git a/source/widgets/listview.c b/source/widgets/listview.c index 853aed22..8605f2d2 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -206,7 +206,7 @@ static void listview_create_row(listview *lv, _listview_row *row) { g_list_free_full(list, g_free); } -static int listview_get_desired_height(widget *wid); +static int listview_get_desired_height(widget *wid, const int width); static void listview_free(widget *wid) { listview *lv = (listview *)wid; @@ -319,7 +319,8 @@ static void barview_draw(widget *wid, cairo_t *draw) { if (lv->barview.direction == LEFT_TO_RIGHT) { for (unsigned int i = 0; i < max && width > 0; i++) { update_element(lv, i, i + offset, TRUE); - int twidth = widget_get_desired_width(WIDGET(lv->boxes[i].box)); + int twidth = widget_get_desired_width(WIDGET(lv->boxes[i].box), + lv->element_height); if (twidth >= width) { if (!first) { break; @@ -339,7 +340,8 @@ static void barview_draw(widget *wid, cairo_t *draw) { for (unsigned int i = 0; i < lv->cur_elements && width > 0 && i <= offset; i++) { update_element(lv, i, offset - i, TRUE); - int twidth = widget_get_desired_width(WIDGET(lv->boxes[i].box)); + int twidth = widget_get_desired_width(WIDGET(lv->boxes[i].box), + lv->element_height); if (twidth >= width) { if (!first) { break; @@ -687,7 +689,8 @@ listview *listview_create(widget *parent, const char *name, }; textbox_text(row.textbox, buff); } - lv->element_height = widget_get_desired_height(WIDGET(row.box)); + // Make textbox very wide. + lv->element_height = widget_get_desired_height(WIDGET(row.box), 100000); widget_free(WIDGET(row.box)); lv->callback = cb; @@ -877,7 +880,8 @@ void listview_nav_page_next(listview *lv) { } } -static int listview_get_desired_height(widget *wid) { +static int listview_get_desired_height(widget *wid, + G_GNUC_UNUSED const int width) { listview *lv = (listview *)wid; if (lv == NULL || lv->widget.enabled == FALSE) { return 0; diff --git a/source/widgets/scrollbar.c b/source/widgets/scrollbar.c index aaa23b68..73740588 100644 --- a/source/widgets/scrollbar.c +++ b/source/widgets/scrollbar.c @@ -40,7 +40,8 @@ static void scrollbar_draw(widget *, cairo_t *); static void scrollbar_free(widget *); -static int scrollbar_get_desired_height(widget *wid) { +static int scrollbar_get_desired_height(widget *wid, + G_GNUC_UNUSED const int width) { // Want height we are. return wid->h; } diff --git a/source/widgets/textbox.c b/source/widgets/textbox.c index 57d76844..d5414f87 100644 --- a/source/widgets/textbox.c +++ b/source/widgets/textbox.c @@ -76,16 +76,24 @@ static void textbox_resize(widget *wid, short w, short h) { textbox *tb = (textbox *)wid; textbox_moveresize(tb, tb->widget.x, tb->widget.y, w, h); } -static int textbox_get_desired_height(widget *wid) { +static int textbox_get_desired_height(widget *wid, const int width) { textbox *tb = (textbox *)wid; + unsigned int offset = ((tb->flags & TB_INDICATOR) ? DOT_OFFSET : 0); if ((tb->flags & TB_AUTOHEIGHT) == 0) { return tb->widget.h; } if (tb->changed) { __textbox_update_pango_text(tb); } + int old_width = pango_layout_get_width(tb->layout); + pango_layout_set_width( + tb->layout, + PANGO_SCALE * + (width - widget_padding_get_padding_width(WIDGET(tb)) - offset)); + int height = textbox_get_estimated_height(tb, pango_layout_get_line_count(tb->layout)); + pango_layout_set_width(tb->layout, old_width); return height; } @@ -899,7 +907,7 @@ int textbox_get_estimated_height(const textbox *tb, int eh) { int height = tb->tbfc->height; return (eh * height) + widget_padding_get_padding_height(WIDGET(tb)); } -int textbox_get_desired_width(widget *wid) { +int textbox_get_desired_width(widget *wid, G_GNUC_UNUSED const int height) { if (wid == NULL) { return 0; } diff --git a/source/widgets/widget.c b/source/widgets/widget.c index 97a4f45c..aaaea1f8 100644 --- a/source/widgets/widget.c +++ b/source/widgets/widget.c @@ -646,23 +646,23 @@ int widget_padding_get_padding_width(const widget *wid) { return width; } -int widget_get_desired_height(widget *wid) { +int widget_get_desired_height(widget *wid, const int width) { if (wid == NULL) { return 0; } if (wid->get_desired_height == NULL) { return wid->h; } - return wid->get_desired_height(wid); + return wid->get_desired_height(wid, width); } -int widget_get_desired_width(widget *wid) { +int widget_get_desired_width(widget *wid, const int height) { if (wid == NULL) { return 0; } if (wid->get_desired_width == NULL) { return wid->w; } - return wid->get_desired_width(wid); + return wid->get_desired_width(wid, height); } int widget_get_absolute_xpos(widget *wid) {