Skip to content

Fix row icons and previews that fail to render - #2323

Merged
DaveDavenport merged 4 commits into
davatorium:nextfrom
vredesbyyrd:fix-icon-current-entry-render
Sep 1, 2026
Merged

DaveDavenport merged 4 commits into
davatorium:nextfrom
vredesbyyrd:fix-icon-current-entry-render

Conversation

@vredesbyyrd

Copy link
Copy Markdown
Contributor

What this fixes

Preview images (icon-current-entry) often fail to appear when the selection changes, and once one is missed it stays blank until you move the selection away and back. In script and dmenu the row icon goes missing with it; in filebrowser (and rofi-blocks) only the preview does.

The bugs, and what changes

1. Finished icon loads are thrown away. Icons decode on a worker thread and signal the view with rofi_view_reload(). The reload handler cleared its "reload pending" flag only after refiltering, so a reload arriving mid-pass coalesced into the pass that had already read it, and was lost. Nothing asks again: the preview is refreshed only when the selection changes, while row icons recover on the next redraw, which is why filebrowser and rofi-blocks lose only the preview. Faster decodes fail more often, being likelier to land inside that window. Fix: clear the flag first.

2. One cached icon id per entry, regardless of size. A theme with both a row icon and a preview asks for one entry at two sizes, but script and dmenu cached a single id for it, so the second request got the first one's image. Fix: match on size and scale, as drun already does.

3. The first entry's fallback index is uninitialized. In script, the memset following each new entry clears the next slot, leaving entry 0 reading stale memory. An out-of-range value makes rofi skip the icon query, so the first row of every reloaded menu has no row icon and no preview. Fix: set it explicitly, as dmenu already does.

Only (1) can affect filebrowser or rofi-blocks; (2) and (3) touch script.c and dmenu.c alone.

Reproducing

All three use the stock fullscreen-preview.rasi, which enables the preview when PREVIEW=true is set.

Nested script mode: the first row of each submenu gets no row icon and no preview. Test script and instructions: https://gist.github.com/vredesbyyrd/5dbb450335523f6b1ae6b7d193893435

filebrowser: open a directory with 100+ images and hold Page Down (more reliable than the arrow keys). Stop on an entry and the preview is often blank.

PREVIEW=true rofi -show filebrowser -theme fullscreen-preview.rasi

dmenu: page through quickly the same way. Here the row icon is missing as well as the preview.

find ~/path/to/images -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.png' \) | sort |
  while IFS= read -r f; do printf '%s\0icon\x1f%s\n' "${f##*/}" "$f"; done |
  PREVIEW=true rofi -dmenu -show-icons -theme fullscreen-preview.rasi

I first hit this in rofi-blocks, which is what the video below shows before the fix.

niri_screencast_2026-08-10.21-20-01.mp4

Testing

meson test passes. I have been running the branch daily with rofi-blocks, and checked script, dmenu, filebrowser, and drun with a preview theme on both backends (xcb/wayland) without hitting regressions.

Full Disclosure

As stated in #2318, I am not a C expert and I am not deeply familiar with rofi's codebase, so I used AI to help me trace the relevant code paths and implement parts of this fix. All changes were carefully reviewed and tested, but additional eyes on are always appreciated.

P.S. I tried to keep the comments concise. I can remove them if preferred.

vredesbyyrd and others added 4 commits August 11, 2026 16:39
The reload idle handler cleared its timeout id only after refiltering, so
a rofi_view_reload() arriving while it ran coalesced into the pass that had
already read the result and was lost. Icon fetches complete on a worker
thread and signal this way, leaving icon-current-entry unpainted until some
later reload happened to arrive.

Clear the id before doing the work instead.
A theme with both a row icon and icon-current-entry asks for one entry at
two sizes, but only one uid is cached, so the second request reused the
surface fetched for the first. Match on size and scale like drun does, and
return what the fetcher holds after re-querying instead of NULL, which
would blank the icon every time the two sizes alternate.
Entries come from g_realloc and every field is set explicitly, except this
one: the memset that follows each entry clears the next slot, so only the
first is left uninitialized. A stale value above the icon count makes
script_get_icon() skip the query entirely, leaving the first row without a
row icon or a preview.
@DaveDavenport
DaveDavenport merged commit 58376cf into davatorium:next Sep 1, 2026
5 checks passed
@DaveDavenport

Copy link
Copy Markdown
Collaborator

Thanks.
Good catch on the fix missing on script/dmenu while it is on drun/run.
(I think I need to apply this to recursive/filebrowser too).

Lets hope this fixes some of the weirdness some people where experiencing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants