Compare commits

..

No commits in common. "1d28627868f5133a25a0197af21a187799ffa98e" and "a75411567e6670a1ce37f0db5d7d79bd19a21d3b" have entirely different histories.

9 changed files with 114 additions and 76 deletions

View File

@ -1,4 +1,4 @@
version = 26 version = 25+
srcdir = . srcdir = .
VPATH = $(srcdir) VPATH = $(srcdir)

View File

@ -32,27 +32,9 @@ Screenshots
![Thumb](http://muennich.github.com/sxiv/img/thumb.png "Thumb mode") ![Thumb](http://muennich.github.com/sxiv/img/thumb.png "Thumb mode")
Dependencies Installation
------------ ------------
sxiv requires the following software to be installed:
* Imlib2
* X11
* Xft
* freetype2
* fontconfig
* giflib (optional, disabled with `HAVE_GIFLIB=0`)
* libexif (optional, disabled with `HAVE_LIBEXIF=0`)
Please make sure to install the corresponding development packages in case that
you want to build sxiv on a distribution with separate runtime and development
packages (e.g. *-dev on Debian).
Building
--------
sxiv is built using the commands: sxiv is built using the commands:
$ make $ make
@ -92,11 +74,6 @@ on GitHub or get a copy using git with the following command:
**Stable releases** **Stable releases**
**[v26](https://github.com/muennich/sxiv/archive/v26.tar.gz)**
*(January 16, 2020)*
* Maintenance release
**[v25](https://github.com/muennich/sxiv/archive/v25.tar.gz)** **[v25](https://github.com/muennich/sxiv/archive/v25.tar.gz)**
*(January 26, 2019)* *(January 26, 2019)*

View File

@ -6,10 +6,17 @@ enum {
WIN_HEIGHT = 600 WIN_HEIGHT = 600
}; };
/* colors and font are configured with 'background', 'foreground' and /* bar font:
* 'font' X resource properties. * (see fonts-conf(5) subsection "FONT NAMES" for valid values)
* See X(7) section Resources and xrdb(1) for more information.
*/ */
static const char * const BAR_FONT = "monospace:size=8";
/* colors:
* overwritten by 'background' and 'foreground' X resource properties.
* (see X(7) section "COLOR NAMES" for valid values)
*/
static const char * const BG_COLOR = "#ffffea";
static const char * const FG_COLOR = "#555555";
#endif #endif
#ifdef _IMAGE_CONFIG #ifdef _IMAGE_CONFIG

View File

@ -497,7 +497,7 @@ void img_render(img_t *img)
} }
imlib_image_put_back_data(data); imlib_image_put_back_data(data);
} else { } else {
c = win->bg.pixel; c = win->fullscreen ? win->black.pixel : win->bg.pixel;
imlib_context_set_color(c >> 16 & 0xFF, c >> 8 & 0xFF, c & 0xFF, 0xFF); imlib_context_set_color(c >> 16 & 0xFF, c >> 8 & 0xFF, c & 0xFF, 0xFF);
imlib_image_fill_rectangle(0, 0, dw, dh); imlib_image_fill_rectangle(0, 0, dw, dh);
} }

2
main.c
View File

