Compare commits

..

2 Commits

View File

@ -2014,7 +2014,7 @@ app_layout_header (void)
} }
static int static int
app_visible_items (void) app_visible_items_height (void)
{ {
struct widget *list = NULL; struct widget *list = NULL;
LIST_FOR_EACH (struct widget, w, g.widgets.head) LIST_FOR_EACH (struct widget, w, g.widgets.head)
@ -2024,7 +2024,13 @@ app_visible_items (void)
hard_assert (list != NULL); hard_assert (list != NULL);
// The raw number of items that would have fit on the terminal // The raw number of items that would have fit on the terminal
return MAX (0, list->height / g.ui_vunit); return MAX (0, list->height);
}
static int
app_visible_items (void)
{
return app_visible_items_height () / g.ui_vunit;
} }
/// Figure out scrollbar appearance. @a s is the minimal slider length as well /// Figure out scrollbar appearance. @a s is the minimal slider length as well
@ -2032,7 +2038,7 @@ app_visible_items (void)
struct scrollbar { long length, start; } struct scrollbar { long length, start; }
app_compute_scrollbar (struct tab *tab, long visible, long s) app_compute_scrollbar (struct tab *tab, long visible, long s)
{ {
long top = tab->item_top, total = tab->item_count; long top = s * tab->item_top, total = s * tab->item_count;
if (total < visible) if (total < visible)
return (struct scrollbar) { 0, 0 }; return (struct scrollbar) { 0, 0 };
if (visible == 1) if (visible == 1)
@ -2042,7 +2048,7 @@ app_compute_scrollbar (struct tab *tab, long visible, long s)
// Only be at the top or bottom when the top or bottom item can be seen. // Only be at the top or bottom when the top or bottom item can be seen.
// The algorithm isn't optimal but it's a bitch to get right. // The algorithm isn't optimal but it's a bitch to get right.
double available_length = s * visible - 2 - s + 1; double available_length = visible - 2 - s + 1;
double lenf = s + available_length * visible / total, length = 0.; double lenf = s + available_length * visible / total, length = 0.;
long offset = 1 + available_length * top / total + modf (lenf, &length); long offset = 1 + available_length * top / total + modf (lenf, &length);
@ -2050,7 +2056,7 @@ app_compute_scrollbar (struct tab *tab, long visible, long s)
if (top == 0) if (top == 0)
return (struct scrollbar) { length, 0 }; return (struct scrollbar) { length, 0 };
if (top + visible >= total) if (top + visible >= total)
return (struct scrollbar) { length, s * visible - length }; return (struct scrollbar) { length, visible - length };
return (struct scrollbar) { length, offset }; return (struct scrollbar) { length, offset };
} }
@ -2099,7 +2105,7 @@ app_sublayout_list (struct widget *list)
{ {
struct tab *tab = g.active_tab; struct tab *tab = g.active_tab;
int to_show = MIN ((int) tab->item_count - tab->item_top, int to_show = MIN ((int) tab->item_count - tab->item_top,
list->height / g.ui_vunit); ceil ((double) list->height / g.ui_vunit));
struct layout l = {}; struct layout l = {};
for (int row = 0; row < to_show; row++) for (int row = 0; row < to_show; row++)
@ -2839,9 +2845,8 @@ app_process_left_mouse_click (struct widget *w, int x, int y, int modifiers)
else if (tab->item_mark < 0) else if (tab->item_mark < 0)
tab->item_mark = tab->item_selected; tab->item_mark = tab->item_selected;
// TODO: Probably will need to fix up item->top
// for partially visible items in X11.
tab->item_selected = row_index + tab->item_top; tab->item_selected = row_index + tab->item_top;
app_ensure_selection_visible ();
app_invalidate (); app_invalidate ();
if (modifiers & APP_KEYMOD_DOUBLE_CLICK) if (modifiers & APP_KEYMOD_DOUBLE_CLICK)
@ -2852,7 +2857,7 @@ app_process_left_mouse_click (struct widget *w, int x, int y, int modifiers)
{ {
struct tab *tab = g.active_tab; struct tab *tab = g.active_tab;
int visible_items = app_visible_items (); int visible_items = app_visible_items ();
tab->item_top = (float) y / w->height tab->item_top = (double) y / w->height
* (int) tab->item_count - visible_items / 2; * (int) tab->item_count - visible_items / 2;
app_invalidate (); app_invalidate ();
break; break;
@ -5171,7 +5176,7 @@ tui_render_scrollbar (struct widget *self)
return; return;
} }
struct scrollbar bar = app_compute_scrollbar (tab, visible_items, 8); struct scrollbar bar = app_compute_scrollbar (tab, visible_items * 8, 8);
bar.length += bar.start; bar.length += bar.start;
int start_part = bar.start % 8; bar.start /= 8; int start_part = bar.start % 8; bar.start /= 8;
@ -5791,10 +5796,8 @@ x11_render_scrollbar (struct widget *self)
x11_render_padding (self); x11_render_padding (self);
struct tab *tab = g.active_tab; struct tab *tab = g.active_tab;
// FIXME: This isn't an integer number in this case.
int visible_items = app_visible_items ();
struct scrollbar bar = struct scrollbar bar =
app_compute_scrollbar (tab, visible_items, g.ui_vunit); app_compute_scrollbar (tab, app_visible_items_height (), g.ui_vunit);
XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture, XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture,
x11_fg_attrs (self->attrs), x11_fg_attrs (self->attrs),
@ -5814,17 +5817,22 @@ x11_make_scrollbar (chtype attrs)
return w; return w;
} }
// TODO: Handle partial items, otherwise this is the same as tui_render_list().
static void static void
x11_render_list (struct widget *self) x11_render_list (struct widget *self)
{ {
x11_render_padding (self); // We could do that for all widgets, but it would be kind-of pointless.
XRenderSetPictureClipRectangles (g.dpy, g.x11_pixmap_picture, 0, 0,
&(XRectangle) { self->x, self->y, self->width, self->height }, 1);
x11_render_padding (self);
LIST_FOR_EACH (struct widget, w, self->on_sublayout (self)) LIST_FOR_EACH (struct widget, w, self->on_sublayout (self))
{ {
w->on_render (w); w->on_render (w);
free (w); free (w);
} }
XRenderChangePicture (g.dpy, g.x11_pixmap_picture, CPClipMask,
&(XRenderPictureAttributes) { .clip_mask = None });
} }
static struct widget * static struct widget *