Skip to content

Commit

Permalink
rework scrotWaitUntil() => scrotSleepFor()
Browse files Browse the repository at this point in the history
absolute time is really awkward to use. scrotSleepFor() instead takes a
starting timestamp and a relative millisecond offset from that start and
returns back the ending timestamp.

this, combined with clockNow(), makes the API easy to use and easy to
replace the existing nanosleep calls with.
  • Loading branch information
N-R-K committed May 27, 2023
1 parent 646f713 commit a57459c
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 20 deletions.
39 changes: 23 additions & 16 deletions src/scrot.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ static Imlib_Image scrotGrabFocused(void);
static void applyFilterIfRequired(void);
static Imlib_Image scrotGrabAutoselect(void);
static long miliToNanoSec(int);
static void scrotWaitUntil(const struct timespec *);
static Imlib_Image scrotGrabShotMulti(void);
static Imlib_Image scrotGrabShotMonitor(void);
static Imlib_Image scrotGrabStackWindows(void);
Expand Down Expand Up @@ -336,13 +335,11 @@ void scrotDoDelay(void)
dprintf(STDERR_FILENO, "Taking shot in ");
for (int i = opt.delay; i > 0; i--) {
dprintf(STDERR_FILENO, "%d.. ", i);
opt.delayStart.tv_sec++;
scrotWaitUntil(&opt.delayStart);
opt.delayStart = scrotSleepFor(opt.delayStart, 1000);
}
dprintf(STDERR_FILENO, "0.\n");
} else {
opt.delayStart.tv_sec += opt.delay;
scrotWaitUntil(&opt.delayStart);
scrotSleepFor(opt.delayStart, opt.delay * 1000);
}
}

Expand All @@ -366,13 +363,22 @@ struct timespec clockNow(void)
return ret;
}

/* scrotWaitUntil: clock_nanosleep with a simpler interface and no EINTR nagging
/* OpenBSD and OS X lack clock_nanosleep(), so we call nanosleep() and use a
* trivial algorithm to correct for drift. The end timespec is returned for
* callers that want it. EINTR is also dealt with.
*/
static void scrotWaitUntil(const struct timespec *time)
struct timespec scrotSleepFor(struct timespec start, int ms)
{
/* OpenBSD and OS X lack clock_nanosleep(), so we use a trivial algorithm to
* correct for drift and call nanosleep() everywhere.
*/
scrotAssert(ms >= 0);
struct timespec end = {
.tv_sec = start.tv_sec + (ms / 1000),
.tv_nsec = start.tv_nsec + miliToNanoSec(ms % 1000),
};
if (end.tv_nsec >= miliToNanoSec(1000)) {
++end.tv_sec;
end.tv_nsec -= miliToNanoSec(1000);
}

struct timespec tmp;
do {
tmp = clockNow();
Expand All @@ -381,13 +387,15 @@ static void scrotWaitUntil(const struct timespec *time)
* doesn't support OS X save for an unmaintained fork. libobsd supports
* OS X but doesn't have the macro yet.
*/
tmp.tv_sec = time->tv_sec - tmp.tv_sec;
tmp.tv_nsec = time->tv_nsec - tmp.tv_nsec;
tmp.tv_sec = end.tv_sec - tmp.tv_sec;
tmp.tv_nsec = end.tv_nsec - tmp.tv_nsec;
if (tmp.tv_nsec < 0) {
tmp.tv_sec--;
--tmp.tv_sec;
tmp.tv_nsec += miliToNanoSec(1000);
}
} while (nanosleep(&tmp, NULL) == -1 && errno == EINTR);
} while (nanosleep(&tmp, NULL) < 0 && errno == EINTR);

return end;
}

/* Clip rectangle nicely */
Expand Down Expand Up @@ -450,8 +458,7 @@ int scrotGetGeometry(Window target, int *rx, int *ry, int *rw, int *rh)
/* HACK: there doesn't seem to be any way to figure out whether the
* raise request was accepted or rejected. so just sleep a bit to
* give the WM some time to update. */
struct timespec t = { .tv_nsec = 160 * 1000L * 1000L };
while (nanosleep(&t, &t) < 0 && errno == EINTR);
scrotSleepFor(clockNow(), 160);
}
}
stat = XGetWindowAttributes(disp, target, &attr);
Expand Down
1 change: 1 addition & 0 deletions src/scrot.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ Window scrotGetWindow(Display *, Window, int, int);
int scrotGetGeometry(Window, int *, int *, int *, int *);
void scrotNiceClip(int *, int *, int *, int *);
struct timespec clockNow(void);
struct timespec scrotSleepFor(struct timespec, int);
void scrotDoDelay(void);
void scrotGrabMousePointer(const Imlib_Image, const int, const int);
4 changes: 2 additions & 2 deletions src/scrot_selection.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,9 @@ bool scrotSelectionGetUserSel(struct SelectionRect *selectionRect)
ret = XGrabKeyboard(disp, root, False, GrabModeAsync, GrabModeAsync, CurrentTime);
if (ret == AlreadyGrabbed) {
int attempts = 20;
struct timespec delay = { 0, 50 * 1000L * 1000L };
struct timespec t = clockNow();
do {
nanosleep(&delay, NULL);
t = scrotSleepFor(t, 50);
ret = XGrabKeyboard(disp, root, False, GrabModeAsync, GrabModeAsync, CurrentTime);
} while (--attempts > 0 && ret == AlreadyGrabbed);
}
Expand Down
3 changes: 1 addition & 2 deletions src/selection_edge.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ void selectionEdgeDestroy(void)
* might not have been updated. a compositor might also buffer frames
* adding latency. so wait a bit for the screen to update and the
* selection borders to go away. */
struct timespec t = { .tv_nsec = 80 * 1000L * 1000L };
while (nanosleep(&t, &t) < 0 && errno == EINTR);
scrotSleepFor(clockNow(), 80);

XFree(pe->classHint);
}
Expand Down

0 comments on commit a57459c

Please sign in to comment.