nsxive26c81f
use win-title script for customizing window title (#213)
this removes the cli flag `-T` as well as related config.h options.
+103 −69
8 files changed
- M config.def.h +0 −13
- A examples/win-title +27 −0
- M main.c +34 −4
- M nsxiv.1 +18 −15
- M nsxiv.h +1 −9
- M options.c +15 −13
- M thumbs.c +0 −2
- M window.c +8 −13
| @@ -16,19 +16,6 @@ static const char *DEFAULT_BAR_FG = NULL; /* NULL means it will default to | |||
| 16 | 16 | static const char *DEFAULT_FONT = "monospace-8"; | |
| 17 | 17 | #endif | |
| 18 | 18 | ||
| 19 | − | #endif | |
| 20 | − | #ifdef _TITLE_CONFIG | |
| 21 | − | ||
| 22 | − | /* default title prefix */ | |
| 23 | − | static const char *TITLE_PREFIX = "nsxiv - "; | |
| 24 | − | ||
| 25 | − | /* default title suffixmode, available options are: | |
| 26 | − | * SUFFIX_EMPTY | |
| 27 | − | * SUFFIX_BASENAME | |
| 28 | − | * SUFFIX_FULLPATH | |
| 29 | − | */ | |
| 30 | − | static const suffixmode_t TITLE_SUFFIXMODE = SUFFIX_BASENAME; | |
| 31 | − | ||
| 32 | 19 | #endif | |
| 33 | 20 | #ifdef _IMAGE_CONFIG | |
| 34 | 21 | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | + | #!/bin/sh | |
| 2 | + | ||
| 3 | + | # Example for $XDG_CONFIG_HOME/nsxiv/exec/win-title | |
| 4 | + | # Called by nsxiv(1) on each redraw. | |
| 5 | + | # The output is set as nsxiv's window title. | |
| 6 | + | # | |
| 7 | + | # Arguments, "Optional" arguments might be empty: | |
| 8 | + | # $1: resolved absolute path of the current file | |
| 9 | + | # $2: current file number | |
| 10 | + | # $3: total file number | |
| 11 | + | # $4: image width (Optional: Disabled on thumbnails mode) | |
| 12 | + | # $5: image height (Optional: Disabled on thumbnails mode) | |
| 13 | + | # $6: current zoom (Optional: Disabled on thumbnails mode) | |
| 14 | + | # | |
| 15 | + | # The term file is used rather than image as nsxiv does not | |
| 16 | + | # precheck that the input files are valid images. Total file | |
| 17 | + | # count may be different from the actual count of valid images. | |
| 18 | + | ||
| 19 | + | exec 2>/dev/null | |
| 20 | + | ||
| 21 | + | filename="${1##*/}" | |
| 22 | + | ||
| 23 | + | if [ -n "$4" ]; then # image mode | |
| 24 | + | printf "%s" "nsxiv - ${filename} | ${4}x${5} ${6}% [${2}/${3}]" | |
| 25 | + | else | |
| 26 | + | printf "%s" "nsxiv - ${filename} [${2}/${3}]" | |
| 27 | + | fi | |
| @@ -87,6 +87,10 @@ static struct { | |||
| 87 | 87 | bool warned; | |
| 88 | 88 | } keyhandler; | |
| 89 | 89 | ||
| 90 | + | static struct { | |
| 91 | + | extcmd_t f; | |
| 92 | + | } wintitle; | |
| 93 | + | ||
| 90 | 94 | static timeout_t timeouts[] = { | |
| 91 | 95 | { { 0, 0 }, false, redraw }, | |
| 92 | 96 | { { 0, 0 }, false, reset_cursor }, | |
| @@ -229,6 +233,33 @@ static bool check_timeouts(struct timeval *t) | |||
| 229 | 233 | return tmin > 0; | |
| 230 | 234 | } | |
| 231 | 235 | ||
| 236 | + | size_t get_win_title(char *buf, int len) | |
| 237 | + | { | |
| 238 | + | char *argv[8]; | |
| 239 | + | spawn_t pfd; | |
| 240 | + | char w[12] = "", h[12] = "", z[12] = "", fidx[12], fcnt[12]; | |
| 241 | + | ssize_t n = -1; | |
| 242 | + | ||
| 243 | + | if (wintitle.f.err || buf == NULL || len <= 0) | |
| 244 | + | return 0; | |
| 245 | + | ||
| 246 | + | if (mode == MODE_IMAGE) { | |
| 247 | + | snprintf(w, ARRLEN(w), "%d", img.w); | |
| 248 | + | snprintf(h, ARRLEN(h), "%d", img.h); | |
| 249 | + | snprintf(z, ARRLEN(z), "%d", (int)(img.zoom * 100)); | |
| 250 | + | } | |
| 251 | + | snprintf(fidx, ARRLEN(fidx), "%d", fileidx+1); | |
| 252 | + | snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt); | |
| 253 | + | construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path, | |
| 254 | + | fidx, fcnt, w, h, z, NULL); | |
| 255 | + | pfd = spawn(wintitle.f.cmd, argv, X_READ); | |
| 256 | + | if (pfd.readfd >= 0) { | |
| 257 | + | if ((n = read(pfd.readfd, buf, len-1)) > 0) | |
| 258 | + | buf[n] = '\0'; | |
| 259 | + | } | |
| 260 | + | return MAX(0, n); | |
| 261 | + | } | |
| 262 | + | ||
| 232 | 263 | void close_info(void) | |
| 233 | 264 | { | |
| 234 | 265 | if (info.fd != -1) { | |
| @@ -320,7 +351,6 @@ void load_image(int new) | |||
| 320 | 351 | close_info(); | |
| 321 | 352 | open_info(); | |
| 322 | 353 | arl_setup(&arl, files[fileidx].path); | |
| 323 | − | win_set_title(&win, files[fileidx].path); | |
| 324 | 354 | ||
| 325 | 355 | if (img.multi.cnt > 0 && img.multi.animate) | |
| 326 | 356 | set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); | |
| @@ -429,6 +459,7 @@ void redraw(void) | |||
| 429 | 459 | tns_render(&tns); | |
| 430 | 460 | } | |
| 431 | 461 | update_info(); | |
| 462 | + | win_set_title(&win); | |
| 432 | 463 | win_draw(&win); | |
| 433 | 464 | reset_timeout(redraw); | |
| 434 | 465 | reset_cursor(); | |
| @@ -879,8 +910,8 @@ int main(int argc, char *argv[]) | |||
| 879 | 910 | dsuffix = "/.config"; | |
| 880 | 911 | } | |
| 881 | 912 | if (homedir != NULL) { | |
| 882 | − | extcmd_t *cmd[] = { &info.f, &keyhandler.f }; | |
| 883 | − | const char *name[] = { "image-info", "key-handler" }; | |
| 913 | + | extcmd_t *cmd[] = { &info.f, &keyhandler.f, &wintitle.f }; | |
| 914 | + | const char *name[] = { "image-info", "key-handler", "win-title" }; | |
| 884 | 915 | const char *s = "/nsxiv/exec/"; | |
| 885 | 916 | ||
| 886 | 917 | for (i = 0; i < ARRLEN(cmd); i++) { | |
| @@ -906,7 +937,6 @@ int main(int argc, char *argv[]) | |||
| 906 | 937 | load_image(fileidx); | |
| 907 | 938 | } | |
| 908 | 939 | win_open(&win); | |
| 909 | − | win_set_title(&win, files[fileidx].path); | |
| 910 | 940 | win_set_cursor(&win, CURSOR_WATCH); | |
| 911 | 941 | ||
| 912 | 942 | atexit(cleanup); | |
| @@ -20,8 +20,6 @@ nsxiv \- Neo Simple X Image Viewer | |||
| 20 | 20 | .IR DELAY ] | |
| 21 | 21 | .RB [ \-s | |
| 22 | 22 | .IR MODE ] | |
| 23 | − | .RB [ \-T | |
| 24 | − | .IR TITLE ] | |
| 25 | 23 | .RB [ \-z | |
| 26 | 24 | .IR ZOOM ] | |
| 27 | 25 | .IR FILE ... | |
| @@ -101,19 +99,6 @@ may be a floating point number. | |||
| 101 | 99 | Set scale mode according to MODE character. Supported modes are: [d]own, | |
| 102 | 100 | [f]it, [F]ill, [w]idth, [h]eight. | |
| 103 | 101 | .TP | |
| 104 | − | .BI "\-T " TITLE | |
| 105 | − | Set the window title to TITLE. Use the format `prefix:suffixmode'. Any string | |
| 106 | − | literal is accepted for prefix, and the format of suffixmode is: | |
| 107 | − | ||
| 108 | − | .EX | |
| 109 | − | Value Format | |
| 110 | − | 0 Empty | |
| 111 | − | 1 Basename of file | |
| 112 | − | 2 Full path to file | |
| 113 | − | .EE | |
| 114 | − | ||
| 115 | − | By default, prefix is set to "nsxiv - " and suffixmode is set to 1 (basename). | |
| 116 | − | .TP | |
| 117 | 102 | .B \-t | |
| 118 | 103 | Start in thumbnail mode. | |
| 119 | 104 | .TP | |
| @@ -439,6 +424,24 @@ Color of the bar foreground. Defaults to window.foreground | |||
| 439 | 424 | Color of the mark foreground. Defaults to window.foreground | |
| 440 | 425 | .TP | |
| 441 | 426 | Please see xrdb(1) on how to change them. | |
| 427 | + | .SH WINDOW TITLE | |
| 428 | + | The window title can be replaced with the output of a user-provided script, | |
| 429 | + | which is called by nsxiv whenever there's a redraw. The path of this script is | |
| 430 | + | .I $XDG_CONFIG_HOME/nsxiv/exec/win-title | |
| 431 | + | and the arguments given to it (where "Optional" arguments might be empty) are: | |
| 432 | + | 1) resolved absolute path of the current file, | |
| 433 | + | 2) current file number, | |
| 434 | + | 3) total file count, | |
| 435 | + | 4) image width (Optional: Disabled on thumbnails mode), | |
| 436 | + | 5) image height (Optional: Disabled on thumbnails mode), | |
| 437 | + | 6) current zoom (Optional: Disabled on thumbnails mode). | |
| 438 | + | .P | |
| 439 | + | The term file is used rather than image as nsxiv does not precheck that the | |
| 440 | + | input files are valid images. Total file count may be different from the actual | |
| 441 | + | count of valid images. | |
| 442 | + | .P | |
| 443 | + | There is also an example script installed together with nsxiv as | |
| 444 | + | .IR EGPREFIX/win-title . | |
| 442 | 445 | .SH STATUS BAR | |
| 443 | 446 | The information displayed on the left side of the status bar can be replaced | |
| 444 | 447 | with the output of a user-provided script, which is called by nsxiv whenever an | |
| @@ -111,12 +111,6 @@ typedef enum { | |||
| 111 | 111 | FF_TN_INIT = 4 | |
| 112 | 112 | } fileflags_t; | |
| 113 | 113 | ||
| 114 | − | typedef enum { | |
| 115 | − | SUFFIX_EMPTY, | |
| 116 | − | SUFFIX_BASENAME, | |
| 117 | − | SUFFIX_FULLPATH | |
| 118 | − | } suffixmode_t; | |
| 119 | − | ||
| 120 | 114 | typedef struct { | |
| 121 | 115 | const char *name; /* as given by user */ | |
| 122 | 116 | const char *path; /* always absolute */ | |
| @@ -265,8 +259,6 @@ struct opt { | |||
| 265 | 259 | Window embed; /* unsigned long */ | |
| 266 | 260 | char *geometry; | |
| 267 | 261 | char *res_name; | |
| 268 | − | const char *title_prefix; | |
| 269 | − | suffixmode_t title_suffixmode; | |
| 270 | 262 | ||
| 271 | 263 | /* misc flags: */ | |
| 272 | 264 | bool quiet; | |
| @@ -448,7 +440,7 @@ void win_toggle_bar(win_t*); | |||
| 448 | 440 | void win_clear(win_t*); | |
| 449 | 441 | void win_draw(win_t*); | |
| 450 | 442 | void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long); | |
| 451 | − | void win_set_title(win_t*, const char*); | |
| 443 | + | void win_set_title(win_t*); | |
| 452 | 444 | void win_set_cursor(win_t*, cursor_t); | |
| 453 | 445 | void win_cursor_pos(win_t*, int*, int*); | |
| 454 | 446 | ||
| @@ -18,8 +18,6 @@ | |||
| 18 | 18 | */ | |
| 19 | 19 | ||
| 20 | 20 | #include "nsxiv.h" | |
| 21 | − | #define _TITLE_CONFIG | |
| 22 | − | #include "config.h" | |
| 23 | 21 | #include "version.h" | |
| 24 | 22 | ||
| 25 | 23 | #include <stdlib.h> | |
| @@ -31,10 +29,23 @@ const opt_t *options; | |||
| 31 | 29 | void print_usage(void) | |
| 32 | 30 | { | |
| 33 | 31 | printf("usage: nsxiv [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] " | |
| 34 | − | "[-g GEOMETRY] [-N NAME] [-T TITLE] [-n NUM] [-S DELAY] [-s MODE] " | |
| 32 | + | "[-g GEOMETRY] [-N NAME] [-n NUM] [-S DELAY] [-s MODE] " | |
| 35 | 33 | "[-z ZOOM] FILES...\n"); | |
| 36 | 34 | } | |
| 37 | 35 | ||
| 36 | + | static void title_deprecation_notice(void) | |
| 37 | + | { | |
| 38 | + | error(EXIT_FAILURE, 0, "\n" | |
| 39 | + | "################################################################\n" | |
| 40 | + | "# DEPRECATION NOTICE #\n" | |
| 41 | + | "################################################################\n" | |
| 42 | + | "# `-T` option has been deprecated in favour of `win-title`. #\n" | |
| 43 | + | "# Please read the `WINDOW TITLE` section of the manpage for #\n" | |
| 44 | + | "# more info. #\n" | |
| 45 | + | "################################################################" | |
| 46 | + | ); | |
| 47 | + | } | |
| 48 | + | ||
| 38 | 49 | static void print_version(void) | |
| 39 | 50 | { | |
| 40 | 51 | puts("nsxiv " VERSION); | |
| @@ -69,8 +80,6 @@ void parse_options(int argc, char **argv) | |||
| 69 | 80 | _options.hide_bar = false; | |
| 70 | 81 | _options.geometry = NULL; | |
| 71 | 82 | _options.res_name = NULL; | |
| 72 | − | _options.title_prefix = TITLE_PREFIX; | |
| 73 | − | _options.title_suffixmode = TITLE_SUFFIXMODE; | |
| 74 | 83 | ||
| 75 | 84 | _options.quiet = false; | |
| 76 | 85 | _options.thumb_mode = false; | |
| @@ -155,14 +164,7 @@ void parse_options(int argc, char **argv) | |||
| 155 | 164 | _options.scalemode = s - scalemodes; | |
| 156 | 165 | break; | |
| 157 | 166 | case 'T': | |
| 158 | − | if ((s = strrchr(optarg, ':')) != NULL) { | |
| 159 | − | *s = '\0'; | |
| 160 | − | n = strtol(++s, &end, 0); | |
| 161 | − | if (*end != '\0' || n < SUFFIX_EMPTY || n > SUFFIX_FULLPATH) | |
| 162 | − | error(EXIT_FAILURE, 0, "Invalid argument for option -T suffixmode: %s", s); | |
| 163 | − | _options.title_suffixmode = n; | |
| 164 | − | } | |
| 165 | − | _options.title_prefix = optarg; | |
| 167 | + | title_deprecation_notice(); /* TODO(v30): remove this option */ | |
| 166 | 168 | break; | |
| 167 | 169 | case 't': | |
| 168 | 170 | _options.thumb_mode = true; | |
| @@ -36,7 +36,6 @@ void exif_auto_orientate(const fileinfo_t*); | |||
| 36 | 36 | Imlib_Image img_open(const fileinfo_t*); | |
| 37 | 37 | ||
| 38 | 38 | static char *cache_dir; | |
| 39 | − | extern const int fileidx; | |
| 40 | 39 | ||
| 41 | 40 | static char* tns_cache_filepath(const char *filepath) | |
| 42 | 41 | { | |
| @@ -530,7 +529,6 @@ bool tns_move_selection(tns_t *tns, direction_t dir, int cnt) | |||
| 530 | 529 | if (!tns->dirty) | |
| 531 | 530 | tns_highlight(tns, *tns->sel, true); | |
| 532 | 531 | } | |
| 533 | − | win_set_title(tns->win, tns->files[fileidx].path); | |
| 534 | 532 | return *tns->sel != old; | |
| 535 | 533 | } | |
| 536 | 534 | ||
| @@ -30,6 +30,8 @@ | |||
| 30 | 30 | #include <X11/Xatom.h> | |
| 31 | 31 | #include <X11/Xresource.h> | |
| 32 | 32 | ||
| 33 | + | extern size_t get_win_title(char *, int); | |
| 34 | + | ||
| 33 | 35 | #if HAVE_LIBFONTS | |
| 34 | 36 | #include "utf8.h" | |
| 35 | 37 | 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, | |||
| 499 | 501 | XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h); | |
| 500 | 502 | } | |
| 501 | 503 | ||
| 502 | − | void win_set_title(win_t *win, const char *path) | |
| 504 | + | void win_set_title(win_t *win) | |
| 503 | 505 | { | |
| 504 | − | enum { title_max = 512 }; | |
| 505 | − | char title[title_max]; | |
| 506 | − | const char *basename = strrchr(path, '/') + 1; | |
| 506 | + | char title[512]; | |
| 507 | + | size_t len; | |
| 507 | 508 | ||
| 508 | − | /* Return if window is not ready yet */ | |
| 509 | − | if (win->xwin == None) | |
| 509 | + | if ((len = get_win_title(title, ARRLEN(title))) <= 0) | |
| 510 | 510 | return; | |
| 511 | 511 | ||
| 512 | − | snprintf(title, title_max, "%s%s", options->title_prefix, | |
| 513 | − | options->title_suffixmode == SUFFIX_BASENAME ? basename : path); | |
| 514 | − | if (options->title_suffixmode == SUFFIX_EMPTY) | |
| 515 | − | *(title+strlen(options->title_prefix)) = '\0'; | |
| 516 | − | ||
| 517 | 512 | XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_NAME], | |
| 518 | 513 | XInternAtom(win->env.dpy, "UTF8_STRING", False), 8, | |
| 519 | − | PropModeReplace, (unsigned char *) title, strlen(title)); | |
| 514 | + | PropModeReplace, (unsigned char *) title, len); | |
| 520 | 515 | XChangeProperty(win->env.dpy, win->xwin, atoms[ATOM__NET_WM_ICON_NAME], | |
| 521 | 516 | XInternAtom(win->env.dpy, "UTF8_STRING", False), 8, | |
| 522 | − | PropModeReplace, (unsigned char *) title, strlen(title)); | |
| 517 | + | PropModeReplace, (unsigned char *) title, len); | |
| 523 | 518 | } | |
| 524 | 519 | ||
| 525 | 520 | void win_set_cursor(win_t *win, cursor_t cursor) | |