use win-title script for customizing window title (#213)

this removes the cli flag `-T` as well as related config.h options.

Co-authored-by: Berke Kocaoğlu <berke.kocaoglu@metu.edu.tr>
This commit is contained in:
N-R-K 2022-02-23 09:23:22 +00:00 committed by GitHub
parent ad95012be9
commit e26c81fe9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 69 deletions

View file

@ -16,19 +16,6 @@ static const char *DEFAULT_BAR_FG = NULL; /* NULL means it will default to
static const char *DEFAULT_FONT = "monospace-8"; static const char *DEFAULT_FONT = "monospace-8";
#endif #endif
#endif
#ifdef _TITLE_CONFIG
/* default title prefix */
static const char *TITLE_PREFIX = "nsxiv - ";
/* default title suffixmode, available options are:
* SUFFIX_EMPTY
* SUFFIX_BASENAME
* SUFFIX_FULLPATH
*/
static const suffixmode_t TITLE_SUFFIXMODE = SUFFIX_BASENAME;
#endif #endif
#ifdef _IMAGE_CONFIG #ifdef _IMAGE_CONFIG

27
examples/win-title Executable file
View file

@ -0,0 +1,27 @@
#!/bin/sh
# Example for $XDG_CONFIG_HOME/nsxiv/exec/win-title
# Called by nsxiv(1) on each redraw.
# The output is set as nsxiv's window title.
#
# Arguments, "Optional" arguments might be empty:
# $1: resolved absolute path of the current file
# $2: current file number
# $3: total file number
# $4: image width (Optional: Disabled on thumbnails mode)
# $5: image height (Optional: Disabled on thumbnails mode)
# $6: current zoom (Optional: Disabled on thumbnails mode)
#
# The term file is used rather than image as nsxiv does not
# precheck that the input files are valid images. Total file
# count may be different from the actual count of valid images.
exec 2>/dev/null
filename="${1##*/}"
if [ -n "$4" ]; then # image mode
printf "%s" "nsxiv - ${filename} | ${4}x${5} ${6}% [${2}/${3}]"
else
printf "%s" "nsxiv - ${filename} [${2}/${3}]"
fi

38
main.c
View file

@ -87,6 +87,10 @@ static struct {
bool warned; bool warned;
} keyhandler; } keyhandler;
static struct {
extcmd_t f;
} wintitle;
static timeout_t timeouts[] = { static timeout_t timeouts[] = {
{ { 0, 0 }, false, redraw }, { { 0, 0 }, false, redraw },
{ { 0, 0 }, false, reset_cursor }, { { 0, 0 }, false, reset_cursor },
@ -229,6 +233,33 @@ static bool check_timeouts(struct timeval *t)
return tmin > 0; return tmin > 0;
} }
size_t get_win_title(char *buf, int len)
{
char *argv[8];
spawn_t pfd;
char w[12] = "", h[12] = "", z[12] = "", fidx[12], fcnt[12];
ssize_t n = -1;
if (wintitle.f.err || buf == NULL || len <= 0)
return 0;
if (mode == MODE_IMAGE) {
snprintf(w, ARRLEN(w), "%d", img.w);
snprintf(h, ARRLEN(h), "%d", img.h);
snprintf(z, ARRLEN(z), "%d", (int)(img.zoom * 100));
}
snprintf(fidx, ARRLEN(fidx), "%d", fileidx+1);
snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt);
construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path,
fidx, fcnt, w, h, z, NULL);
pfd = spawn(wintitle.f.cmd, argv, X_READ);
if (pfd.readfd >= 0) {
if ((n = read(pfd.readfd, buf, len-1)) > 0)
buf[n] = '\0';
}
return MAX(0, n);
}
void close_info(void) void close_info(void)
{ {
if (info.fd != -1) { if (info.fd != -1) {
@ -320,7 +351,6 @@ void load_image(int new)
close_info(); close_info();
open_info(); open_info();
arl_setup(&arl, files[fileidx].path); arl_setup(&arl, files[fileidx].path);
win_set_title(&win, files[fileidx].path);
if (img.multi.cnt > 0 && img.multi.animate) if (img.multi.cnt > 0 && img.multi.animate)
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
@ -429,6 +459,7 @@ void redraw(void)
tns_render(&tns); tns_render(&tns);
} }
update_info(); update_info();
win_set_title(&win);
win_draw(&win); win_draw(&win);
reset_timeout(redraw); reset_timeout(redraw);
reset_cursor(); reset_cursor();
@ -879,8 +910,8 @@ int main(int argc, char *argv[])
dsuffix = "/.config"; dsuffix = "/.config";
} }
if (homedir != NULL) { if (homedir != NULL) {
extcmd_t *cmd[] = { &info.f, &keyhandler.f }; extcmd_t *cmd[] = { &info.f, &keyhandler.f, &wintitle.f };
const char *name[] = { "image-info", "key-handler" }; const char *name[] = { "image-info", "key-handler", "win-title" };
const char *s = "/nsxiv/exec/"; const char *s = "/nsxiv/exec/";
for (i = 0; i < ARRLEN(cmd); i++) { for (i = 0; i < ARRLEN(cmd); i++) {
@ -906,7 +937,6 @@ int main(int argc, char *argv[])
load_image(fileidx); load_image(fileidx);
} }
win_open(&win); win_open(&win);
win_set_title(&win, files[fileidx].path);
win_set_cursor(&win, CURSOR_WATCH); win_set_cursor(&win, CURSOR_WATCH);
atexit(cleanup); atexit(cleanup);

33
nsxiv.1
View file

@ -20,8 +20,6 @@ nsxiv \- Neo Simple X Image Viewer
.IR DELAY ] .IR DELAY ]
.RB [ \-s .RB [ \-s
.IR MODE ] .IR MODE ]
.RB [ \-T
.IR TITLE ]
.RB [ \-z .RB [ \-z
.IR ZOOM ] .IR ZOOM ]
.IR FILE ... .IR FILE ...
@ -101,19 +99,6 @@ may be a floating point number.
Set scale mode according to MODE character. Supported modes are: [d]own, Set scale mode according to MODE character. Supported modes are: [d]own,
[f]it, [F]ill, [w]idth, [h]eight. [f]it, [F]ill, [w]idth, [h]eight.
.TP .TP
.BI "\-T " TITLE
Set the window title to TITLE. Use the format `prefix:suffixmode'. Any string
literal is accepted for prefix, and the format of suffixmode is:
.EX
Value Format
0 Empty
1 Basename of file
2 Full path to file
.EE
By default, prefix is set to "nsxiv - " and suffixmode is set to 1 (basename).
.TP
.B \-t .B \-t
Start in thumbnail mode. Start in thumbnail mode.
.TP .TP
@ -439,6 +424,24 @@ Color of the bar foreground. Defaults to window.foreground
Color of the mark foreground. Defaults to window.foreground Color of the mark foreground. Defaults to window.foreground
.TP .TP
Please see xrdb(1) on how to change them. Please see xrdb(1) on how to change them.
.SH WINDOW TITLE
The window title can be replaced with the output of a user-provided script,
which is called by nsxiv whenever there's a redraw. The path of this script is
.I $XDG_CONFIG_HOME/nsxiv/exec/win-title
and the arguments given to it (where "Optional" arguments might be empty) are:
1) resolved absolute path of the current file,
2) current file number,
3) total file count,
4) image width (Optional: Disabled on thumbnails mode),
5) image height (Optional: Disabled on thumbnails mode),
6) current zoom (Optional: Disabled on thumbnails mode).
.P
The term file is used rather than image as nsxiv does not precheck that the
input files are valid images. Total file count may be different from the actual
count of valid images.
.P
There is also an example script installed together with nsxiv as
.IR EGPREFIX/win-title .
.SH STATUS BAR .SH STATUS BAR
The information displayed on the left side of the status bar can be replaced The information displayed on the left side of the status bar can be replaced
with the output of a user-provided script, which is called by nsxiv whenever an with the output of a user-provided script, which is called by nsxiv whenever an

10
nsxiv.h
View file

@ -111,12 +111,6 @@ typedef enum {
FF_TN_INIT = 4 FF_TN_INIT = 4
} fileflags_t; } fileflags_t;
typedef enum {
SUFFIX_EMPTY,
SUFFIX_BASENAME,
SUFFIX_FULLPATH
} suffixmode_t;
typedef struct { typedef struct {
const char *name; /* as given by user */ const char *name; /* as given by user */
const char *path; /* always absolute */ const char *path; /* always absolute */
@ -265,8 +259,6 @@ struct opt {
Window embed; /* unsigned long */ Window embed; /* unsigned long */
char *geometry; char *geometry;
char *res_name; char *res_name;
const char *title_prefix;
suffixmode_t title_suffixmode;
/* misc flags: */ /* misc flags: */
bool quiet; bool quiet;
@ -448,7 +440,7 @@ void win_toggle_bar(win_t*);
void win_clear(win_t*); void win_clear(win_t*);
void win_draw(win_t*); void win_draw(win_t*);
void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long); void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long);
void win_set_title(win_t*, const char*); void win_set_title(win_t*);
void win_set_cursor(win_t*, cursor_t); void win_set_cursor(win_t*, cursor_t);
void win_cursor_pos(win_t*, int*, int*); void win_cursor_pos(win_t*, int*, int*);

View file

@ -18,8 +18,6 @@
*/ */
#include "nsxiv.h" #include "nsxiv.h"
#define _TITLE_CONFIG
#include "config.h"
#include "version.h" #include "version.h"
#include <stdlib.h> #include <stdlib.h>
@ -31,10 +29,23 @@ const opt_t *options;
void print_usage(void) void print_usage(void)
{ {
printf("usage: nsxiv [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] " printf("usage: nsxiv [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] "
"[-g GEOMETRY] [-N NAME] [-T TITLE] [-n NUM] [-S DELAY] [-s MODE] " "[-g GEOMETRY] [-N NAME] [-n NUM] [-S DELAY] [-s MODE] "
"[-z ZOOM] FILES...\n"); "[-z ZOOM] FILES...\n");
} }
static void title_deprecation_notice(void)
{
error(EXIT_FAILURE, 0, "\n"
"################################################################\n"
"# DEPRECATION NOTICE #\n"
"################################################################\n"
"# `-T` option has been deprecated in favour of `win-title`. #\n"
"# Please read the `WINDOW TITLE` section of the manpage for #\n"
"# more info. #\n"
"################################################################"
);
}
static void print_version(void) static void print_version(void)
{ {
puts("nsxiv " VERSION); puts("nsxiv " VERSION);
@ -69,8 +80,6 @@ void parse_options(int argc, char **argv)
_options.hide_bar = false; _options.hide_bar = false;
_options.geometry = NULL; _options.geometry = NULL;
_options.res_name = NULL; _options.res_name = NULL;
_options.title_prefix = TITLE_PREFIX;
_options.title_suffixmode = TITLE_SUFFIXMODE;
_options.quiet = false; _options.quiet = false;
_options.thumb_mode = false; _options.thumb_mode = false;
@ -155,14 +164,7 @@ void parse_options(int argc, char **argv)
_options.scalemode = s - scalemodes; _options.scalemode = s - scalemodes;
break; break;
case 'T': case 'T':
if ((s = strrchr(optarg, ':')) != NULL) { title_deprecation_notice(); /* TODO(v30): remove this option */
*s = '\0';
n = strtol(++s, &end, 0);
if (*end != '\0' || n < SUFFIX_EMPTY || n > SUFFIX_FULLPATH)
error(EXIT_FAILURE, 0, "Invalid argument for option -T suffixmode: %s", s);
_options.title_suffixmode = n;
}
_options.title_prefix = optarg;
break; break;
case 't': case 't':
_options.thumb_mode = true; _options.thumb_mode = true;

View file

@ -36,7 +36,6 @@ void exif_auto_orientate(const fileinfo_t*);
Imlib_Image img_open(const fileinfo_t*); Imlib_Image img_open(const fileinfo_t*);
static char *cache_dir; static char *cache_dir;
extern const int fileidx;
static char* tns_cache_filepath(const char *filepath) static char* tns_cache_filepath(const char *filepath)
{ {
@ -530,7 +529,6 @@ bool tns_move_selection(tns_t *tns, direction_t dir, int cnt)
if (!tns->dirty) if (!tns->dirty)
tns_highlight(tns, *tns->sel, true); tns_highlight(tns, *tns->sel, true);
} }
win_set_title(tns->win, tns->files[fileidx].path);
return *tns->sel != old; return *tns->sel != old;
} }

View file

@ -30,6 +30,8 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xresource.h> #include <X11/Xresource.h>
extern size_t get_win_title(char *, int);
#if HAVE_LIBFONTS #if HAVE_LIBFONTS
#include "utf8.h" #include "utf8.h"
static XftFont *font; static XftFont *font;
@ -499,27 +501,20 @@ void win_draw_rect(win_t *win, int x, int y, int w, int h, bool fill, int lw,
XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h); XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h);
} }
void win_set_title(win_t *win, const char *path) void win_set_title(win_t *win)
{ {
enum { title_max = 512 }; char title[512];
char title[title_max]; size_t len;
const char *basename = strrchr(path, '/') + 1;
/* Return if window is not ready yet */ if ((len = get_win_title(title, ARRLEN(title))) <= 0)
if (win->xwin == None)
return; return;
snprintf(title, title_max, "%s%s", options->title_prefix,
options->title_suffixmode == SUFFIX_BASENAME ? basename : path);
if (options->title_suffixmode == SUFFIX_EMPTY)
*(title+strlen(options->title_prefix)) = '\0';
XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_NAME], XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_NAME],
XInternAtom(win->env.dpy, "UTF8_STRING", False), 8, XInternAtom(win->env.dpy, "UTF8_STRING", False), 8,
PropModeReplace, (unsigned char *) title, strlen(title)); PropModeReplace, (unsigned char *) title, len);
XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_ICON_NAME], XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_ICON_NAME],
XInternAtom(win->env.dpy, "UTF8_STRING", False), 8, XInternAtom(win->env.dpy, "UTF8_STRING", False), 8,
PropModeReplace, (unsigned char *) title, strlen(title)); PropModeReplace, (unsigned char *) title, len);
} }
void win_set_cursor(win_t *win, cursor_t cursor) void win_set_cursor(win_t *win, cursor_t cursor)