Compare commits

..

12 Commits

Author SHA1 Message Date
mrsu 99f685df84 .gitignore 2024-06-16 00:14:56 +01:00
mrsu 4e217429aa Merge branch 'master' 2024-06-16 00:14:35 +01:00
NRK 420a0a2455 ci: fix macos build
for whatever reason, the path where homebrew installs headers
and libraries are no longer being searched by default. work
around it by manually specifying them with -I and -L.
2024-06-06 10:50:15 +00:00
NRK 2a62683e60 fix: missing include in 65acb98
caught by the github CI.
the woodpecker CI somehow missed this.

Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/497
2024-06-05 21:02:02 +00:00
NRK 931912dcf6 make pipes non-blocking and read output on POLLHUP (#490)
this makes it so that script outputs are read when the script
actually finishes. one objection to reading on POLLHUP was that
the script might fill up the pipe and get stuck. we already mark
the read-end as non-blocking on our end so might as well make
the write-end non-blocking as well which avoids the script
getting blocked after (and if) it fills up the pipe.

ref: https://codeberg.org/nsxiv/nsxiv/pulls/334
Closes: https://codeberg.org/nsxiv/nsxiv/issues/377

Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/490
Reviewed-by: eylles <eylles@noreply.codeberg.org>
2024-06-05 19:40:58 +00:00
NRK 65acb98396 fix: unresponsive UI when animation is too fast (#489)
the previous check_timeouts() logic tried to greedily handle as
many timeouts as possible until there are no more active
timeouts left. this caused a number of issues such as:

https://codeberg.org/nsxiv/nsxiv/issues/439
https://codeberg.org/nsxiv/nsxiv-record/issues/281

the new logic relaxes this and only does a single iteration.
any remaining active timeout will be picked up by the next
iteration instead.

Fixes: https://codeberg.org/nsxiv/nsxiv/issues/439
2024-06-05 19:37:46 +00:00
e5150 a581cd6344 fix: image placement when rotating (#493)
When rotating a partially shown image (i.e. image size * zoom >
window size) the image is panned to top or left (if `win->w` or
`win->h` is greatest, respectively). Seems to be due to
unsignedness of `win->[wh]`, when taking the difference between
them in `img_rotate` either `img->[xy]` ends up being close to
`UINT_MAX` and the image is panned to top or left edge.

Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/493
Reviewed-by: NRK <nrk@disroot.org>
Co-authored-by: e5150 <e5150@noreply.codeberg.org>
Co-committed-by: e5150 <e5150@noreply.codeberg.org>
2024-04-23 06:47:09 +00:00
fxdn 437e060021 document Xresources application namespace explicitly (#488)
A decent amount of users have been confused by this.
So make it more explicit to avoid confusion.

Co-authored-by: NRK <nrk@disroot.org>
Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/488
Reviewed-by: NRK <nrk@disroot.org>
Co-authored-by: fxdn <fxdn@noreply.codeberg.org>
Co-committed-by: fxdn <fxdn@noreply.codeberg.org>
2024-02-17 08:14:05 +00:00
NRK 6cc1225fef free cache_tmpfile in tns_free (#485)
doesn't really matter since the process is about to exit
anyways, but makes it consistent with everything else.

Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/485
2024-02-12 22:00:31 +00:00
NRK 0faff1866d ci: adjust clang-tidy checks
disable misc-include-cleaner, it nags about "directly" including
things like "stdbool.h" instead of relying on "nsxiv.h" for it.

also disable bugprone-switch-missing-default-case which nags
about missing `default` switch cases.
2024-02-09 01:55:53 +00:00
mrsu b7f0e75a47 update 2023-08-31 14:58:12 +01:00
mrsu 0ed25a767a config 2023-06-29 13:43:21 +01:00
10 changed files with 58 additions and 41 deletions

View File

@ -47,7 +47,11 @@ jobs:
- name: build - name: build
run: | run: |
# libinotify-kqueue isn't available on homebrew # libinotify-kqueue isn't available on homebrew
make clean && make -s OPT_DEP_DEFAULT=1 HAVE_INOTIFY=0 make clean && make -s OPT_DEP_DEFAULT=1 HAVE_INOTIFY=0 \
CPPFLAGS="-I/opt/homebrew/include -I/opt/homebrew/include/freetype2" \
LDLIBS="-L/opt/homebrew/lib"
# force uninstallation with --ignore-dependencies # force uninstallation with --ignore-dependencies
brew uninstall --ignore-dependencies libxft libexif brew uninstall --ignore-dependencies libxft libexif
make clean && make -s OPT_DEP_DEFAULT=0 make clean && make -s OPT_DEP_DEFAULT=0 \
CPPFLAGS="-I/opt/homebrew/include" \
LDLIBS="-L/opt/homebrew/lib"

7
.gitignore vendored
View File

@ -1,6 +1,5 @@
config.h
version.h
*.d
*.o *.o
*.orig
*.rej
nsxiv nsxiv
icon/img2data config.h

View File

@ -11,9 +11,9 @@ static const char *WIN_BG[] = { "Nsxiv.window.background", "white" };
static const char *WIN_FG[] = { "Nsxiv.window.foreground", "black" }; static const char *WIN_FG[] = { "Nsxiv.window.foreground", "black" };
static const char *MARK_FG[] = { "Nsxiv.mark.foreground", NULL }; static const char *MARK_FG[] = { "Nsxiv.mark.foreground", NULL };
#if HAVE_LIBFONTS #if HAVE_LIBFONTS
static const char *BAR_BG[] = { "Nsxiv.bar.background", NULL }; static const char *BAR_BG[] = { "Nsxiv.bar.background", "#005577" };
static const char *BAR_FG[] = { "Nsxiv.bar.foreground", NULL }; static const char *BAR_FG[] = { "Nsxiv.bar.foreground", "#eadab1" };
static const char *BAR_FONT[] = { "Nsxiv.bar.font", "monospace-8" }; static const char *BAR_FONT[] = { "Nsxiv.bar.font", "monospace-16" };
/* if true, statusbar appears on top of the window */ /* if true, statusbar appears on top of the window */
static const bool TOP_STATUSBAR = false; static const bool TOP_STATUSBAR = false;
@ -74,10 +74,10 @@ static const bool ALPHA_LAYER = false;
#ifdef INCLUDE_THUMBS_CONFIG #ifdef INCLUDE_THUMBS_CONFIG
/* thumbnail sizes in pixels (width == height): */ /* thumbnail sizes in pixels (width == height): */
static const int thumb_sizes[] = { 32, 64, 96, 128, 160 }; static const int thumb_sizes[] = { 32, 64, 96, 128, 160, 256, 512, 800, 1024 };
/* thumbnail size at startup, index into thumb_sizes[]: */ /* thumbnail size at startup, index into thumb_sizes[]: */
static const int THUMB_SIZE = 3; static const int THUMB_SIZE = 7;
#endif #endif
#ifdef INCLUDE_MAPPINGS_CONFIG #ifdef INCLUDE_MAPPINGS_CONFIG

View File

@ -440,7 +440,9 @@ Zoom in.
.B Button5 .B Button5
Zoom out. Zoom out.
.SH CONFIGURATION .SH CONFIGURATION
The following X resources are supported: The following X resources are supported under "Nsxiv" (e.g.
.B Nsxiv.bar.font
):
.TP .TP
.B window.background .B window.background
Color of the window background Color of the window background

View File

@ -4,13 +4,13 @@ misc-*,android-cloexec-*,llvm-include-order
-readability-*,readability-duplicate-include,readability-misleading-indentation -readability-*,readability-duplicate-include,readability-misleading-indentation
# silence # silence
-misc-unused-parameters -misc-unused-parameters,-misc-include-cleaner,-misc-no-recursion
-bugprone-easily-swappable-parameters,-bugprone-narrowing-conversions,-bugprone-incorrect-roundings -bugprone-easily-swappable-parameters,-bugprone-narrowing-conversions,-bugprone-incorrect-roundings
-bugprone-implicit-widening-of-multiplication-result,-bugprone-integer-division -bugprone-implicit-widening-of-multiplication-result,-bugprone-integer-division
-android-cloexec-fopen,-android-cloexec-pipe,-cert-err33-c -android-cloexec-fopen,-android-cloexec-pipe,-cert-err33-c
-bugprone-assignment-in-if-condition -bugprone-assignment-in-if-condition
-bugprone-suspicious-realloc-usage -bugprone-suspicious-realloc-usage
-bugprone-switch-missing-default-case
# false positive warnings # false positive warnings
-clang-analyzer-valist.Uninitialized -clang-analyzer-valist.Uninitialized
-misc-no-recursion

View File

@ -676,8 +676,8 @@ void img_rotate(img_t *img, degree_t d)
ox = d == DEGREE_90 ? img->x : img->win->w - img->x - img->w * img->zoom; ox = d == DEGREE_90 ? img->x : img->win->w - img->x - img->w * img->zoom;
oy = d == DEGREE_270 ? img->y : img->win->h - img->y - img->h * img->zoom; oy = d == DEGREE_270 ? img->y : img->win->h - img->y - img->h * img->zoom;
img->x = oy + (img->win->w - img->win->h) / 2; img->x = oy + (int)(img->win->w - img->win->h) / 2;
img->y = ox + (img->win->h - img->win->w) / 2; img->y = ox + (int)(img->win->h - img->win->w) / 2;
tmp = img->w; tmp = img->w;
img->w = img->h; img->w = img->h;

41
main.c
View File

@ -25,6 +25,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <locale.h> #include <locale.h>
#include <poll.h> #include <poll.h>
#include <signal.h> #include <signal.h>
@ -249,10 +250,10 @@ void reset_timeout(timeout_f handler)
static bool check_timeouts(int *t) static bool check_timeouts(int *t)
{ {
int i = 0, tdiff, tmin = -1; int i = 0, tdiff, tmin;
struct timeval now; struct timeval now;
while (i < (int)ARRLEN(timeouts)) { for (i = 0; i < (int)ARRLEN(timeouts); ++i) {
if (timeouts[i].active) { if (timeouts[i].active) {
gettimeofday(&now, 0); gettimeofday(&now, 0);
tdiff = TV_DIFF(&timeouts[i].when, &now); tdiff = TV_DIFF(&timeouts[i].when, &now);
@ -260,16 +261,22 @@ static bool check_timeouts(int *t)
timeouts[i].active = false; timeouts[i].active = false;
if (timeouts[i].handler != NULL) if (timeouts[i].handler != NULL)
timeouts[i].handler(); timeouts[i].handler();
i = tmin = -1;
} else if (tmin < 0 || tdiff < tmin) {
tmin = tdiff;
} }
} }
i++;
} }
if (tmin > 0 && t != NULL)
*t = tmin; tmin = INT_MAX;
return tmin > 0; gettimeofday(&now, 0);
for (i = 0; i < (int)ARRLEN(timeouts); ++i) {
if (timeouts[i].active) {
tdiff = TV_DIFF(&timeouts[i].when, &now);
tmin = MIN(tmin, tdiff);
}
}
if (tmin != INT_MAX && t != NULL)
*t = MAX(tmin, 0);
return tmin != INT_MAX;
} }
static void autoreload(void) static void autoreload(void)
@ -328,8 +335,7 @@ static void open_title(void)
snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt); snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt);
construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path, construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path,
fidx, fcnt, w, h, z, NULL); fidx, fcnt, w, h, z, NULL);
if ((wintitle.pid = spawn(&wintitle.fd, NULL, argv)) > 0) wintitle.pid = spawn(&wintitle.fd, NULL, O_NONBLOCK, argv);
fcntl(wintitle.fd, F_SETFL, O_NONBLOCK);
} }
void close_info(void) void close_info(void)
@ -352,8 +358,7 @@ void open_info(void)
} }
construct_argv(argv, ARRLEN(argv), cmd, files[fileidx].name, w, h, construct_argv(argv, ARRLEN(argv), cmd, files[fileidx].name, w, h,
files[fileidx].path, NULL); files[fileidx].path, NULL);
if ((info.pid = spawn(&info.fd, NULL, argv)) > 0) info.pid = spawn(&info.fd, NULL, O_NONBLOCK, argv);
fcntl(info.fd, F_SETFL, O_NONBLOCK);
} }
static void read_info(void) static void read_info(void)
@ -643,7 +648,7 @@ static bool run_key_handler(const char *key, unsigned int mask)
mask & Mod1Mask ? "M-" : "", mask & Mod1Mask ? "M-" : "",
mask & ShiftMask ? "S-" : "", key); mask & ShiftMask ? "S-" : "", key);
construct_argv(argv, ARRLEN(argv), keyhandler.f.cmd, kstr, NULL); construct_argv(argv, ARRLEN(argv), keyhandler.f.cmd, kstr, NULL);
if ((pid = spawn(NULL, &writefd, argv)) < 0) if ((pid = spawn(NULL, &writefd, 0x0, argv)) < 0)
return false; return false;
if ((pfs = fdopen(writefd, "w")) == NULL) { if ((pfs = fdopen(writefd, "w")) == NULL) {
error(0, errno, "open pipe"); error(0, errno, "open pipe");
@ -800,13 +805,15 @@ static void run(void)
pfd[FD_INFO].fd = info.fd; pfd[FD_INFO].fd = info.fd;
pfd[FD_TITLE].fd = wintitle.fd; pfd[FD_TITLE].fd = wintitle.fd;
pfd[FD_ARL].fd = arl.fd; pfd[FD_ARL].fd = arl.fd;
pfd[FD_X].events = pfd[FD_INFO].events = pfd[FD_TITLE].events = pfd[FD_ARL].events = POLLIN;
pfd[FD_X].events = pfd[FD_ARL].events = POLLIN;
pfd[FD_INFO].events = pfd[FD_TITLE].events = 0;
if (poll(pfd, ARRLEN(pfd), to_set ? timeout : -1) < 0) if (poll(pfd, ARRLEN(pfd), to_set ? timeout : -1) < 0)
continue; continue;
if (pfd[FD_INFO].revents & POLLIN) if (pfd[FD_INFO].revents & POLLHUP)
read_info(); read_info();
if (pfd[FD_TITLE].revents & POLLIN) if (pfd[FD_TITLE].revents & POLLHUP)
read_title(); read_title();
if ((pfd[FD_ARL].revents & POLLIN) && arl_handle(&arl)) { if ((pfd[FD_ARL].revents & POLLIN) && arl_handle(&arl)) {
img.autoreload_pending = true; img.autoreload_pending = true;

View File

@ -356,7 +356,7 @@ int r_closedir(r_dir_t*);
char* r_readdir(r_dir_t*, bool); char* r_readdir(r_dir_t*, bool);
int r_mkdir(char*); int r_mkdir(char*);
void construct_argv(char**, unsigned int, ...); void construct_argv(char**, unsigned int, ...);
pid_t spawn(int*, int*, char *const []); pid_t spawn(int*, int*, int, char *const []);
/* window.c */ /* window.c */

View File

@ -198,6 +198,8 @@ CLEANUP void tns_free(tns_t *tns)
free(cache_dir); free(cache_dir);
cache_dir = NULL; cache_dir = NULL;
free(cache_tmpfile);
cache_tmpfile = cache_tmpfile_base = NULL;
} }
static Imlib_Image tns_scale_down(Imlib_Image im, int dim) static Imlib_Image tns_scale_down(Imlib_Image im, int dim)

17
util.c
View File

@ -21,6 +21,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <spawn.h> #include <spawn.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -230,25 +231,27 @@ void construct_argv(char **argv, unsigned int len, ...)
assert(argv[len - 1] == NULL && "argv should be NULL terminated"); assert(argv[len - 1] == NULL && "argv should be NULL terminated");
} }
static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx) static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx, int pipeflags)
{ {
int err; int err = 0;
if (pipe(pfd) < 0) { if (pipe(pfd) < 0) {
error(0, errno, "pipe: %s", cmd); error(0, errno, "pipe: %s", cmd);
return -1; return -1;
} }
err = posix_spawn_file_actions_adddup2(fa, pfd[dupidx], dupidx); if (pipeflags && (fcntl(pfd[0], F_SETFL, pipeflags) < 0 || fcntl(pfd[1], F_SETFL, pipeflags) < 0))
err = errno;
err = err ? err : posix_spawn_file_actions_adddup2(fa, pfd[dupidx], dupidx);
err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[0]); err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[0]);
err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[1]); err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[1]);
if (err) { if (err) {
error(0, err, "posix_spawn_file_actions: %s", cmd); error(0, err, "mkspawn_pipe: %s", cmd);
close(pfd[0]); close(pfd[0]);
close(pfd[1]); close(pfd[1]);
} }
return err ? -1 : 0; return err ? -1 : 0;
} }
pid_t spawn(int *readfd, int *writefd, char *const argv[]) pid_t spawn(int *readfd, int *writefd, int pipeflags, char *const argv[])
{ {
pid_t pid = -1; pid_t pid = -1;
const char *cmd; const char *cmd;
@ -263,9 +266,9 @@ pid_t spawn(int *readfd, int *writefd, char *const argv[])
return pid; return pid;
} }
if (readfd != NULL && mkspawn_pipe(&fa, cmd, pfd_read, 1) < 0) if (readfd != NULL && mkspawn_pipe(&fa, cmd, pfd_read, 1, pipeflags) < 0)
goto err_destroy_fa; goto err_destroy_fa;
if (writefd != NULL && mkspawn_pipe(&fa, cmd, pfd_write, 0) < 0) if (writefd != NULL && mkspawn_pipe(&fa, cmd, pfd_write, 0, pipeflags) < 0)
goto err_close_readfd; goto err_close_readfd;
if ((err = posix_spawnp(&pid, cmd, &fa, NULL, argv, environ)) != 0) { if ((err = posix_spawnp(&pid, cmd, &fa, NULL, argv, environ)) != 0) {