Manual event handling in main.c
This commit is contained in:
		
							parent
							
								
									e8cf8da208
								
							
						
					
					
						commit
						12a94cc40e
					
				
							
								
								
									
										299
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										299
									
								
								main.c
									
									
									
									
									
								
							| @ -32,17 +32,10 @@ | |||||||
| #include "util.h" | #include "util.h" | ||||||
| #include "window.h" | #include "window.h" | ||||||
| 
 | 
 | ||||||
| void on_keypress(XEvent*); |  | ||||||
| void on_buttonpress(XEvent*); |  | ||||||
| void on_buttonrelease(XEvent*); |  | ||||||
| void on_motionnotify(XEvent*); |  | ||||||
| void on_configurenotify(XEvent*); |  | ||||||
| 
 |  | ||||||
| void update_title(); | void update_title(); | ||||||
| void check_append(const char*); | void check_append(const char*); | ||||||
| void read_dir_rec(const char*); | void read_dir_rec(const char*); | ||||||
| 
 | void run(); | ||||||
| static void (*handler[LASTEvent])(XEvent*); |  | ||||||
| 
 | 
 | ||||||
| img_t img; | img_t img; | ||||||
| win_t win; | win_t win; | ||||||
| @ -52,11 +45,6 @@ win_t win; | |||||||
| const char **filenames; | const char **filenames; | ||||||
| int filecnt, fileidx; | int filecnt, fileidx; | ||||||
| 
 | 
 | ||||||
| unsigned char timeout; |  | ||||||
| 
 |  | ||||||
| int mox; |  | ||||||
| int moy; |  | ||||||
| 
 |  | ||||||
| #define TITLE_LEN 256 | #define TITLE_LEN 256 | ||||||
| char win_title[TITLE_LEN]; | char win_title[TITLE_LEN]; | ||||||
| 
 | 
 | ||||||
