diff options
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | README.md | 15 | ||||
| -rw-r--r-- | TODO | 3 | ||||
| -rw-r--r-- | image.c | 48 | ||||
| -rw-r--r-- | image.h | 6 | ||||
| -rw-r--r-- | main.c | 20 | ||||
| -rw-r--r-- | sxiv.1 | 90 | ||||
| -rw-r--r-- | sxiv.h | 2 | ||||
| -rw-r--r-- | window.c | 43 | ||||
| -rw-r--r-- | window.h | 4 | 
10 files changed, 219 insertions, 21 deletions
| @@ -1,8 +1,10 @@  all: sxiv +VERSION=git-20110126 +  CC?=gcc  PREFIX?=/usr/local -CFLAGS+= -std=c99 -Wall -pedantic -g +CFLAGS+= -std=c99 -Wall -pedantic -DVERSION=\"$(VERSION)\"  LDFLAGS+=   LIBS+= -lX11 -lImlib2 @@ -16,7 +18,10 @@ sxiv:	$(OBJFILES)  	$(CC) $(CFLAGS) -c -o $@ $<  install: all -	install -D -m 4755 -o root -g root sxiv $(PREFIX)/sbin/sxiv +	install -D -m 4755 -o root -g root sxiv $(PREFIX)/bin/sxiv +	mkdir -p $(PREFIX)/share/man/man1 +	sed "s/VERSION/$(VERSION)/g" sxiv.1 > $(PREFIX)/share/man/man1/sxiv.1 +	chmod 644 $(PREFIX)/share/man/man1/sxiv.1  clean:  	rm -f sxiv *.o @@ -2,9 +2,10 @@ sxiv: Simple (or small or suckless) X Image Viewer  sxiv is a really simple alternative to feh and qiv. Its only dependency is  imlib2. The primary goal for writing sxiv is to create an image viewer, which -only implements the most basic features required for fast image viewing. Its -code base should be kept small and clean to make it easy for you to dig into it -and customize it for your needs. +only implements the most basic features required for fast image viewing. It +works nicely with tiling window managers and its code base should be kept small +and clean to make it easy for you to dig into it and customize it for your +needs.  Installation  ------------ @@ -36,8 +37,12 @@ Use the following keys to control sxiv:      Escape       Quit sxiv and return an exit value of 2 (useful for scripting)      Space,n      Go to the next image      Backspace,p  Go to the previous image -		g/G          Go to first/last image -		[/]          Go 10 images backward/forward +    g/G          Go to first/last image +    [/]          Go 10 images backward/forward      +,=          Zoom in      -            Zoom out      h,j,k,l      Scroll left/down/up/right +    <,>          Rotate image (counter-)clockwise by 90 degrees +    f            Toggle fullscreen mode (requires an EWMH/NetWM compliant +                 window manager) +    a            Toggle anti-aliasing @@ -1,6 +1,3 @@  - mouse scrolling and zooming  - add some useful command line options -- write man page -- toggle aliasing -- fullscreen mode  - view all images in directories (recursive mode) @@ -33,8 +33,10 @@ void img_init(img_t *img, win_t *win) {  	zoom_min = zoom_levels[0] / 100.0;  	zoom_max = zoom_levels[zl_cnt - 1] / 100.0; -	if (img) +	if (img) {  		img->zoom = 1.0; +		img->aa = 1; +	}  	if (win) {  		imlib_context_set_display(win->env.dpy); @@ -63,6 +65,7 @@ int img_load(img_t *img, const char *filename) {  	}  	imlib_context_set_image(im); +	imlib_context_set_anti_alias(img->aa);  	img->re = 0;  	img->checkpan = 0; @@ -104,7 +107,7 @@ void img_render(img_t *img, win_t *win) {  	if (!img || !win || !imlib_context_get_image())  		return; -	if ((!img->re || !img->zoomed) && SCALE_MODE != SCALE_ZOOM) { +	if (!img->zoomed && SCALE_MODE != SCALE_ZOOM) {  		/* set zoom level to fit image into window */  		zw = (float) win->w / (float) img->w;  		zh = (float) win->h / (float) img->h; @@ -241,3 +244,44 @@ int img_pan(img_t *img, win_t *win, pandir_t dir) {  	return ox != img->x || oy != img->y;  } + +int img_rotate(img_t *img, win_t *win, int d) { +	int ox, oy, tmp; + +	if (!img || !win) +		return 0; + +	ox = d == 1 ? img->x : win->w - img->x - img->w * img->zoom; +	oy = d == 3 ? img->y : win->h - img->y - img->h * img->zoom; + +	imlib_image_orientate(d); + +	img->x = oy + (win->w - win->h) / 2; +	img->y = ox + (win->h - win->w) / 2; + +	tmp = img->w; +	img->w = img->h; +	img->h = tmp; + +	img->checkpan = 1; + +	return 1; +} + +int img_rotate_left(img_t *img, win_t *win) { +	return img_rotate(img, win, 3); +} + +int img_rotate_right(img_t *img, win_t *win) { +	return img_rotate(img, win, 1); +} + +int img_toggle_antialias(img_t *img) { +	if (!img) +		return 0; + +	img->aa ^= 1; +	imlib_context_set_anti_alias(img->aa); + +	return 1; +} @@ -39,6 +39,7 @@ typedef struct img_s {  	unsigned char re;  	unsigned char checkpan;  	unsigned char zoomed; +	unsigned char aa;  	int x;  	int y;  	int w; @@ -56,4 +57,9 @@ int img_zoom_out(img_t*);  int img_pan(img_t*, win_t*, pandir_t); +int img_rotate_left(img_t*, win_t*); +int img_rotate_right(img_t*, win_t*); + +int img_toggle_antialias(img_t*); +  #endif /* IMAGE_H */ @@ -181,7 +181,7 @@ void on_keypress(XEvent *ev) {  			cleanup();  			exit(0); -		/* navigate through image list */ +		/* navigate image list */  		case 'n':  			if (fileidx + 1 < filecnt) {  				img_load(&img, filenames[++fileidx]); @@ -245,6 +245,24 @@ void on_keypress(XEvent *ev) {  		case 'l':  			changed = img_pan(&img, &win, PAN_RIGHT);  			break; + +		/* rotation */ +		case '<': +			changed = img_rotate_left(&img, &win); +			break; +		case '>': +			changed = img_rotate_right(&img, &win); +			break; + +		/* control window */ +		case 'f': +			win_toggle_fullscreen(&win); +			break; + +		/* miscellaneous */ +		case 'a': +			changed = img_toggle_antialias(&img); +			break;  	}  	if (changed) { @@ -0,0 +1,90 @@ +.TH SXIV 1 sxiv\-VERSION +.SH NAME +sxiv \- Simple (or small or suckless) X Image Viewer +.SH SYNOPSIS +.B sxiv +.RB [ \-hv ] +.IR FILE ... +.SH DESCRIPTION +sxiv is a simple image viewer for X. It only has the most basic features +required for fast image viewing. +.P +Please note, that the fullscreen mode requires an EWMH/NetWM compliant window +manager. +.SH OPTIONS +.TP +.B \-h +Print brief usage information to standard output and exit. +.TP +.B \-v +Print version information to standard output and exit. +.SH KEYBOARD COMMANDS +.SS General +.TP +.B q +Quit sxiv. +.TP +.B Escape +Quit sxiv and return an exit value of 2. +.SS Navigate image list  +.TP +.BR Space ", " n +Go to the next image. +.TP +.BR Backspace ", " p +Go to the previous image. +.TP +.B g +Go to the first image. +.TP +.B G +Go to the last image. +.TP +.B [ +Go 10 images backward. +.TP +.B ] +Go 10 images forward. +.SS Zooming +.TP +.BR + ", " = +Zoom in. +.TP +.B \- +Zoom out. +.SS Panning +.TP +.B h +Pan left. +.TP +.B j +Pan down. +.TP +.B k +Pan up. +.TP +.B l +Pan right. +.SS Rotation +.TP +.B < +Rotate image counter-clockwise by 90 degrees. +.TP +.B > +Rotate image clockwise by 90 degrees. +.SS Control window +.TP +.B f +Toggle fullscreen mode. +.SS Miscellaneous +.TP +.B a +Toggle anti-aliasing. +.SH AUTHORS +.TP +Bert Muennich <ber.t at gmx.com> +.SH HOMEPAGE +.TP +http://github.com/muennich/sxiv +.SH SEE ALSO +.BR feh (1), qiv (1) @@ -21,8 +21,6 @@  #include "config.h" -#define VERSION "git-20110123" -  #define ABS(a)   ((a) < 0 ? (-(a)) : (a))  #define MIN(a,b) ((a) < (b) ? (a) : (b))  #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -18,17 +18,19 @@  #include <stdlib.h>  #include <stdio.h> +#include <string.h>  #include <X11/Xutil.h>  #include "sxiv.h"  #include "window.h" +GC bgc; +  void win_open(win_t *win) {  	win_env_t *e;  	XClassHint *classhint;  	XColor bgcol; -	XGCValues gcval;  	if (!win)  		return; @@ -48,6 +50,9 @@ void win_open(win_t *win) {  		                    &bgcol, &bgcol))  		DIE("could not allocate color: %s", BG_COLOR); +	win->bgcol = bgcol.pixel; +	win->pm = 0; +  	win->w = WIN_WIDTH;  	win->h = WIN_HEIGHT;  	if (win->w > e->scrw) @@ -66,9 +71,7 @@ void win_open(win_t *win) {  	XSelectInput(e->dpy, win->xwin,  	             StructureNotifyMask | KeyPressMask | ButtonPressMask); -	gcval.foreground = bgcol.pixel; -	win->bgc = XCreateGC(e->dpy, win->xwin, GCForeground, &gcval); -	win->pm = 0; +	bgc = XCreateGC(e->dpy, win->xwin, 0, None);  	win_set_title(win, "sxiv"); @@ -119,8 +122,34 @@ int win_configure(win_t *win, XConfigureEvent *c) {  	return changed;  } +void win_toggle_fullscreen(win_t *win) { +	XEvent ev; +	XClientMessageEvent *cm; + +	if (!win) +		return; + +	win->fullscreen ^= 1; + +	memset(&ev, 0, sizeof(ev)); +	ev.type = ClientMessage; + +	cm = &ev.xclient; +	cm->window = win->xwin; +	cm->message_type = XInternAtom(win->env.dpy, "_NET_WM_STATE", False); +	cm->format = 32; +	cm->data.l[0] = win->fullscreen; +	cm->data.l[1] = XInternAtom(win->env.dpy, "_NET_WM_STATE_FULLSCREEN", False); +	cm->data.l[2] = XInternAtom(win->env.dpy, "_NET_WM_STATE_ABOVE", False); +	cm->data.l[3] = 0; + +	XSendEvent(win->env.dpy, DefaultRootWindow(win->env.dpy), False, +	           SubstructureNotifyMask, &ev); +} +  void win_clear(win_t *win) {  	win_env_t *e; +	XGCValues gcval;  	if (!win)  		return; @@ -130,7 +159,11 @@ void win_clear(win_t *win) {  	if (win->pm)  		XFreePixmap(e->dpy, win->pm);  	win->pm = XCreatePixmap(e->dpy, win->xwin, e->scrw, e->scrh, e->depth); -	XFillRectangle(e->dpy, win->pm, win->bgc, 0, 0, e->scrw, e->scrh); + +	gcval.foreground = win->fullscreen ? BlackPixel(e->dpy, e->scr) : win->bgcol; +	XChangeGC(e->dpy, bgc, GCForeground, &gcval); + +	XFillRectangle(e->dpy, win->pm, bgc, 0, 0, e->scrw, e->scrh);  }  void win_draw(win_t *win) { @@ -33,7 +33,8 @@ typedef struct win_env_s {  typedef struct win_s {  	Window xwin;  	win_env_t env; -	GC bgc; + +	unsigned long bgcol;  	Pixmap pm;  	int w; @@ -51,6 +52,7 @@ void win_close(win_t*);  void win_set_title(win_t*, const char*);  int win_configure(win_t*, XConfigureEvent*); +void win_toggle_fullscreen(win_t*);  void win_clear(win_t*);  void win_draw(win_t*); | 
