Krolyxon
Commit 1d74938

Branches

Refs →

nsxiv1d74938

Put event handling back into main.c; events -> commands

Author
Bert
Date
2011-08-19 15:02 +0200
Parent
1d7849e
Commit
1d749382f00bb0bfdb900b6ddb0bb8b3743b99d0

+211 −216

5 files changed

  1. M Makefile +1 −1
  2. R events.c → commands.c +5 −206
  3. R events.h → commands.h +4 −7
  4. M main.c +194 −2
  5. M types.h +7 −0
M Makefile View
@@ -9,7 +9,7 @@ CFLAGS = -Wall -pedantic -O2 -DVERSION=\"$(VERSION)\"
99 LDFLAGS =
1010 LIBS = -lX11 -lImlib2
1111
12−SRC = events.o image.c main.c options.c thumbs.c util.c window.c
12+SRC = commands.c image.c main.c options.c thumbs.c util.c window.c
1313 OBJ = $(SRC:.c=.o)
1414
1515 sxiv: $(OBJ)
R events.c → commands.c View
@@ -1,4 +1,4 @@
1−/* sxiv: events.c
1+/* sxiv: commands.c
22 * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
33 *
44 * This program is free software; you can redistribute it and/or
@@ -16,36 +16,20 @@
1616 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA.
1717 */
1818
19−#define _GENERAL_CONFIG
20−#define _MAPPINGS_CONFIG
21−
2219 #include <stdlib.h>
2320 #include <string.h>
2421 #include <unistd.h>
25−#include <sys/time.h>
2622 #include <sys/wait.h>
27−#include <X11/keysym.h>
28−#include <X11/Xutil.h>
2923
30−#include "events.h"
24+#include "commands.h"
3125 #include "image.h"
3226 #include "thumbs.h"
3327 #include "types.h"
3428 #include "util.h"
35−#include "window.h"
36−#include "config.h"
37−
38−/* timeouts in milliseconds: */
39−enum {
40− TO_WIN_RESIZE = 75,
41− TO_CURSOR_HIDE = 1500,
42− TO_THUMBS_LOAD = 200
43−};
4429
4530 void cleanup();
4631 void remove_file(int, unsigned char);
4732 void load_image(int);
48−void update_title();
4933
5034 extern appmode_t mode;
5135 extern img_t img;
@@ -55,193 +39,8 @@ extern win_t win;
5539 extern fileinfo_t *files;
5640 extern int filecnt, fileidx;
5741
58−int timo_cursor;
59−int timo_redraw;
60−
61−void redraw() {
62− if (mode == MODE_IMAGE) {
63− img_render(&img, &win);
64− if (timo_cursor)
65− win_set_cursor(&win, CURSOR_ARROW);
66− else
67− win_set_cursor(&win, CURSOR_NONE);
68− } else {
69− tns_render(&tns, &win);
70− }
71− update_title();
72− timo_redraw = 0;
73−}
74−
75−Bool keymask(const keymap_t *k, unsigned int state) {
76− return (k->ctrl ? ControlMask : 0) == (state & ControlMask);
77−}
78−
79−Bool buttonmask(const button_t *b, unsigned int state) {
80− return ((b->ctrl ? ControlMask : 0) | (b->shift ? ShiftMask : 0)) ==
81− (state & (ControlMask | ShiftMask));
82−}
83−
84−void on_keypress(XKeyEvent *kev) {
85− int i;
86− KeySym ksym;
87− char key;
88−
89− if (!kev)
90− return;
91−
92− XLookupString(kev, &key, 1, &ksym, NULL);
93−
94− for (i = 0; i < LEN(keys); i++) {
95− if (keys[i].ksym == ksym && keymask(&keys[i], kev->state)) {
96− if (keys[i].cmd && keys[i].cmd(keys[i].arg))
97− redraw();
98− return;
99− }
100− }
101−}
102−
103−void on_buttonpress(XButtonEvent *bev) {
104− int i, sel;
105−
106− if (!bev)
107− return;
108−
109− if (mode == MODE_IMAGE) {
110− win_set_cursor(&win, CURSOR_ARROW);
111− timo_cursor = TO_CURSOR_HIDE;
112−
113− for (i = 0; i < LEN(buttons); i++) {
114− if (buttons[i].button == bev->button &&
115− buttonmask(&buttons[i], bev->state))
116− {
117− if (buttons[i].cmd && buttons[i].cmd(buttons[i].arg))
118− redraw();
119− return;
120− }
121− }
122− } else {
123− /* thumbnail mode (hard-coded) */
124− switch (bev->button) {
125− case Button1:
126− if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) {
127− if (sel == tns.sel) {
128− load_image(tns.sel);
129− mode = MODE_IMAGE;
130− timo_cursor = TO_CURSOR_HIDE;
131− } else {
132− tns_highlight(&tns, &win, tns.sel, False);
133− tns_highlight(&tns, &win, sel, True);
134− tns.sel = sel;
135− }
136− redraw();
137− break;
138− }
139− break;
140− case Button4:
141− case Button5:
142− if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN))
143− redraw();
144− break;
145− }
146− }
147−}
148−
149−void run() {
150− int xfd, timeout;
151− fd_set fds;
152− struct timeval tt, t0, t1;
153− XEvent ev;
154−
155− timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0;
156−
157− redraw();
158−
159− while (1) {
160− if (mode == MODE_THUMB && tns.cnt < filecnt) {
161− /* load thumbnails */
162− win_set_cursor(&win, CURSOR_WATCH);
163− gettimeofday(&t0, 0);
164−
165− while (tns.cnt < filecnt && !XPending(win.env.dpy)) {
166− if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False))
167− tns.cnt++;
168− else
169− remove_file(tns.cnt, 0);
170− gettimeofday(&t1, 0);
171− if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD)
172− break;
173− }
174− if (tns.cnt == filecnt)
175− win_set_cursor(&win, CURSOR_ARROW);
176− if (!XPending(win.env.dpy)) {
177− redraw();
178− continue;
179− } else {
180− timo_redraw = TO_THUMBS_LOAD;
181− }
182− } else if (timo_cursor || timo_redraw) {
183− /* check active timeouts */
184− gettimeofday(&t0, 0);
185− timeout = MIN(timo_cursor + 1, timo_redraw + 1);
186− MSEC_TO_TIMEVAL(timeout, &tt);
187− xfd = ConnectionNumber(win.env.dpy);
188− FD_ZERO(&fds);
189− FD_SET(xfd, &fds);
190−
191− if (!XPending(win.env.dpy))
192− select(xfd + 1, &fds, 0, 0, &tt);
193− gettimeofday(&t1, 0);
194− timeout = MIN(TIMEDIFF(&t1, &t0), timeout);
195−
196− /* timeouts fired? */
197− if (timo_cursor) {
198− timo_cursor = MAX(0, timo_cursor - timeout);
199− if (!timo_cursor)
200− win_set_cursor(&win, CURSOR_NONE);
201− }
202− if (timo_redraw) {
203− timo_redraw = MAX(0, timo_redraw - timeout);
204− if (!timo_redraw)
205− redraw();
206− }
207− if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy))
208− continue;
209− }
210−
211− if (!XNextEvent(win.env.dpy, &ev)) {
212− /* handle events */
213− switch (ev.type) {
214− case ButtonPress:
215− on_buttonpress(&ev.xbutton);
216− break;
217− case ClientMessage:
218− if ((Atom) ev.xclient.data.l[0] == wm_delete_win)
219− return;
220− break;
221− case ConfigureNotify:
222− if (win_configure(&win, &ev.xconfigure)) {
223− timo_redraw = TO_WIN_RESIZE;
224− if (mode == MODE_IMAGE)
225− img.checkpan = 1;
226− else
227− tns.dirty = 1;
228− }
229− break;
230− case KeyPress:
231− on_keypress(&ev.xkey);
232− break;
233− case MotionNotify:
234− if (!timo_cursor)
235− win_set_cursor(&win, CURSOR_ARROW);
236− timo_cursor = TO_CURSOR_HIDE;
237− break;
238− }
239− }
240− }
241−}
242−
243−
244−/* command functions for key and button mappings: */
42+extern int timo_cursor;
43+extern int timo_redraw;
24544
24645 int it_quit(arg_t a) {
24746 cleanup();
@@ -593,7 +392,7 @@ int it_shell_cmd(arg_t a) {
593392 end:
594393 if (mode == MODE_THUMB)
595394 win_set_cursor(&win, CURSOR_ARROW);
596− /* else: cursor is reset in redraw() */
395+ /* else: cursor gets reset in redraw() */
597396
598397 free(cmdline);
599398
R events.h → commands.h View
@@ -1,4 +1,4 @@
1−/* sxiv: events.h
1+/* sxiv: commands.h
22 * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
33 *
44 * This program is free software; you can redistribute it and/or
@@ -16,8 +16,8 @@
1616 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA.
1717 */
1818
19−#ifndef EVENTS_H
20−#define EVENTS_H
19+#ifndef COMMANDS_H
20+#define COMMANDS_H
2121
2222 #include <X11/Xlib.h>
2323
@@ -39,9 +39,6 @@ typedef struct {
3939 arg_t arg;
4040 } button_t;
4141
42−void run();
43−
44−/* command functions for key and button mappings: */
4542 int it_quit(arg_t);
4643 int it_switch_mode(arg_t);
4744 int it_toggle_fullscreen(arg_t);
@@ -63,4 +60,4 @@ int i_toggle_alpha(arg_t);
6360 int it_open_with(arg_t);
6461 int it_shell_cmd(arg_t);
6562
66−#endif /* EVENTS_H */
63+#endif /* COMMANDS_H */
M main.c View
@@ -17,11 +17,15 @@
1717 */
1818
1919 #include <stdlib.h>
20+#include <stdio.h>
2021 #include <string.h>
2122 #include <unistd.h>
2223 #include <sys/stat.h>
24+#include <sys/time.h>
25+#include <X11/Xutil.h>
26+#include <X11/keysym.h>
2327
24−#include "events.h"
28+#include "commands.h"
2529 #include "image.h"
2630 #include "options.h"
2731 #include "thumbs.h"
@@ -29,6 +33,9 @@
2933 #include "util.h"
3034 #include "window.h"
3135
36+#define _MAPPINGS_CONFIG
37+#include "config.h"
38+
3239 enum {
3340 TITLE_LEN = 256,
3441 FNAME_CNT = 1024
@@ -45,6 +52,9 @@ size_t filesize;
4552
4653 char win_title[TITLE_LEN];
4754
55+int timo_cursor;
56+int timo_redraw;
57+
4858 void cleanup() {
4959 static int in = 0;
5060
@@ -115,7 +125,7 @@ void load_image(int new) {
115125 if (new < 0 || new >= filecnt)
116126 return;
117127
118− /* cursor is reset in redraw() */
128+ /* cursor gets reset in redraw() */
119129 win_set_cursor(&win, CURSOR_WATCH);
120130 img_close(&img, 0);
121131
@@ -158,6 +168,188 @@ void update_title() {
158168 win_set_title(&win, win_title);
159169 }
160170
171+void redraw() {
172+ if (mode == MODE_IMAGE) {
173+ img_render(&img, &win);
174+ if (timo_cursor)
175+ win_set_cursor(&win, CURSOR_ARROW);
176+ else
177+ win_set_cursor(&win, CURSOR_NONE);
178+ } else {
179+ tns_render(&tns, &win);
180+ }
181+ update_title();
182+ timo_redraw = 0;
183+}
184+
185+Bool keymask(const keymap_t *k, unsigned int state) {
186+ return (k->ctrl ? ControlMask : 0) == (state & ControlMask);
187+}
188+
189+Bool buttonmask(const button_t *b, unsigned int state) {
190+ return ((b->ctrl ? ControlMask : 0) | (b->shift ? ShiftMask : 0)) ==
191+ (state & (ControlMask | ShiftMask));
192+}
193+
194+void on_keypress(XKeyEvent *kev) {
195+ int i;
196+ KeySym ksym;
197+ char key;
198+
199+ if (!kev)
200+ return;
201+
202+ XLookupString(kev, &key, 1, &ksym, NULL);
203+
204+ for (i = 0; i < LEN(keys); i++) {
205+ if (keys[i].ksym == ksym && keymask(&keys[i], kev->state)) {
206+ if (keys[i].cmd && keys[i].cmd(keys[i].arg))
207+ redraw();
208+ return;
209+ }
210+ }
211+}
212+
213+void on_buttonpress(XButtonEvent *bev) {
214+ int i, sel;
215+
216+ if (!bev)
217+ return;
218+
219+ if (mode == MODE_IMAGE) {
220+ win_set_cursor(&win, CURSOR_ARROW);
221+ timo_cursor = TO_CURSOR_HIDE;
222+
223+ for (i = 0; i < LEN(buttons); i++) {
224+ if (buttons[i].button == bev->button &&
225+ buttonmask(&buttons[i], bev->state))
226+ {
227+ if (buttons[i].cmd && buttons[i].cmd(buttons[i].arg))
228+ redraw();
229+ return;
230+ }
231+ }
232+ } else {
233+ /* thumbnail mode (hard-coded) */
234+ switch (bev->button) {
235+ case Button1:
236+ if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) {
237+ if (sel == tns.sel) {
238+ load_image(tns.sel);
239+ mode = MODE_IMAGE;
240+ timo_cursor = TO_CURSOR_HIDE;
241+ } else {
242+ tns_highlight(&tns, &win, tns.sel, False);
243+ tns_highlight(&tns, &win, sel, True);
244+ tns.sel = sel;
245+ }
246+ redraw();
247+ break;
248+ }
249+ break;
250+ case Button4:
251+ case Button5:
252+ if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN))
253+ redraw();
254+ break;
255+ }
256+ }
257+}
258+
259+void run() {
260+ int xfd, timeout;
261+ fd_set fds;
262+ struct timeval tt, t0, t1;
263+ XEvent ev;
264+
265+ timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0;
266+
267+ redraw();
268+
269+ while (1) {
270+ if (mode == MODE_THUMB && tns.cnt < filecnt) {
271+ /* load thumbnails */
272+ win_set_cursor(&win, CURSOR_WATCH);
273+ gettimeofday(&t0, 0);
274+
275+ while (tns.cnt < filecnt && !XPending(win.env.dpy)) {
276+ if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False))
277+ tns.cnt++;
278+ else
279+ remove_file(tns.cnt, 0);
280+ gettimeofday(&t1, 0);
281+ if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD)
282+ break;
283+ }
284+ if (tns.cnt == filecnt)
285+ win_set_cursor(&win, CURSOR_ARROW);
286+ if (!XPending(win.env.dpy)) {
287+ redraw();
288+ continue;
289+ } else {
290+ timo_redraw = TO_THUMBS_LOAD;
291+ }
292+ } else if (timo_cursor || timo_redraw) {
293+ /* check active timeouts */
294+ gettimeofday(&t0, 0);
295+ timeout = MIN(timo_cursor + 1, timo_redraw + 1);
296+ MSEC_TO_TIMEVAL(timeout, &tt);
297+ xfd = ConnectionNumber(win.env.dpy);
298+ FD_ZERO(&fds);
299+ FD_SET(xfd, &fds);
300+
301+ if (!XPending(win.env.dpy))
302+ select(xfd + 1, &fds, 0, 0, &tt);
303+ gettimeofday(&t1, 0);
304+ timeout = MIN(TIMEDIFF(&t1, &t0), timeout);
305+
306+ /* timeouts fired? */
307+ if (timo_cursor) {
308+ timo_cursor = MAX(0, timo_cursor - timeout);
309+ if (!timo_cursor)
310+ win_set_cursor(&win, CURSOR_NONE);
311+ }
312+ if (timo_redraw) {
313+ timo_redraw = MAX(0, timo_redraw - timeout);
314+ if (!timo_redraw)
315+ redraw();
316+ }
317+ if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy))
318+ continue;
319+ }
320+
321+ if (!XNextEvent(win.env.dpy, &ev)) {
322+ /* handle events */
323+ switch (ev.type) {
324+ case ButtonPress:
325+ on_buttonpress(&ev.xbutton);
326+ break;
327+ case ClientMessage:
328+ if ((Atom) ev.xclient.data.l[0] == wm_delete_win)
329+ return;
330+ break;
331+ case ConfigureNotify:
332+ if (win_configure(&win, &ev.xconfigure)) {
333+ timo_redraw = TO_WIN_RESIZE;
334+ if (mode == MODE_IMAGE)
335+ img.checkpan = 1;
336+ else
337+ tns.dirty = 1;
338+ }
339+ break;
340+ case KeyPress:
341+ on_keypress(&ev.xkey);
342+ break;
343+ case MotionNotify:
344+ if (!timo_cursor)
345+ win_set_cursor(&win, CURSOR_ARROW);
346+ timo_cursor = TO_CURSOR_HIDE;
347+ break;
348+ }
349+ }
350+ }
351+}
352+
161353 int fncmp(const void *a, const void *b) {
162354 return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name);
163355 }
M types.h View
@@ -31,4 +31,11 @@ typedef struct {
3131 const char *path; /* always absolute */
3232 } fileinfo_t;
3333
34+/* timeouts in milliseconds: */
35+enum {
36+ TO_WIN_RESIZE = 75,
37+ TO_CURSOR_HIDE = 1500,
38+ TO_THUMBS_LOAD = 200
39+};
40+
3441 #endif /* TYPES_H */