#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "img/image.h"
#include "types.h"
#include "color_bits.h"
Window create_window(Display *dpy, int xsz, int ysz);
XImage *create_ximage(Display *dpy, int xsz, int ysz, uint32_t *img);
void event_loop(Display *dpy, Window win, XImage *ximg);
int main(int argc, char **argv) {
Display *dpy;
Window win;
XImage *ximg;
int i;
uint32_t *img;
unsigned long xsz, ysz;
if(!(dpy = XOpenDisplay(0))) {
fprintf(stderr, "Could not connect to the X server\n");
return EXIT_FAILURE;
}
for(i=1; i<argc; i++) {
if(argv[i][0] == '-') {
fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
break;
} else {
if(!(img = load_image(argv[i], &xsz, &ysz))) {
continue;
}
win = create_window(dpy, xsz, ysz);
ximg = create_ximage(dpy, xsz, ysz, img);
if(win && ximg) {
event_loop(dpy, win, ximg);
}
if(ximg) XDestroyImage(ximg);
if(win) XDestroyWindow(dpy, win);
}
}
XCloseDisplay(dpy);
return 0;
}
Window create_window(Display *dpy, int xsz, int ysz) {
Window win, root_win;
int screen;
XSetWindowAttributes xattr;
Atom wm_delete;
XTextProperty tp_wname;
static char *win_title = "mindlapse :: image viewer";
XClassHint class_hint;
screen = DefaultScreen(dpy);
root_win = RootWindow(dpy, screen);
xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, screen);
xattr.colormap = DefaultColormap(dpy, screen);
win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, CopyFromParent, InputOutput,
DefaultVisual(dpy, screen), CWColormap | CWBackPixel | CWBorderPixel, &xattr);
XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask);
wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
XSetWMProtocols(dpy, win, &wm_delete, 1);
XStringListToTextProperty(&win_title, 1, &tp_wname);
XSetWMName(dpy, win, &tp_wname);
XFree(tp_wname.value);
class_hint.res_name = "imgv";
class_hint.res_class = "imgv_window";
XSetClassHint(dpy, win, &class_hint);
XMapWindow(dpy, win);
XFlush(dpy);
return win;
}
XImage *create_ximage(Display *dpy, int xsz, int ysz, uint32_t *img) {
XImage *ximg;
int screen = DefaultScreen(dpy);
if(!(ximg = XCreateImage(dpy, DefaultVisual(dpy, screen), 24, ZPixmap, 0, (void*)img, xsz, ysz, 8, 0))) {
fprintf(stderr, "XCreateImage failed\n");
return 0;
}
return ximg;
}
void event_loop(Display *dpy, Window win, XImage *ximg) {
KeySym keysym;
int window_mapped = 0;
while(1) {
XEvent event;
XNextEvent(dpy, &event);
switch(event.type) {
case MapNotify:
window_mapped = 1;
break;
case UnmapNotify:
window_mapped = 0;
break;
case Expose:
if(window_mapped && event.xexpose.count == 0) {
GC gc = XCreateGC(dpy, win, 0, 0);
XPutImage(dpy, win, gc, ximg, 0, 0, 0, 0, ximg->width, ximg->height);
XFreeGC(dpy, gc);
XFlush(dpy);
}
break;
case KeyPress:
keysym = XLookupKeysym((XKeyEvent*)&event.xkey, 0);
if((keysym & 0xff) == 27) {
return;
}
break;
case ClientMessage:
{
char *atom_name = XGetAtomName(dpy, event.xclient.message_type);
if(!strcmp(atom_name, "WM_PROTOCOLS")) {
XFree(atom_name);
return;
}
XFree(atom_name);
}
break;
default:
break;
}
}
}