| @ -69,39 +57,6 @@ void cleanup() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void run() { |  | ||||||
| 	int xfd; |  | ||||||
| 	fd_set fds; |  | ||||||
| 	struct timeval t; |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	handler[KeyPress] = on_keypress; |  | ||||||
| 	handler[ButtonPress] = on_buttonpress; |  | ||||||
| 	handler[ButtonRelease] = on_buttonrelease; |  | ||||||
| 	handler[MotionNotify] = on_motionnotify; |  | ||||||
| 	handler[ConfigureNotify] = on_configurenotify; |  | ||||||
| 
 |  | ||||||
| 	timeout = 0; |  | ||||||
| 
 |  | ||||||
| 	while (1) { |  | ||||||
| 		if (timeout) { |  | ||||||
| 			t.tv_sec = 0; |  | ||||||
| 			t.tv_usec = 250; |  | ||||||
| 			xfd = ConnectionNumber(win.env.dpy); |  | ||||||
| 			FD_ZERO(&fds); |  | ||||||
| 			FD_SET(xfd, &fds); |  | ||||||
| 			 |  | ||||||
| 			if (!XPending(win.env.dpy) && !select(xfd + 1, &fds, 0, 0, &t)) { |  | ||||||
| 				img_render(&img, &win); |  | ||||||
| 				timeout = 0; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (!XNextEvent(win.env.dpy, &ev) && handler[ev.type]) |  | ||||||
| 			handler[ev.type](&ev); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
| 	int i; | 	int i; | ||||||
| 	const char *filename; | 	const char *filename; | ||||||
| @ -158,15 +113,102 @@ int main(int argc, char **argv) { | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void on_keypress(XEvent *ev) { | void update_title() { | ||||||
|  | 	int n; | ||||||
|  | 
 | ||||||
|  | 	n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> %s", fileidx + 1, | ||||||
|  | 	             filecnt, (int) (img.zoom * 100.0), filenames[fileidx]); | ||||||
|  | 	 | ||||||
|  | 	if (n >= TITLE_LEN) { | ||||||
|  | 		win_title[TITLE_LEN - 2] = '.'; | ||||||
|  | 		win_title[TITLE_LEN - 3] = '.'; | ||||||
|  | 		win_title[TITLE_LEN - 4] = '.'; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	win_set_title(&win, win_title); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void check_append(const char *filename) { | ||||||
|  | 	if (!filename) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if (img_check(filename)) { | ||||||
|  | 		if (fileidx == filecnt) { | ||||||
|  | 			filecnt *= 2; | ||||||
|  | 			filenames = (const char**) s_realloc(filenames, | ||||||
|  | 																					 filecnt * sizeof(const char*)); | ||||||
|  | 		} | ||||||
|  | 		filenames[fileidx++] = filename; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void read_dir_rec(const char *dirname) { | ||||||
|  | 	char *filename; | ||||||
|  | 	const char **dirnames; | ||||||
|  | 	int dircnt, diridx; | ||||||
|  | 	unsigned char first; | ||||||
|  | 	size_t len; | ||||||
|  | 	DIR *dir; | ||||||
|  | 	struct dirent *dentry; | ||||||
|  | 	struct stat fstats; | ||||||
|  | 
 | ||||||
|  | 	if (!dirname) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	dircnt = DNAME_CNT; | ||||||
|  | 	diridx = first = 1; | ||||||
|  | 	dirnames = (const char**) s_malloc(dircnt * sizeof(const char*)); | ||||||
|  | 	dirnames[0] = dirname; | ||||||
|  | 
 | ||||||
|  | 	while (diridx > 0) { | ||||||
|  | 		dirname = dirnames[--diridx]; | ||||||
|  | 		if (!(dir = opendir(dirname))) | ||||||
|  | 			die("could not open directory: %s", dirname); | ||||||
|  | 		while ((dentry = readdir(dir))) { | ||||||
|  | 			if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) | ||||||
|  | 				continue; | ||||||
|  | 			len = strlen(dirname) + strlen(dentry->d_name) + 2; | ||||||
|  | 			filename = (char*) s_malloc(len * sizeof(char)); | ||||||
|  | 			snprintf(filename, len, "%s/%s", dirname, dentry->d_name); | ||||||
|  | 			if (stat(filename, &fstats)) { | ||||||
|  | 				warn("could not stat file: %s", filename); | ||||||
|  | 				free(filename); | ||||||
|  | 			} else if (S_ISDIR(fstats.st_mode)) { | ||||||
|  | 				if (diridx == dircnt) { | ||||||
|  | 					dircnt *= 2; | ||||||
|  | 					dirnames = (const char**) s_realloc(dirnames, | ||||||
|  | 					                                    dircnt * sizeof(const char*)); | ||||||
|  | 				} | ||||||
|  | 				dirnames[diridx++] = filename; | ||||||
|  | 			} else { | ||||||
|  | 				check_append(filename); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		closedir(dir); | ||||||
|  | 		if (!first) | ||||||
|  | 			free((void*) dirname); | ||||||
|  | 		else | ||||||
|  | 			first = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	free(dirnames); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* event handling */ | ||||||
|  | 
 | ||||||
|  | unsigned char timeout; | ||||||
|  | int mox, moy; | ||||||
|  | 
 | ||||||
|  | void on_keypress(XKeyEvent *kev) { | ||||||
| 	char key; | 	char key; | ||||||
| 	KeySym ksym; | 	KeySym ksym; | ||||||
| 	int changed; | 	int changed; | ||||||
| 
 | 
 | ||||||
| 	if (!ev) | 	if (!kev) | ||||||
| 		return; | 		return; | ||||||
| 	 | 	 | ||||||
| 	XLookupString(&ev->xkey, &key, 1, &ksym, NULL); | 	XLookupString(kev, &key, 1, &ksym, NULL); | ||||||
| 	changed = 0; | 	changed = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (ksym) { | 	switch (ksym) { | ||||||
| @ -271,17 +313,17 @@ void on_keypress(XEvent *ev) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void on_buttonpress(XEvent *ev) { | void on_buttonpress(XButtonEvent *bev) { | ||||||
| 	int changed; | 	int changed; | ||||||
| 	unsigned int mask; | 	unsigned int mask; | ||||||
| 
 | 
 | ||||||
| 	if (!ev) | 	if (!bev) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	mask = CLEANMASK(ev->xbutton.state); | 	mask = CLEANMASK(bev->state); | ||||||
| 	changed = 0; | 	changed = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (ev->xbutton.button) { | 	switch (bev->button) { | ||||||
| 		case Button1: | 		case Button1: | ||||||
| 			if (fileidx + 1 < filecnt) { | 			if (fileidx + 1 < filecnt) { | ||||||
| 				img_load(&img, filenames[++fileidx]); | 				img_load(&img, filenames[++fileidx]); | ||||||
| @ -289,8 +331,8 @@ void on_buttonpress(XEvent *ev) { | |||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case Button2: | 		case Button2: | ||||||
| 			mox = ev->xbutton.x; | 			mox = bev->x; | ||||||
| 			moy = ev->xbutton.y; | 			moy = bev->y; | ||||||
| 			win_set_cursor(&win, CURSOR_HAND); | 			win_set_cursor(&win, CURSOR_HAND); | ||||||
| 			break; | 			break; | ||||||
| 		case Button3: | 		case Button3: | ||||||
| @ -330,118 +372,63 @@ void on_buttonpress(XEvent *ev) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void on_buttonrelease(XEvent *ev) { | void on_motionnotify(XMotionEvent *mev) { | ||||||
| 	if (!ev) | 	if (!mev) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (ev->xbutton.button == Button2) | 	if (mev->x >= 0 && mev->x <= win.w && mev->y >= 0 && mev->y <= win.h) { | ||||||
| 		win_set_cursor(&win, CURSOR_ARROW); | 		if (img_move(&img, &win, mev->x - mox, mev->y - moy)) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void on_motionnotify(XEvent *ev) { |  | ||||||
| 	XMotionEvent *m; |  | ||||||
| 
 |  | ||||||
| 	if (!ev) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	m = &ev->xmotion; |  | ||||||
| 	 |  | ||||||
| 	if (m->x >= 0 && m->x <= win.w && m->y >= 0 && m->y <= win.h) { |  | ||||||
| 		if (img_move(&img, &win, m->x - mox, m->y - moy)) |  | ||||||
| 			timeout = 1; | 			timeout = 1; | ||||||
| 
 | 
 | ||||||
| 		mox = m->x; | 		mox = mev->x; | ||||||
| 		moy = m->y; | 		moy = mev->y; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void on_configurenotify(XEvent *ev) { | void run() { | ||||||
| 	if (!ev) | 	int xfd; | ||||||
| 		return; | 	fd_set fds; | ||||||
|  | 	struct timeval t; | ||||||
|  | 	XEvent ev; | ||||||
| 
 | 
 | ||||||
| 	if (win_configure(&win, &ev->xconfigure)) { | 	timeout = 0; | ||||||
| 		img.checkpan = 1; |  | ||||||
| 		timeout = 1; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void update_title() { | 	while (1) { | ||||||
| 	int n; | 		if (timeout) { | ||||||
|  | 			t.tv_sec = 0; | ||||||
|  | 			t.tv_usec = 250; | ||||||
|  | 			xfd = ConnectionNumber(win.env.dpy); | ||||||
|  | 			FD_ZERO(&fds); | ||||||
|  | 			FD_SET(xfd, &fds); | ||||||
| 			 | 			 | ||||||
| 	n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> %s", fileidx + 1, | 			if (!XPending(win.env.dpy) && !select(xfd + 1, &fds, 0, 0, &t)) { | ||||||
| 	             filecnt, (int) (img.zoom * 100.0), filenames[fileidx]); | 				img_render(&img, &win); | ||||||
| 	 | 				timeout = 0; | ||||||
| 	if (n >= TITLE_LEN) { |  | ||||||
| 		win_title[TITLE_LEN - 2] = '.'; |  | ||||||
| 		win_title[TITLE_LEN - 3] = '.'; |  | ||||||
| 		win_title[TITLE_LEN - 4] = '.'; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	win_set_title(&win, win_title); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void check_append(const char *filename) { |  | ||||||
| 	if (!filename) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	if (img_check(filename)) { |  | ||||||
| 		if (fileidx == filecnt) { |  | ||||||
| 			filecnt *= 2; |  | ||||||
| 			filenames = (const char**) s_realloc(filenames, |  | ||||||
| 																					 filecnt * sizeof(const char*)); |  | ||||||
| 		} |  | ||||||
| 		filenames[fileidx++] = filename; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void read_dir_rec(const char *dirname) { |  | ||||||
| 	char *filename; |  | ||||||
| 	const char **dirnames; |  | ||||||
| 	int dircnt, diridx; |  | ||||||
| 	unsigned char first; |  | ||||||
| 	size_t len; |  | ||||||
| 	DIR *dir; |  | ||||||
| 	struct dirent *dentry; |  | ||||||
| 	struct stat fstats; |  | ||||||
| 
 |  | ||||||
| 	if (!dirname) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	dircnt = DNAME_CNT; |  | ||||||
| 	diridx = first = 1; |  | ||||||
| 	dirnames = (const char**) s_malloc(dircnt * sizeof(const char*)); |  | ||||||
| 	dirnames[0] = dirname; |  | ||||||
| 
 |  | ||||||
| 	while (diridx > 0) { |  | ||||||
| 		dirname = dirnames[--diridx]; |  | ||||||
| 		if (!(dir = opendir(dirname))) |  | ||||||
| 			die("could not open directory: %s", dirname); |  | ||||||
| 		while ((dentry = readdir(dir))) { |  | ||||||
| 			if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) |  | ||||||
| 				continue; |  | ||||||
| 			len = strlen(dirname) + strlen(dentry->d_name) + 2; |  | ||||||
| 			filename = (char*) s_malloc(len * sizeof(char)); |  | ||||||
| 			snprintf(filename, len, "%s/%s", dirname, dentry->d_name); |  | ||||||
| 			if (stat(filename, &fstats)) { |  | ||||||
| 				warn("could not stat file: %s", filename); |  | ||||||
| 				free(filename); |  | ||||||
| 			} else if (S_ISDIR(fstats.st_mode)) { |  | ||||||
| 				if (diridx == dircnt) { |  | ||||||
| 					dircnt *= 2; |  | ||||||
| 					dirnames = (const char**) s_realloc(dirnames, |  | ||||||
| 					                                    dircnt * sizeof(const char*)); |  | ||||||
| 				} |  | ||||||
| 				dirnames[diridx++] = filename; |  | ||||||
| 			} else { |  | ||||||
| 				check_append(filename); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		closedir(dir); |  | ||||||
| 		if (!first) |  | ||||||
| 			free((void*) dirname); |  | ||||||
| 		else |  | ||||||
| 			first = 0; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	free(dirnames); | 		if (!XNextEvent(win.env.dpy, &ev)) { | ||||||
|  | 			switch (ev.type) { | ||||||
|  | 				case KeyPress: | ||||||
|  | 					on_keypress(&ev.xkey); | ||||||
|  | 					break; | ||||||
|  | 				case ButtonPress: | ||||||
|  | 					on_buttonpress(&ev.xbutton); | ||||||
|  | 					break; | ||||||
|  | 				case ButtonRelease: | ||||||
|  | 					if (ev.xbutton.button == Button2) | ||||||
|  | 						win_set_cursor(&win, CURSOR_ARROW); | ||||||
|  | 					break; | ||||||
|  | 				case MotionNotify: | ||||||
|  | 					on_motionnotify(&ev.xmotion); | ||||||
|  | 					break; | ||||||
|  | 				case ConfigureNotify: | ||||||
|  | 					if (win_configure(&win, &ev.xconfigure)) { | ||||||
|  | 						img.checkpan = 1; | ||||||
|  | 						timeout = 1; | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert
						Bert