From 1d749382f00bb0bfdb900b6ddb0bb8b3743b99d0 Mon Sep 17 00:00:00 2001 From: Bert Date: Fri, 19 Aug 2011 15:02:10 +0200 Subject: [PATCH] Put event handling back into main.c; events -> commands --- Makefile | 2 +- events.c => commands.c | 211 +---------------------------------------- events.h => commands.h | 11 +-- main.c | 196 +++++++++++++++++++++++++++++++++++++- types.h | 7 ++ 5 files changed, 211 insertions(+), 216 deletions(-) rename events.c => commands.c (63%) rename events.h => commands.h (91%) diff --git a/Makefile b/Makefile index 991d1b4..852a966 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CFLAGS = -Wall -pedantic -O2 -DVERSION=\"$(VERSION)\" LDFLAGS = LIBS = -lX11 -lImlib2 -SRC = events.o image.c main.c options.c thumbs.c util.c window.c +SRC = commands.c image.c main.c options.c thumbs.c util.c window.c OBJ = $(SRC:.c=.o) sxiv: $(OBJ) diff --git a/events.c b/commands.c similarity index 63% rename from events.c rename to commands.c index 2862d23..7dbd019 100644 --- a/events.c +++ b/commands.c @@ -1,4 +1,4 @@ -/* sxiv: events.c +/* sxiv: commands.c * Copyright (c) 2011 Bert Muennich * * This program is free software; you can redistribute it and/or @@ -16,36 +16,20 @@ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA. */ -#define _GENERAL_CONFIG -#define _MAPPINGS_CONFIG - #include #include #include -#include #include -#include -#include -#include "events.h" +#include "commands.h" #include "image.h" #include "thumbs.h" #include "types.h" #include "util.h" -#include "window.h" -#include "config.h" - -/* timeouts in milliseconds: */ -enum { - TO_WIN_RESIZE = 75, - TO_CURSOR_HIDE = 1500, - TO_THUMBS_LOAD = 200 -}; void cleanup(); void remove_file(int, unsigned char); void load_image(int); -void update_title(); extern appmode_t mode; extern img_t img; @@ -55,193 +39,8 @@ extern win_t win; extern fileinfo_t *files; extern int filecnt, fileidx; -int timo_cursor; -int timo_redraw; - -void redraw() { - if (mode == MODE_IMAGE) { - img_render(&img, &win); - if (timo_cursor) - win_set_cursor(&win, CURSOR_ARROW); - else - win_set_cursor(&win, CURSOR_NONE); - } else { - tns_render(&tns, &win); - } - update_title(); - timo_redraw = 0; -} - -Bool keymask(const keymap_t *k, unsigned int state) { - return (k->ctrl ? ControlMask : 0) == (state & ControlMask); -} - -Bool buttonmask(const button_t *b, unsigned int state) { - return ((b->ctrl ? ControlMask : 0) | (b->shift ? ShiftMask : 0)) == - (state & (ControlMask | ShiftMask)); -} - -void on_keypress(XKeyEvent *kev) { - int i; - KeySym ksym; - char key; - - if (!kev) - return; - - XLookupString(kev, &key, 1, &ksym, NULL); - - for (i = 0; i < LEN(keys); i++) { - if (keys[i].ksym == ksym && keymask(&keys[i], kev->state)) { - if (keys[i].cmd && keys[i].cmd(keys[i].arg)) - redraw(); - return; - } - } -} - -void on_buttonpress(XButtonEvent *bev) { - int i, sel; - - if (!bev) - return; - - if (mode == MODE_IMAGE) { - win_set_cursor(&win, CURSOR_ARROW); - timo_cursor = TO_CURSOR_HIDE; - - for (i = 0; i < LEN(buttons); i++) { - if (buttons[i].button == bev->button && - buttonmask(&buttons[i], bev->state)) - { - if (buttons[i].cmd && buttons[i].cmd(buttons[i].arg)) - redraw(); - return; - } - } - } else { - /* thumbnail mode (hard-coded) */ - switch (bev->button) { - case Button1: - if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { - if (sel == tns.sel) { - load_image(tns.sel); - mode = MODE_IMAGE; - timo_cursor = TO_CURSOR_HIDE; - } else { - tns_highlight(&tns, &win, tns.sel, False); - tns_highlight(&tns, &win, sel, True); - tns.sel = sel; - } - redraw(); - break; - } - break; - case Button4: - case Button5: - if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN)) - redraw(); - break; - } - } -} - -void run() { - int xfd, timeout; - fd_set fds; - struct timeval tt, t0, t1; - XEvent ev; - - timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0; - - redraw(); - - while (1) { - if (mode == MODE_THUMB && tns.cnt < filecnt) { - /* load thumbnails */ - win_set_cursor(&win, CURSOR_WATCH); - gettimeofday(&t0, 0); - - while (tns.cnt < filecnt && !XPending(win.env.dpy)) { - if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False)) - tns.cnt++; - else - remove_file(tns.cnt, 0); - gettimeofday(&t1, 0); - if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD) - break; - } - if (tns.cnt == filecnt) - win_set_cursor(&win, CURSOR_ARROW); - if (!XPending(win.env.dpy)) { - redraw(); - continue; - } else { - timo_redraw = TO_THUMBS_LOAD; - } - } else if (timo_cursor || timo_redraw) { - /* check active timeouts */ - gettimeofday(&t0, 0); - timeout = MIN(timo_cursor + 1, timo_redraw + 1); - MSEC_TO_TIMEVAL(timeout, &tt); - xfd = ConnectionNumber(win.env.dpy); - FD_ZERO(&fds); - FD_SET(xfd, &fds); - - if (!XPending(win.env.dpy)) - select(xfd + 1, &fds, 0, 0, &tt); - gettimeofday(&t1, 0); - timeout = MIN(TIMEDIFF(&t1, &t0), timeout); - - /* timeouts fired? */ - if (timo_cursor) { - timo_cursor = MAX(0, timo_cursor - timeout); - if (!timo_cursor) - win_set_cursor(&win, CURSOR_NONE); - } - if (timo_redraw) { - timo_redraw = MAX(0, timo_redraw - timeout); - if (!timo_redraw) - redraw(); - } - if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy)) - continue; - } - - if (!XNextEvent(win.env.dpy, &ev)) { - /* handle events */ - switch (ev.type) { - case ButtonPress: - on_buttonpress(&ev.xbutton); - break; - case ClientMessage: - if ((Atom) ev.xclient.data.l[0] == wm_delete_win) - return; - break; - case ConfigureNotify: - if (win_configure(&win, &ev.xconfigure)) { - timo_redraw = TO_WIN_RESIZE; - if (mode == MODE_IMAGE) - img.checkpan = 1; - else - tns.dirty = 1; - } - break; - case KeyPress: - on_keypress(&ev.xkey); - break; - case MotionNotify: - if (!timo_cursor) - win_set_cursor(&win, CURSOR_ARROW); - timo_cursor = TO_CURSOR_HIDE; - break; - } - } - } -} - - -/* command functions for key and button mappings: */ +extern int timo_cursor; +extern int timo_redraw; int it_quit(arg_t a) { cleanup(); @@ -593,7 +392,7 @@ int it_shell_cmd(arg_t a) { end: if (mode == MODE_THUMB) win_set_cursor(&win, CURSOR_ARROW); - /* else: cursor is reset in redraw() */ + /* else: cursor gets reset in redraw() */ free(cmdline); diff --git a/events.h b/commands.h similarity index 91% rename from events.h rename to commands.h index 0b48055..c249d29 100644 --- a/events.h +++ b/commands.h @@ -1,4 +1,4 @@ -/* sxiv: events.h +/* sxiv: commands.h * Copyright (c) 2011 Bert Muennich * * This program is free software; you can redistribute it and/or @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA. */ -#ifndef EVENTS_H -#define EVENTS_H +#ifndef COMMANDS_H +#define COMMANDS_H #include @@ -39,9 +39,6 @@ typedef struct { arg_t arg; } button_t; -void run(); - -/* command functions for key and button mappings: */ int it_quit(arg_t); int it_switch_mode(arg_t); int it_toggle_fullscreen(arg_t); @@ -63,4 +60,4 @@ int i_toggle_alpha(arg_t); int it_open_with(arg_t); int it_shell_cmd(arg_t); -#endif /* EVENTS_H */ +#endif /* COMMANDS_H */ diff --git a/main.c b/main.c index d8dba0d..44b3e69 100644 --- a/main.c +++ b/main.c @@ -17,11 +17,15 @@ */ #include +#include #include #include #include +#include +#include +#include -#include "events.h" +#include "commands.h" #include "image.h" #include "options.h" #include "thumbs.h" @@ -29,6 +33,9 @@ #include "util.h" #include "window.h" +#define _MAPPINGS_CONFIG +#include "config.h" + enum { TITLE_LEN = 256, FNAME_CNT = 1024 @@ -45,6 +52,9 @@ size_t filesize; char win_title[TITLE_LEN]; +int timo_cursor; +int timo_redraw; + void cleanup() { static int in = 0; @@ -115,7 +125,7 @@ void load_image(int new) { if (new < 0 || new >= filecnt) return; - /* cursor is reset in redraw() */ + /* cursor gets reset in redraw() */ win_set_cursor(&win, CURSOR_WATCH); img_close(&img, 0); @@ -158,6 +168,188 @@ void update_title() { win_set_title(&win, win_title); } +void redraw() { + if (mode == MODE_IMAGE) { + img_render(&img, &win); + if (timo_cursor) + win_set_cursor(&win, CURSOR_ARROW); + else + win_set_cursor(&win, CURSOR_NONE); + } else { + tns_render(&tns, &win); + } + update_title(); + timo_redraw = 0; +} + +Bool keymask(const keymap_t *k, unsigned int state) { + return (k->ctrl ? ControlMask : 0) == (state & ControlMask); +} + +Bool buttonmask(const button_t *b, unsigned int state) { + return ((b->ctrl ? ControlMask : 0) | (b->shift ? ShiftMask : 0)) == + (state & (ControlMask | ShiftMask)); +} + +void on_keypress(XKeyEvent *kev) { + int i; + KeySym ksym; + char key; + + if (!kev) + return; + + XLookupString(kev, &key, 1, &ksym, NULL); + + for (i = 0; i < LEN(keys); i++) { + if (keys[i].ksym == ksym && keymask(&keys[i], kev->state)) { + if (keys[i].cmd && keys[i].cmd(keys[i].arg)) + redraw(); + return; + } + } +} + +void on_buttonpress(XButtonEvent *bev) { + int i, sel; + + if (!bev) + return; + + if (mode == MODE_IMAGE) { + win_set_cursor(&win, CURSOR_ARROW); + timo_cursor = TO_CURSOR_HIDE; + + for (i = 0; i < LEN(buttons); i++) { + if (buttons[i].button == bev->button && + buttonmask(&buttons[i], bev->state)) + { + if (buttons[i].cmd && buttons[i].cmd(buttons[i].arg)) + redraw(); + return; + } + } + } else { + /* thumbnail mode (hard-coded) */ + switch (bev->button) { + case Button1: + if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { + if (sel == tns.sel) { + load_image(tns.sel); + mode = MODE_IMAGE; + timo_cursor = TO_CURSOR_HIDE; + } else { + tns_highlight(&tns, &win, tns.sel, False); + tns_highlight(&tns, &win, sel, True); + tns.sel = sel; + } + redraw(); + break; + } + break; + case Button4: + case Button5: + if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN)) + redraw(); + break; + } + } +} + +void run() { + int xfd, timeout; + fd_set fds; + struct timeval tt, t0, t1; + XEvent ev; + + timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0; + + redraw(); + + while (1) { + if (mode == MODE_THUMB && tns.cnt < filecnt) { + /* load thumbnails */ + win_set_cursor(&win, CURSOR_WATCH); + gettimeofday(&t0, 0); + + while (tns.cnt < filecnt && !XPending(win.env.dpy)) { + if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False)) + tns.cnt++; + else + remove_file(tns.cnt, 0); + gettimeofday(&t1, 0); + if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD) + break; + } + if (tns.cnt == filecnt) + win_set_cursor(&win, CURSOR_ARROW); + if (!XPending(win.env.dpy)) { + redraw(); + continue; + } else { + timo_redraw = TO_THUMBS_LOAD; + } + } else if (timo_cursor || timo_redraw) { + /* check active timeouts */ + gettimeofday(&t0, 0); + timeout = MIN(timo_cursor + 1, timo_redraw + 1); + MSEC_TO_TIMEVAL(timeout, &tt); + xfd = ConnectionNumber(win.env.dpy); + FD_ZERO(&fds); + FD_SET(xfd, &fds); + + if (!XPending(win.env.dpy)) + select(xfd + 1, &fds, 0, 0, &tt); + gettimeofday(&t1, 0); + timeout = MIN(TIMEDIFF(&t1, &t0), timeout); + + /* timeouts fired? */ + if (timo_cursor) { + timo_cursor = MAX(0, timo_cursor - timeout); + if (!timo_cursor) + win_set_cursor(&win, CURSOR_NONE); + } + if (timo_redraw) { + timo_redraw = MAX(0, timo_redraw - timeout); + if (!timo_redraw) + redraw(); + } + if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy)) + continue; + } + + if (!XNextEvent(win.env.dpy, &ev)) { + /* handle events */ + switch (ev.type) { + case ButtonPress: + on_buttonpress(&ev.xbutton); + break; + case ClientMessage: + if ((Atom) ev.xclient.data.l[0] == wm_delete_win) + return; + break; + case ConfigureNotify: + if (win_configure(&win, &ev.xconfigure)) { + timo_redraw = TO_WIN_RESIZE; + if (mode == MODE_IMAGE) + img.checkpan = 1; + else + tns.dirty = 1; + } + break; + case KeyPress: + on_keypress(&ev.xkey); + break; + case MotionNotify: + if (!timo_cursor) + win_set_cursor(&win, CURSOR_ARROW); + timo_cursor = TO_CURSOR_HIDE; + break; + } + } + } +} + int fncmp(const void *a, const void *b) { return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name); } diff --git a/types.h b/types.h index c1bb464..f19d693 100644 --- a/types.h +++ b/types.h @@ -31,4 +31,11 @@ typedef struct { const char *path; /* always absolute */ } fileinfo_t; +/* timeouts in milliseconds: */ +enum { + TO_WIN_RESIZE = 75, + TO_CURSOR_HIDE = 1500, + TO_THUMBS_LOAD = 200 +}; + #endif /* TYPES_H */