Put event handling back into main.c; events -> commands
This commit is contained in:
		
							parent
							
								
									1d7849efc1
								
							
						
					
					
						commit
						1d749382f0
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								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) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| /* sxiv: events.c
 | ||||
| /* sxiv: commands.c
 | ||||
|  * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de> | ||||
|  * | ||||
|  * 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 <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/wait.h> | ||||
| #include <X11/keysym.h> | ||||
| #include <X11/Xutil.h> | ||||
| 
 | ||||
| #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); | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| /* sxiv: events.h
 | ||||
| /* sxiv: commands.h
 | ||||
|  * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de> | ||||
|  * | ||||
|  * 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 <X11/Xlib.h> | ||||
| 
 | ||||
| @ -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 */ | ||||
							
								
								
									
										196
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								main.c
									
									
									
									
									
								
							| @ -17,11 +17,15 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/time.h> | ||||
| #include <X11/Xutil.h> | ||||
| #include <X11/keysym.h> | ||||
| 
 | ||||
| #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); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert
						Bert