@ -774,7 +774,7 @@ void run(void)
} else { } else {
tns.dirty = true; tns.dirty = true;
} }
if (!resized) { if (!resized || win.fullscreen) {
redraw(); redraw();
set_timeout(clear_resize, TO_REDRAW_RESIZE, false); set_timeout(clear_resize, TO_REDRAW_RESIZE, false);
resized = true; resized = true;

17
sxiv.1
View File

@ -375,19 +375,6 @@ Zoom in.
.TP .TP
.B ScrollDown .B ScrollDown
Zoom out. Zoom out.
.SH CONFIGURATION
The following X resources are supported:
.TP
.B background
Color of the window background and bar foreground
.TP
.B foreground
Color of the window foreground and bar background
.TP
.B font
Name of Xft bar font
.TP
Please see xrdb(1) on how to change them.
.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 sxiv whenever an with the output of a user-provided script, which is called by sxiv whenever an
@ -444,5 +431,5 @@ Max Voit <mvdev at with-eyes.net>
https://github.com/muennich/sxiv https://github.com/muennich/sxiv
.EE .EE
.SH SEE ALSO .SH SEE ALSO
.BR X (7), .BR feh (1),
.BR xrdb (1) .BR qiv (1)

5
sxiv.h
View File

@ -385,6 +385,7 @@ enum {
ATOM__NET_WM_ICON, ATOM__NET_WM_ICON,
ATOM__NET_WM_STATE, ATOM__NET_WM_STATE,
ATOM__NET_WM_STATE_FULLSCREEN, ATOM__NET_WM_STATE_FULLSCREEN,
ATOM__NET_SUPPORTED,
ATOM_COUNT ATOM_COUNT
}; };
@ -407,8 +408,10 @@ struct win {
Window xwin; Window xwin;
win_env_t env; win_env_t env;
bool light; /* bg is lighter than fg */
XftColor bg; XftColor bg;
XftColor fg; XftColor fg;
XftColor black;
int x; int x;
int y; int y;
@ -416,6 +419,8 @@ struct win {
unsigned int h; /* = win height - bar height */ unsigned int h; /* = win height - bar height */
unsigned int bw; unsigned int bw;
bool fullscreen;
struct { struct {
int w; int w;
int h; int h;

View File

@ -469,14 +469,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) { if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) {
win_t *win = tns->win; win_t *win = tns->win;
thumb_t *t = &tns->thumbs[n]; thumb_t *t = &tns->thumbs[n];
unsigned long col = win->bg.pixel; unsigned long col = win->fullscreen ? win->black.pixel : win->bg.pixel;
int x = t->x + t->w, y = t->y + t->h; int x = t->x + t->w, y = t->y + t->h;
win_draw_rect(win, x - 1, y + 1, 1, tns->bw, true, 1, col); win_draw_rect(win, x - 1, y + 1, 1, tns->bw, true, 1, col);
win_draw_rect(win, x + 1, y - 1, tns->bw, 1, true, 1, col); win_draw_rect(win, x + 1, y - 1, tns->bw, 1, true, 1, col);
if (mark) if (mark)
col = win->fg.pixel; col = win->fullscreen && win->light ? win->bg.pixel : win->fg.pixel;
win_draw_rect(win, x, y, tns->bw + 2, tns->bw + 2, true, 1, col); win_draw_rect(win, x, y, tns->bw + 2, tns->bw + 2, true, 1, col);
@ -490,9 +490,14 @@ void tns_highlight(tns_t *tns, int n, bool hl)
if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) { if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) {
win_t *win = tns->win; win_t *win = tns->win;
thumb_t *t = &tns->thumbs[n]; thumb_t *t = &tns->thumbs[n];
unsigned long col = hl ? win->fg.pixel : win->bg.pixel; unsigned long col;
int oxy = (tns->bw + 1) / 2 + 1, owh = tns->bw + 2; int oxy = (tns->bw + 1) / 2 + 1, owh = tns->bw + 2;
if (hl)
col = win->fullscreen && win->light ? win->bg.pixel : win->fg.pixel;
else
col = win->fullscreen ? win->black.pixel : win->bg.pixel;
win_draw_rect(win, t->x - oxy, t->y - oxy, t->w + owh, t->h + owh, win_draw_rect(win, t->x - oxy, t->y - oxy, t->w + owh, t->h + owh,
false, tns->bw, col); false, tns->bw, col);

105
window.c
View File

@ -53,6 +53,9 @@ static int barheight;
Atom atoms[ATOM_COUNT]; Atom atoms[ATOM_COUNT];
static Bool fs_support;
static Bool fs_warned;
void win_init_font(const win_env_t *e, const char *fontstr) void win_init_font(const win_env_t *e, const char *fontstr)
{ {
if ((font = XftFontOpenName(e->dpy, e->scr, fontstr)) == NULL) if ((font = XftFontOpenName(e->dpy, e->scr, fontstr)) == NULL)
@ -71,14 +74,48 @@ void win_alloc_color(const win_env_t *e, const char *name, XftColor *col)
} }
} }
const char* win_res(XrmDatabase db, const char *name, const char *def) void win_check_wm_support(Display *dpy, Window root)
{
int format;
long offset = 0, length = 16;
Atom *data, type;
unsigned long i, nitems, bytes_left;
Bool found = False;
while (!found && length > 0) {
if (XGetWindowProperty(dpy, root, atoms[ATOM__NET_SUPPORTED],
offset, length, False, XA_ATOM, &type, &format,
&nitems, &bytes_left, (unsigned char**) &data))
{
break;
}
if (type == XA_ATOM && format == 32) {
for (i = 0; i < nitems; i++) {
if (data[i] == atoms[ATOM__NET_WM_STATE_FULLSCREEN]) {
found = True;
fs_support = True;
break;
}
}
}
XFree(data);
offset += nitems;
length = MIN(length, bytes_left / 4);
}
}
const char* win_res(Display *dpy, const char *name, const char *def)
{ {
char *type; char *type;
XrmValue ret; XrmValue ret;
XrmDatabase db;
char *res_man;
if (db != None && XrmInitialize();
XrmGetResource(db, name, name, &type, &ret) &&
STREQ(type, "String")) if ((res_man = XResourceManagerString(dpy)) != NULL &&
(db = XrmGetStringDatabase(res_man)) != NULL &&
XrmGetResource(db, name, name, &type, &ret) && STREQ(type, "String"))
{ {
return ret.addr; return ret.addr;
} else { } else {
@ -86,15 +123,18 @@ const char* win_res(XrmDatabase db, const char *name, const char *def)
} }
} }
unsigned int win_luminance(const XftColor *col)
{
return (col->color.red + col->color.green + col->color.blue) / 3;
}
#define INIT_ATOM_(atom) \ #define INIT_ATOM_(atom) \
atoms[ATOM_##atom] = XInternAtom(e->dpy, #atom, False); atoms[ATOM_##atom] = XInternAtom(e->dpy, #atom, False);
void win_init(win_t *win) void win_init(win_t *win)
{ {
win_env_t *e; win_env_t *e;
const char *bg, *fg, *f; const char *bg, *fg;
char *res_man;
XrmDatabase db;
memset(win, 0, sizeof(win_t)); memset(win, 0, sizeof(win_t));
@ -112,17 +152,14 @@ void win_init(win_t *win)
if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
error(0, 0, "No locale support"); error(0, 0, "No locale support");
XrmInitialize(); win_init_font(e, BAR_FONT);
res_man = XResourceManagerString(e->dpy);
db = res_man != NULL ? XrmGetStringDatabase(res_man) : None;
f = win_res(db, RES_CLASS ".font", "monospace-8"); bg = win_res(e->dpy, RES_CLASS ".background", BG_COLOR);
win_init_font(e, f); fg = win_res(e->dpy, RES_CLASS ".foreground", FG_COLOR);
bg = win_res(db, RES_CLASS ".background", "white");
fg = win_res(db, RES_CLASS ".foreground", "black");
win_alloc_color(e, bg, &win->bg); win_alloc_color(e, bg, &win->bg);
win_alloc_color(e, fg, &win->fg); win_alloc_color(e, fg, &win->fg);
win_alloc_color(e, "black", &win->black);
win->light = win_luminance(&win->bg) > win_luminance(&win->fg);
win->bar.l.size = BAR_L_LEN; win->bar.l.size = BAR_L_LEN;
win->bar.r.size = BAR_R_LEN; win->bar.r.size = BAR_R_LEN;
@ -139,6 +176,9 @@ void win_init(win_t *win)
INIT_ATOM_(_NET_WM_ICON); INIT_ATOM_(_NET_WM_ICON);
INIT_ATOM_(_NET_WM_STATE); INIT_ATOM_(_NET_WM_STATE);
INIT_ATOM_(_NET_WM_STATE_FULLSCREEN); INIT_ATOM_(_NET_WM_STATE_FULLSCREEN);
INIT_ATOM_(_NET_SUPPORTED);
win_check_wm_support(e->dpy, RootWindow(e->dpy, e->scr));
} }
void win_open(win_t *win) void win_open(win_t *win)
@ -154,6 +194,7 @@ void win_open(win_t *win)
Pixmap none; Pixmap none;
int gmask; int gmask;
XSizeHints sizehints; XSizeHints sizehints;
Bool fullscreen = options->fullscreen && fs_support;
e = &win->env; e = &win->env;
parent = options->embed != 0 ? options->embed : RootWindow(e->dpy, e->scr); parent = options->embed != 0 ? options->embed : RootWindow(e->dpy, e->scr);
@ -258,14 +299,14 @@ void win_open(win_t *win)
win->buf.h = e->scrh; win->buf.h = e->scrh;
win->buf.pm = XCreatePixmap(e->dpy, win->xwin, win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
win->buf.w, win->buf.h, e->depth); win->buf.w, win->buf.h, e->depth);
XSetForeground(e->dpy, gc, win->bg.pixel); XSetForeground(e->dpy, gc, fullscreen ? win->black.pixel : win->bg.pixel);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h); XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm); XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm);
XMapWindow(e->dpy, win->xwin); XMapWindow(e->dpy, win->xwin);
XFlush(e->dpy); XFlush(e->dpy);
if (options->fullscreen) if (fullscreen)
win_toggle_fullscreen(win); win_toggle_fullscreen(win);
} }
@ -302,6 +343,15 @@ void win_toggle_fullscreen(win_t *win)
XEvent ev; XEvent ev;
XClientMessageEvent *cm; XClientMessageEvent *cm;
if (!fs_support) {
if (!fs_warned) {
error(0, 0, "No fullscreen support");
fs_warned = True;
}
return;
}
win->fullscreen = !win->fullscreen;
memset(&ev, 0, sizeof(ev)); memset(&ev, 0, sizeof(ev));
ev.type = ClientMessage; ev.type = ClientMessage;
@ -309,8 +359,9 @@ void win_toggle_fullscreen(win_t *win)
cm->window = win->xwin; cm->window = win->xwin;
cm->message_type = atoms[ATOM__NET_WM_STATE]; cm->message_type = atoms[ATOM__NET_WM_STATE];
cm->format = 32; cm->format = 32;
cm->data.l[0] = 2; // toggle cm->data.l[0] = win->fullscreen;
cm->data.l[1] = atoms[ATOM__NET_WM_STATE_FULLSCREEN]; cm->data.l[1] = atoms[ATOM__NET_WM_STATE_FULLSCREEN];
cm->data.l[2] = cm->data.l[3] = 0;
XSendEvent(win->env.dpy, DefaultRootWindow(win->env.dpy), False, XSendEvent(win->env.dpy, DefaultRootWindow(win->env.dpy), False,
SubstructureNotifyMask | SubstructureRedirectMask, &ev); SubstructureNotifyMask | SubstructureRedirectMask, &ev);
@ -340,7 +391,7 @@ void win_clear(win_t *win)
win->buf.pm = XCreatePixmap(e->dpy, win->xwin, win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
win->buf.w, win->buf.h, e->depth); win->buf.w, win->buf.h, e->depth);
} }
XSetForeground(e->dpy, gc, win->bg.pixel); XSetForeground(e->dpy, gc, win->fullscreen ? win->black.pixel : win->bg.pixel);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h); XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
} }
@ -387,6 +438,7 @@ void win_draw_bar(win_t *win)
win_env_t *e; win_env_t *e;
win_bar_t *l, *r; win_bar_t *l, *r;
XftDraw *d; XftDraw *d;
const XftColor *bg, *fg;
if ((l = &win->bar.l)->buf == NULL || (r = &win->bar.r)->buf == NULL) if ((l = &win->bar.l)->buf == NULL || (r = &win->bar.r)->buf == NULL)
return; return;
@ -397,23 +449,28 @@ void win_draw_bar(win_t *win)
d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr), d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
DefaultColormap(e->dpy, e->scr)); DefaultColormap(e->dpy, e->scr));
XSetForeground(e->dpy, gc, win->fg.pixel); if (win->fullscreen && !win->light)
bg = &win->bg, fg = &win->fg;
else
bg = &win->fg, fg = &win->bg;
XSetForeground(e->dpy, gc, bg->pixel);
XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h); XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h);
XSetForeground(e->dpy, gc, win->bg.pixel); XSetForeground(e->dpy, gc, fg->pixel);
XSetBackground(e->dpy, gc, win->fg.pixel); XSetBackground(e->dpy, gc, bg->pixel);
if ((len = strlen(r->buf)) > 0) { if ((len = strlen(r->buf)) > 0) {
if ((tw = TEXTWIDTH(win, r->buf, len)) > w) if ((tw = TEXTWIDTH(win, r->buf, len)) > w)
return; return;
x = win->w - tw - H_TEXT_PAD; x = win->w - tw - H_TEXT_PAD;
w -= tw; w -= tw;
win_draw_text(win, d, &win->bg, x, y, r->buf, len, tw); win_draw_text(win, d, fg, x, y, r->buf, len, tw);
} }
if ((len = strlen(l->buf)) > 0) { if ((len = strlen(l->buf)) > 0) {
x = H_TEXT_PAD; x = H_TEXT_PAD;
w -= 2 * H_TEXT_PAD; /* gap between left and right parts */ w -= 2 * H_TEXT_PAD; /* gap between left and right parts */
win_draw_text(win, d, &win->bg, x, y, l->buf, len, w); win_draw_text(win, d, fg, x, y, l->buf, len, w);
} }
XftDrawDestroy(d); XftDrawDestroy(d);
} }