Skip to content

Hot-reload the active skin when its file changes on disk - #5141

Open
axelfontaine wants to merge 1 commit into
MidnightCommander:masterfrom
axelfontaine:skin-hot-reload
Open

Hot-reload the active skin when its file changes on disk#5141
axelfontaine wants to merge 1 commit into
MidnightCommander:masterfrom
axelfontaine:skin-hot-reload

Conversation

@axelfontaine

@axelfontaine axelfontaine commented Aug 17, 2026

Copy link
Copy Markdown

This is a prerequisite for mc following live theme-switches on Omarchy (something I've wanted for a while).

Made with Claude.

Notes from Claude:

Proposed changes

Currently, picking up a change to the current skin's .ini file requires restarting mc, or re-selecting the same skin from Options > Appearance. This is inconvenient for skins that are regenerated by an external process — e.g. a script that derives an mc skin from the desktop theme and wants it to apply live, without the user closing and reopening mc.

On Linux, this watches the active skin file with inotify and re-applies it automatically on change, reusing the same reload path (mc_skin_deinit + mc_skin_init + panel/filehighlight refresh + repaint_screen) already used by the interactive skin picker in the Appearance dialog (src/filemanager/boxes.c's skin_apply), now exposed as mc_skin_reload(). The watch fd is integrated into the existing select() loop via add_select_channel()/delete_select_channel(), the same generic mechanism already used for background job and subshell pipes — no new event-loop machinery.

The watch is armed once at startup and intentionally never re-armed on each event: the expected write pattern is an in-place truncate+write, which never invalidates the original watch descriptor. Re-arming from within the event callback was tried first and found to self-trigger forever, since inotify_rm_watch() itself raises IN_IGNORED on the same fd, which the next select() sees immediately — worth calling out in case it comes up in review.

This is Linux-only (inotify has no equivalent on the other platforms mc supports), guarded with #ifdef __linux__, matching existing precedent elsewhere in the tree (cons.handler.c, key.c, subshell/proxyfunc.c).

Manually verified: launched mc, edited the active skin file's colors on disk, and confirmed the running instance recolors in place with no restart, no keypress, and no measurable CPU overhead at idle or after reload.

Checklist

  • Lint and unit tests pass locally with my changes (make indent && make check)
  • I have added tests that prove my fix is effective or that my feature works — this changes runtime behavior at the process/event-loop level (verified manually as described above); happy to add coverage if there's a preferred pattern for this kind of thing in the existing test suite
  • I have added the necessary documentation — didn't see an obvious place to document this in the man pages; pointers welcome

Currently, picking up a change to the current skin's .ini file requires
restarting mc, or re-selecting the same skin from Options > Appearance.
This is inconvenient for skins that are regenerated by an external
process (e.g. a script that derives an mc skin from the desktop theme
and wants it to apply live, without the user closing and reopening mc).

On Linux, watch the active skin file with inotify and re-apply it
automatically on change, reusing the same reload path (mc_skin_deinit +
mc_skin_init + panel/filehighlight refresh + repaint_screen) already
used by the interactive skin picker in the Appearance dialog, now
exposed as mc_skin_reload(). The watch fd is integrated into the
existing select() loop via add_select_channel()/delete_select_channel(),
the same generic mechanism already used for background job and subshell
pipes.

The watch is armed once at startup and intentionally never re-armed on
each event: our write pattern is an in-place truncate+write, which
never invalidates the original watch descriptor. Re-arming from within
the event callback was tried first and found to self-trigger forever,
since inotify_rm_watch() itself raises IN_IGNORED on the same fd, which
the next select() sees immediately.

This is Linux-only (inotify has no equivalent on the other platforms mc
supports), guarded with #ifdef __linux__, matching existing precedent
elsewhere in the tree (cons.handler.c, key.c, subshell/proxyfunc.c).

Signed-off-by: Axel Fontaine <axel@axelfontaine.com>
@github-actions github-actions Bot added this to the Future Releases milestone Aug 17, 2026
@github-actions github-actions Bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Aug 17, 2026
@MBroholmA

Copy link
Copy Markdown

+1 to this. Omarchy needs a themed CLI commander for file management

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

Labels

needs triage Needs triage by maintainers prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

2 participants