예제 #1
0
static int windows_filter_pump(const SDL_Event *event) {
	//handle multimedia button events
	if (event->type == SDL_SYSWMEVENT)
	{
		SDL_SysWMmsg *wmmsg;
		wmmsg = event->syswm.msg;
		
		if (wmmsg->msg == WM_APPCOMMAND) {
			switch (GET_APPCOMMAND_LPARAM(wmmsg->lParam)) {
				case APPCOMMAND_MEDIA_NEXTTRACK:
					jive_send_key_event(JIVE_EVENT_KEY_PRESS, JIVE_KEY_FWD, jive_jiffies());
					return 0; // return non-zero, because we have handled the message (see MSDN doc)
				case APPCOMMAND_MEDIA_PREVIOUSTRACK:
					jive_send_key_event(JIVE_EVENT_KEY_PRESS, JIVE_KEY_REW, jive_jiffies());
					return 0;
				case APPCOMMAND_MEDIA_PLAY_PAUSE:
					jive_send_key_event(JIVE_EVENT_KEY_PRESS, JIVE_KEY_PAUSE, jive_jiffies());
					return 0;
				case APPCOMMAND_VOLUME_DOWN:
					jive_send_key_event(JIVE_EVENT_KEY_DOWN, JIVE_KEY_VOLUME_DOWN, jive_jiffies());
					jive_send_key_event(JIVE_EVENT_KEY_UP, JIVE_KEY_VOLUME_DOWN, jive_jiffies());
					return 0;
				case APPCOMMAND_VOLUME_UP:
					jive_send_key_event(JIVE_EVENT_KEY_DOWN, JIVE_KEY_VOLUME_UP, jive_jiffies());
					jive_send_key_event(JIVE_EVENT_KEY_UP, JIVE_KEY_VOLUME_UP, jive_jiffies());
					return 0;
				//todo: APPCOMMAND_MEDIA_STOP or JIVE_KEY_VOLUME_UP - do anything for these?
				default : break;
			}
		}
    }
	return 1;
}
예제 #2
0
void jive_send_char_press_event(Uint16 unicode) {
	JiveEvent event;
	memset(&event, 0, sizeof(JiveEvent));

	event.type = JIVE_EVENT_CHAR_PRESS;
	event.ticks = jive_jiffies();
	event.u.text.unicode = unicode;
	jive_queue_event(&event);
}
예제 #3
0
void jive_send_gesture_event(JiveGesture code) {
	JiveEvent event;
	memset(&event, 0, sizeof(JiveEvent));

	event.type = JIVE_EVENT_GESTURE;
	event.ticks = jive_jiffies();
	event.u.gesture.code = code;
	jive_queue_event(&event);
}
예제 #4
0
static void process_timers(lua_State *L) {
	JiveEvent jevent;
	Uint32 now;

	memset(&jevent, 0, sizeof(JiveEvent));
	jevent.ticks = now = jive_jiffies();

	if (pointer_timeout && pointer_timeout < now) {
		SDL_ShowCursor(SDL_DISABLE);
		pointer_timeout = 0;
	}

	if (mouse_timeout && mouse_timeout < now) {
		if (mouse_state == MOUSE_STATE_DOWN) {
			jevent.type = JIVE_EVENT_MOUSE_HOLD;
			jevent.u.mouse.x = (mouse_timeout_arg >> 0) & 0xFFFF;
			jevent.u.mouse.y = (mouse_timeout_arg >> 16) & 0xFFFF;
			mouse_state = MOUSE_STATE_SENT;

			do_dispatch_event(L, &jevent);
		}
		mouse_timeout = 0;
	}
예제 #5
0
/* dns resolver thread */
static int dns_resolver_thread(void *p) {
	socket_t fd = (long) p;
	struct hostent *hostent;
	struct in_addr **addr, byaddr;
	char **alias;
	size_t len;
	char *buf;
	char *failed_error = NULL;
	Uint32 failed_timeout = 0;

	while (1) {
		if (recv(fd, &len, sizeof(len), 0) < 0) {
			/* broken pipe */
			return 0;
		}

		buf = malloc(len + 1);
		if (recv(fd, buf, len, 0) < 0) {
			/* broken pipe */
			free(buf);
			return 0;
		}
		buf[len] = '\0';
		if (failed_error && stat_resolv_conf()) {
			#ifndef _WIN32
			//reload resolv.conf
			res_init();
			#endif
		}
		else if (failed_error && !stat_resolv_conf()) {
			Uint32 now = jive_jiffies();
			
			if (now - failed_timeout < RESOLV_TIMEOUT) {
				write_str(fd, failed_error);
				free(buf);
				continue;
			}
		}
		failed_error = NULL;

		if (inet_aton(buf, &byaddr)) {
			hostent = gethostbyaddr((char *) &byaddr, sizeof(addr), AF_INET);
		}
		else {
			hostent = gethostbyname(buf);
		}
		free(buf);

		if (hostent == NULL) {
			/* error */
			switch (h_errno) {
			case HOST_NOT_FOUND:
				write_str(fd, "Not found");
				break;
			case NO_DATA:
				write_str(fd, "No data");
				break;
			case NO_RECOVERY:
				failed_error = "No recovery";
				failed_timeout = jive_jiffies();
				write_str(fd, failed_error);
				break;
			case TRY_AGAIN:
				failed_error = "Try again"; 
				failed_timeout = jive_jiffies();
				write_str(fd, failed_error);
				break;
			}
		}
		else {
			write_str(fd, ""); // no error
			write_str(fd, hostent->h_name);

			alias = hostent->h_aliases;
			while (*alias) {
				write_str(fd, *alias);
				alias++;
			}
			write_str(fd, ""); // end of aliases

			addr = (struct in_addr **) hostent->h_addr_list;
			while (*addr) {
				write_str(fd, inet_ntoa(**addr));
				addr++;
			}
			write_str(fd, ""); // end if addrs
		}
	}
}
예제 #6
0
int jiveL_dispatch_event(lua_State *L) {
	Uint32 r = 0;
	Uint32 t0 = 0, t1 = 0;
	clock_t c0 = 0, c1 = 0;

	/* stack is:
	 * 1: framework
	 * 2: widget
	 * 3: event
	 */

	if (perfwarn.event) {
		t0 = jive_jiffies();
		c0 = clock();
	}

	lua_pushcfunction(L, jive_traceback);  /* push traceback function */

	// call global event listeners
	if (jive_getmethod(L, 1, "_event")) {
		lua_pushvalue(L, 1); // framework
		lua_pushvalue(L, 3); // event
		lua_pushboolean(L, 1); // global listeners

		if (lua_pcall(L, 3, 1, 4) != 0) {
			LOG_WARN(log_ui_draw, "error in event function:\n\t%s\n", lua_tostring(L, -1));
			return 0;
		}

		r |= lua_tointeger(L, -1);
		lua_pop(L, 1);
	}

	/* by default send the event to the top window. fetch that top
	 * window here in case the global event handler has modified
	 * the window stack.
	 */
	if (lua_isnil(L, 2)) {
		lua_getfield(L, 1, "windowStack");
		if (lua_objlen(L, -1) == 0) {
			lua_pop(L, 1);
			return 0;
		}
		lua_rawgeti(L, -1, 1);
		lua_replace(L, 2);
	}

	// call widget event handler, unless the event is consumed
	if (!(r & JIVE_EVENT_CONSUME) && jive_getmethod(L, 2, "_event")) {
		lua_pushvalue(L, 2); // widget
		lua_pushvalue(L, 3); // event

		if (lua_pcall(L, 2, 1, 4) != 0) {
			LOG_WARN(log_ui_draw, "error in event function:\n\t%s\n", lua_tostring(L, -1));
			return 0;
		}

		r |= lua_tointeger(L, -1);
		lua_pop(L, 1);
	}

	// call unused event listeners, unless the event is consumed
	if (!(r & JIVE_EVENT_CONSUME) && jive_getmethod(L, 1, "_event")) {
		lua_pushvalue(L, 1); // framework
		lua_pushvalue(L, 3); // event
		lua_pushboolean(L, 0); // unused listeners

		if (lua_pcall(L, 3, 1, 4) != 0) {
			LOG_WARN(log_ui_draw, "error in event function:\n\t%s\n", lua_tostring(L, -1));
			return 0;
		}

		r |= lua_tointeger(L, -1);
		lua_pop(L, 1);
	}

	if (perfwarn.event) {
		t1 = jive_jiffies();
		c1 = clock();
		if (t1-t0 > perfwarn.event) {
			printf("process_event > %dms: %4dms (%dms) ", perfwarn.event, t1-t0, (int)((c1-c0) * 1000 / CLOCKS_PER_SEC));
			lua_getglobal(L, "tostring");
			lua_pushvalue(L, 2);
			lua_call(L, 1, 1);
			lua_pushcfunction(L, jiveL_event_tostring);
			lua_pushvalue(L, 3);
			lua_call(L, 1, 1);
			printf("[widget:%s event:%s]\n", lua_tostring(L, -2), lua_tostring(L, -1));
			lua_pop(L, 2);
		}
	}

	lua_pushinteger(L, r);
	return 1;
}
예제 #7
0
static int _draw_screen(lua_State *L) {
	JiveSurface *srf;
	Uint32 t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
	clock_t c0 = 0, c1 = 0;
	bool_t standalone_draw, drawn = false;


	JIVEL_STACK_CHECK_BEGIN(L);

	/* stack is:
	 * 1: framework
	 * 2: surface (in screen format)
	 * 3: standalone_draw (used to draw screen to a new surface)
	 */

	srf = tolua_tousertype(L, 2, 0);
	standalone_draw = lua_toboolean(L, 3);

	/* Exit if we have no windows, nothing to draw */
	lua_getfield(L, 1, "windowStack");
	if (lua_objlen(L, -1) == 0) {
		lua_pop(L, 1);

		JIVEL_STACK_CHECK_ASSERT(L);
		return 0;
	}
	lua_rawgeti(L, -1, 1);	// topwindow

	if (perfwarn.screen) {
		t0 = jive_jiffies();
		c0 = clock();
	}


	do {
		jive_origin = next_jive_origin;

		/* Layout window and widgets */
		if (jive_getmethod(L, -1, "checkLayout")) {
			lua_pushvalue(L, -2);
			lua_call(L, 1, 0);
		}

		/* check in case the origin changes during layout */
	} while (jive_origin != next_jive_origin);

	if (perfwarn.screen) t1 = jive_jiffies();
 
	/* Widget animations - don't update in a standalone draw as its not the main screen update */
	if (!standalone_draw) {
		lua_getfield(L, 1, "animations");
		lua_pushnil(L);
		while (lua_next(L, -2) != 0) {
			lua_getfield(L, -1, "animations");
			lua_pushnil(L);
			while (lua_next(L, -2) != 0) {
				int frame;
				
				/* stack is:
				 * -2: key
				 * -1: table
				 */
				lua_rawgeti(L, -1, 2);
				frame = lua_tointeger(L, -1) - 1;
				
				if (frame == 0) {
					lua_rawgeti(L, -2, 1); // function
					lua_pushvalue(L, -6); // widget
					lua_call(L, 1, 0);
					// function is poped by lua_call
					
					lua_rawgeti(L, -2, 3);
					lua_rawseti(L, -3, 2);
				}
				else {
				  lua_pushinteger(L, frame);
				  lua_rawseti(L, -3, 2);
				}
				lua_pop(L, 2);
			}
			lua_pop(L, 2);
		}
		lua_pop(L, 1);
	}

	if (perfwarn.screen) t2 = jive_jiffies();

	/* Window transitions */
	lua_getfield(L, 1, "transition");
	if (!lua_isnil(L, -1)) {
		/* Draw background */
		jive_surface_set_clip(srf, NULL);
		jive_tile_set_alpha(jive_background, 0); // no alpha channel
		jive_tile_blit(jive_background, srf, 0, 0, screen_w, screen_h);

		if (perfwarn.screen) t3 = jive_jiffies();
		
		/* Animate screen transition */
		lua_pushvalue(L, -1);
		lua_pushvalue(L, -3);  	// widget
		lua_pushvalue(L, 2);	// surface
		lua_call(L, 2, 0);

		drawn = true;
	}
	else if (jive_dirty_region.w || standalone_draw) {
		SDL_Rect dirty;

		/* only redraw dirty region for non standalone draws */
		if (!standalone_draw) {
			jive_rect_union(&jive_dirty_region, &last_dirty_region, &dirty);
			jive_surface_set_clip(srf, &dirty);
		}

#if 0
		printf("REDRAW: %d,%d %dx%d\n", jive_dirty_region.x, jive_dirty_region.y, jive_dirty_region.w, jive_dirty_region.h);
		printf("--> %d,%d %dx%d\n", dirty.x, dirty.y, dirty.w, dirty.h);
#endif

		/* Draw background */
		jive_tile_blit(jive_background, srf, 0, 0, screen_w, screen_h);

		if (perfwarn.screen) t3 = jive_jiffies();

		/* Draw screen */
		if (jive_getmethod(L, -2, "draw")) {
			lua_pushvalue(L, -3);	// widget
			lua_pushvalue(L, 2);	// surface
			lua_pushinteger(L, JIVE_LAYER_ALL); // layer
			lua_call(L, 3, 0);
		}

#if 0
		// show the dirty region for debug purposes:
		jive_surface_rectangleColor(srf, jive_dirty_region.x, jive_dirty_region.y,
			jive_dirty_region.x + jive_dirty_region.w, jive_dirty_region.y + jive_dirty_region.h, 0xFFFFFFFF);
#endif	

		/* clear the dirty region for non standalone draws */
		if (!standalone_draw) {
			memcpy(&last_dirty_region, &jive_dirty_region, sizeof(last_dirty_region));
			jive_dirty_region.w = 0;
		}

		drawn = true;
	}

	if (perfwarn.screen) {
		t4 = jive_jiffies();
		c1 = clock();
		if (t4-t0 > perfwarn.screen) {
			if (!t3) {
				t3 = t2;
			}
			printf("update_screen > %dms: %4dms (%dms) [layout:%dms animate:%dms background:%dms draw:%dms]\n",
				   perfwarn.screen, t4-t0, (int)((c1-c0) * 1000 / CLOCKS_PER_SEC), t1-t0, t2-t1, t3-t2, t4-t3);
		}
	}
	
	lua_pop(L, 3);

	JIVEL_STACK_CHECK_END(L);

	lua_pushboolean(L, drawn);
	return 1;
}
예제 #8
0
static int process_event(lua_State *L, SDL_Event *event) {
	JiveEvent jevent;
	Uint32 now;

	memset(&jevent, 0, sizeof(JiveEvent));
	jevent.ticks = now = jive_jiffies();

	switch (event->type) {
	case SDL_QUIT:
		jiveL_quit(L);
		exit(0);
		break;

	case SDL_MOUSEBUTTONDOWN:
		/* map the mouse scroll wheel to up/down */
		if (event->button.button == SDL_BUTTON_WHEELUP) {
			jevent.type = JIVE_EVENT_SCROLL;
			--(jevent.u.scroll.rel);
			break;
		}
		else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
			jevent.type = JIVE_EVENT_SCROLL;
			++(jevent.u.scroll.rel);
			break;
		}

		// Fall through

	case SDL_MOUSEBUTTONUP:
		if (event->button.button == SDL_BUTTON_LEFT) {
			if (event->button.state == SDL_PRESSED) {
				jevent.type = JIVE_EVENT_MOUSE_DOWN;
				jevent.u.mouse.x = event->button.x;
				jevent.u.mouse.y = event->button.y;
			}
			else {
				jevent.type = JIVE_EVENT_MOUSE_UP;
				jevent.u.mouse.x = event->button.x;
				jevent.u.mouse.y = event->button.y;
			}
		}

		if (event->type == SDL_MOUSEBUTTONDOWN) {
			if (mouse_state == MOUSE_STATE_NONE) {
				mouse_state = MOUSE_STATE_DOWN;
				mouse_timeout_arg = (event->button.y << 16) | event->button.x;
				mouse_timeout = now + HOLD_TIMEOUT;
				mouse_long_timeout = now + LONG_HOLD_TIMEOUT;

				mouse_origin_x = event->button.x;
				mouse_origin_y = event->button.y;
				break;
			}
		}
		else /* SDL_MOUSEBUTTONUP */ {
			if (mouse_state == MOUSE_STATE_DOWN) {
				/*
				 * MOUSE_PRESSED and MOUSE_UP events
				 */
				JiveEvent up;

				memset(&up, 0, sizeof(JiveEvent));
				up.type = JIVE_EVENT_MOUSE_PRESS;
				up.ticks = jive_jiffies();
				up.u.mouse.x = event->button.x;
				up.u.mouse.y = event->button.y;
				do_dispatch_event(L, &up);
			}

			mouse_timeout = 0;
			mouse_long_timeout = 0;
			mouse_state = MOUSE_STATE_NONE;
		}
		break;

	case SDL_MOUSEMOTION:

		/* show mouse cursor */
		if (pointer_timeout == 0) {
			SDL_ShowCursor(SDL_ENABLE);
		}
		pointer_timeout = now + POINTER_TIMEOUT;

		if (event->motion.state & SDL_BUTTON(1)) {
			if ( (mouse_state == MOUSE_STATE_DOWN || mouse_state == MOUSE_STATE_SENT)) {
				jevent.type = JIVE_EVENT_MOUSE_DRAG;
				jevent.u.mouse.x = event->motion.x;
				jevent.u.mouse.y = event->motion.y;
			}
		}
		else {
			jevent.type = JIVE_EVENT_MOUSE_MOVE;
			jevent.u.mouse.x = event->motion.x;
			jevent.u.mouse.y = event->motion.y;
		}
		break;

	case SDL_KEYDOWN:
		if (event->key.keysym.mod == KMOD_NONE || event->key.keysym.mod == KMOD_NUM) {
			if (event->key.keysym.sym == SDLK_UP) {
				jevent.type = JIVE_EVENT_SCROLL;
				--(jevent.u.scroll.rel);
				break;
			}
			else if (event->key.keysym.sym == SDLK_DOWN) {
				jevent.type = JIVE_EVENT_SCROLL;
				++(jevent.u.scroll.rel);
				break;
			}
		}
		// Fall through

	case SDL_KEYUP: {
		struct jive_keymap *entry = keymap;

#ifdef EMULATE_IR
		if (event->key.keysym.mod & (KMOD_ALT|KMOD_MODE)) {
			struct jive_keyir *ir = irmap;

			while (ir->keysym != SDLK_UNKNOWN) {
				if (ir->keysym == event->key.keysym.sym) {
					break;
				}
				ir++;
			}
			if (ir->keysym == SDLK_UNKNOWN) {
				break;
			}

			if (event->type == SDL_KEYDOWN) {
				jevent.type = JIVE_EVENT_IR_DOWN;
				jevent.u.ir.code = ir->code;
			}
			else {
				JiveEvent irup;

				jevent.type = JIVE_EVENT_IR_PRESS;
				jevent.u.ir.code = ir->code;

				memset(&irup, 0, sizeof(JiveEvent));
				irup.type = JIVE_EVENT_IR_UP;
				irup.ticks = jive_jiffies();
				irup.u.ir.code = ir->code;
				jive_queue_event(&irup);
			}

			break;
		}
#endif

		while (entry->keysym != SDLK_UNKNOWN) {
			if (entry->keysym == event->key.keysym.sym) {
				if (event->type == SDL_KEYDOWN && (!entry->mod || entry->mod == event->key.keysym.mod)) {
					// match a key with same modifiers if present on keydown
					break;
				}
				if (event->type == SDL_KEYUP && (key_mask & entry->keycode)) {
					// match a key which is currently marked as down ignoring modifiers as they may have changed
					break;
				}
			}
			entry++;
		}

		if (entry->keysym == SDLK_UNKNOWN) {
			// handle regular character keys ('a', 't', etc..)
			if (event->type == SDL_KEYDOWN && event->key.keysym.unicode != 0) {
				jevent.type = JIVE_EVENT_CHAR_PRESS;
				if (event->key.keysym.sym == SDLK_BACKSPACE) {
					//special case for Backspace, where value set is not ascii value, instead pass backspace ascii value
					jevent.u.text.unicode = 8;
				} else {
					jevent.u.text.unicode = event->key.keysym.unicode;
				}
			}
		}

		/* handle pgup/upgn and cursors as repeatable keys */
		else if (entry->keysym == SDLK_PAGEUP || entry->keysym == SDLK_PAGEDOWN ||
				entry->keysym == SDLK_UP || entry->keysym == SDLK_DOWN || entry->keysym == SDLK_LEFT || entry->keysym == SDLK_RIGHT) {
			if (event->type == SDL_KEYDOWN) {
				jevent.type = JIVE_EVENT_KEY_PRESS;
				jevent.ticks = jive_jiffies();
				jevent.u.key.code = entry->keycode;
			}
		}
		
		else if (event->type == SDL_KEYDOWN) {
			if (key_mask & entry->keycode) {
				// ignore key repeats
				return 0;
			}
			if (key_mask == 0) {
				key_state = KEY_STATE_NONE;
			}

			switch (key_state) {
			case KEY_STATE_NONE:
				key_state = KEY_STATE_DOWN;
				// fall through

			case KEY_STATE_DOWN: {
				key_mask |= entry->keycode;

				jevent.type = JIVE_EVENT_KEY_DOWN;
				jevent.u.key.code = entry->keycode;

				key_timeout = now + HOLD_TIMEOUT;
				break;
			 }

			case KEY_STATE_SENT:
				break;
			}
		}
		else /* SDL_KEYUP */ {
			if (! (key_mask & entry->keycode)) {
				// ignore repeated key ups
				return 0;
			}

			switch (key_state) {
			case KEY_STATE_NONE:
				break;

			case KEY_STATE_DOWN: {
				/*
				 * KEY_PRESSED and KEY_UP events
				 */
				JiveEvent keyup;

				jevent.type = JIVE_EVENT_KEY_PRESS;
				jevent.u.key.code = key_mask;

				memset(&keyup, 0, sizeof(JiveEvent));
				keyup.type = JIVE_EVENT_KEY_UP;
				keyup.ticks = jive_jiffies();
				keyup.u.key.code = entry->keycode;
				jive_queue_event(&keyup);

				key_state = KEY_STATE_SENT;
				break;
			}

			case KEY_STATE_SENT: {
				/*
				 * KEY_UP event
				 */
				jevent.type = JIVE_EVENT_KEY_UP;
				jevent.u.key.code = entry->keycode;
				break;
			}
			}

			key_timeout = 0;
			key_mask &= ~(entry->keycode);
			if (key_mask == 0) {
				key_state = KEY_STATE_NONE;
			}
		}
		break;
	}

	case SDL_USEREVENT:
		assert(event->user.code == JIVE_USER_EVENT_EVENT);

		memcpy(&jevent, event->user.data1, sizeof(JiveEvent));
		free(event->user.data1);
		break;

	case SDL_VIDEORESIZE: {
		JiveSurface *srf;
		int bpp = 16;

		screen_w = event->resize.w;
		screen_h = event->resize.h;

		srf = jive_surface_set_video_mode(screen_w, screen_h, bpp, jive_surface_isSDLFullScreen(NULL));

		if (!srf) {
			LOG_ERROR(log_ui_draw, "Video mode not supported: %dx%d\n", screen_w, screen_h);

			SDL_Quit();
			exit(-1);
		}

		lua_getfield(L, 1, "screen");

		lua_getfield(L, -1, "bounds");
		lua_pushinteger(L, screen_w);
		lua_rawseti(L, -2, 3);
		lua_pushinteger(L, screen_h);
		lua_rawseti(L, -2, 4);
		lua_pop(L, 1);

		tolua_pushusertype(L, srf, "Surface");
		lua_setfield(L, -2, "surface");

		lua_pop(L, 1);

		next_jive_origin++;

		jevent.type = JIVE_EVENT_WINDOW_RESIZE;
		
		/* Avoid mouse_up causing a mouse press event to occur */
		mouse_state = MOUSE_STATE_NONE;
		break;

	}

	default:
		return 0;
	}

	return do_dispatch_event(L, &jevent);
}
예제 #9
0
int jiveL_get_ticks(lua_State *L) {
	lua_pushinteger(L, jive_jiffies());
	return 1;
}
예제 #10
0
static int process_event(lua_State *L, SDL_Event *event) {
	JiveEvent jevent;
	Uint32 now;

	memset(&jevent, 0, sizeof(JiveEvent));
	jevent.ticks = now = jive_jiffies();

	switch (event->type) {
	case SDL_QUIT:
		jiveL_quit(L);
		exit(0);
		break;

	case SDL_MOUSEBUTTONDOWN:
		/* map the mouse scroll wheel to up/down */
		if (event->button.button == SDL_BUTTON_WHEELUP) {
			jevent.type = JIVE_EVENT_SCROLL;
			--(jevent.u.scroll.rel);
			break;
		}
		else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
			jevent.type = JIVE_EVENT_SCROLL;
			++(jevent.u.scroll.rel);
			break;
		}

		// Fall through

	case SDL_MOUSEBUTTONUP:
		if (event->button.button == SDL_BUTTON_LEFT) {
			if (event->button.state == SDL_PRESSED) {
				jevent.type = JIVE_EVENT_MOUSE_DOWN;
				jevent.u.mouse.x = event->button.x;
				jevent.u.mouse.y = event->button.y;
			}
			else {
				jevent.type = JIVE_EVENT_MOUSE_UP;
				jevent.u.mouse.x = event->button.x;
				jevent.u.mouse.y = event->button.y;
			}
		}

		if (event->type == SDL_MOUSEBUTTONDOWN) {
			if (mouse_state == MOUSE_STATE_NONE) {
				mouse_state = MOUSE_STATE_DOWN;
				mouse_timeout_arg = (event->button.y << 16) | event->button.x;
				mouse_timeout = now + HOLD_TIMEOUT;
				mouse_long_timeout = now + LONG_HOLD_TIMEOUT;

				mouse_origin_x = event->button.x;
				mouse_origin_y = event->button.y;
				break;
			}
		}
		else /* SDL_MOUSEBUTTONUP */ {
			if (mouse_state == MOUSE_STATE_DOWN) {
				/*
				 * MOUSE_PRESSED and MOUSE_UP events
				 */
				JiveEvent up;

				memset(&up, 0, sizeof(JiveEvent));
				up.type = JIVE_EVENT_MOUSE_PRESS;
				up.ticks = jive_jiffies();
				up.u.mouse.x = event->button.x;
				up.u.mouse.y = event->button.y;
				do_dispatch_event(L, &up);
			}

			mouse_timeout = 0;
			mouse_long_timeout = 0;
			mouse_state = MOUSE_STATE_NONE;
		}
		break;

	case SDL_MOUSEMOTION:

		/* show mouse cursor */
		if (pointer_timeout == 0) {
			SDL_ShowCursor(SDL_ENABLE);
		}
		pointer_timeout = now + POINTER_TIMEOUT;

		if (event->motion.state & SDL_BUTTON(1)) {
			if ( (mouse_state == MOUSE_STATE_DOWN || mouse_state == MOUSE_STATE_SENT)) {
				jevent.type = JIVE_EVENT_MOUSE_DRAG;
				jevent.u.mouse.x = event->motion.x;
				jevent.u.mouse.y = event->motion.y;
			}
		}
		else {
			jevent.type = JIVE_EVENT_MOUSE_MOVE;
			jevent.u.mouse.x = event->motion.x;
			jevent.u.mouse.y = event->motion.y;
		}
		break;

	case SDL_KEYDOWN:
		/*
		  this emulates the scrollwheel using keypresses - remove for them moment as we want 4 way navigation

		if (event->key.keysym.mod == KMOD_NONE || event->key.keysym.mod == KMOD_NUM) {
			if (event->key.keysym.sym == SDLK_UP) {
				jevent.type = JIVE_EVENT_SCROLL;
				--(jevent.u.scroll.rel);
				break;
			}
			else if (event->key.keysym.sym == SDLK_DOWN) {
				jevent.type = JIVE_EVENT_SCROLL;
				++(jevent.u.scroll.rel);
				break;
			}
		}
		*/
		// Fall through

	case SDL_KEYUP: {
		struct jive_keymap *entry = keymap;
		
		if (event->key.keysym.mod & (KMOD_ALT|KMOD_MODE)) {
			/* simulate IR input, using alt key */
			struct jive_keyir *ir = irmap;

			while (ir->keysym != SDLK_UNKNOWN) {
				if (ir->keysym == event->key.keysym.sym) {
					break;
				}
				ir++;
			}
			if (ir->keysym == SDLK_UNKNOWN) {
				break;
			}

			if (event->type == SDL_KEYDOWN) {
				jevent.type = JIVE_EVENT_IR_DOWN;
				jevent.u.ir.code = ir->code;
			}
			else {
				JiveEvent irup;

				jevent.type = JIVE_EVENT_IR_PRESS;
				jevent.u.ir.code = ir->code;

				memset(&irup, 0, sizeof(JiveEvent));
				irup.type = JIVE_EVENT_IR_UP;
				irup.ticks = jive_jiffies();
				irup.u.ir.code = ir->code;
				jive_queue_event(&irup);
			}

			break;
		}

		while (entry->keysym != SDLK_UNKNOWN) {
			if (entry->keysym == event->key.keysym.sym) {
				break;
			}
			entry++;
		}

		if (entry->keysym == SDLK_UNKNOWN) {
			// handle regular character keys ('a', 't', etc..)
			if (event->type == SDL_KEYDOWN && event->key.keysym.unicode != 0) {
				jevent.type = JIVE_EVENT_CHAR_PRESS;
				if (event->key.keysym.sym == SDLK_BACKSPACE) {
					//special case for Backspace, where value set is not ascii value, instead pass backspace ascii value
					jevent.u.text.unicode = 8;
				} else {
					jevent.u.text.unicode = event->key.keysym.unicode;
				}
			}
		}

		/* handle pgup/upgn as repeatable keys */
		else if (entry->keysym == SDLK_PAGEUP || entry->keysym == SDLK_PAGEDOWN ||
				 entry->keysym == SDLK_UP || entry->keysym == SDLK_DOWN || entry->keysym == SDLK_LEFT || entry->keysym == SDLK_RIGHT ) {
			if (event->type == SDL_KEYDOWN) {
				jevent.type = JIVE_EVENT_KEY_PRESS;
				jevent.ticks = jive_jiffies();
				jevent.u.key.code = entry->keycode;
			}
		}
		
		else if (event->type == SDL_KEYDOWN) {
			if (key_mask & entry->keycode) {
				// ignore key repeats
				return 0;
			}
			if (key_mask == 0) {
				key_state = KEY_STATE_NONE;
			}

			switch (key_state) {
			case KEY_STATE_NONE:
				key_state = KEY_STATE_DOWN;
				// fall through

			case KEY_STATE_DOWN: {
				key_mask |= entry->keycode;

				jevent.type = JIVE_EVENT_KEY_DOWN;
				jevent.u.key.code = entry->keycode;

				key_timeout = now + HOLD_TIMEOUT;
				break;
			 }

			case KEY_STATE_SENT:
				break;
			}
		}
		else /* SDL_KEYUP */ {
			if (! (key_mask & entry->keycode)) {
				// ignore repeated key ups
				return 0;
			}

			switch (key_state) {
			case KEY_STATE_NONE:
				break;

			case KEY_STATE_DOWN: {
				/*
				 * KEY_PRESSED and KEY_UP events
				 */
				JiveEvent keyup;

				jevent.type = JIVE_EVENT_KEY_PRESS;
				jevent.u.key.code = key_mask;

				memset(&keyup, 0, sizeof(JiveEvent));
				keyup.type = JIVE_EVENT_KEY_UP;
				keyup.ticks = jive_jiffies();
				keyup.u.key.code = entry->keycode;
				jive_queue_event(&keyup);

				key_state = KEY_STATE_SENT;
				break;
			}

			case KEY_STATE_SENT: {
				/*
				 * KEY_UP event
				 */
				jevent.type = JIVE_EVENT_KEY_UP;
				jevent.u.key.code = entry->keycode;
				break;
			}
			}

			key_timeout = 0;
			key_mask &= ~(entry->keycode);
			if (key_mask == 0) {
				key_state = KEY_STATE_NONE;
			}
		}
		break;
	}

	case SDL_USEREVENT:
		assert(event->user.code == JIVE_USER_EVENT_EVENT);

		memcpy(&jevent, event->user.data1, sizeof(JiveEvent));
		free(event->user.data1);
		break;

		/* disable for the moment as it causes continual resizing
		   if the event for a resize gets delayed as we have a stack of resize notifications which cause resize to the old size

	case SDL_VIDEORESIZE: {
		JiveSurface *srf;
		int bpp = 16;

		screen_w = event->resize.w;
		screen_h = event->resize.h;

		srf = jive_surface_set_video_mode(screen_w, screen_h, bpp, false);

		lua_getfield(L, 1, "screen");

		lua_getfield(L, -1, "bounds");
		lua_pushinteger(L, screen_w);
		lua_rawseti(L, -2, 3);
		lua_pushinteger(L, screen_h);
		lua_rawseti(L, -2, 4);
		lua_pop(L, 1);

		JiveSurface **p = (JiveSurface **)lua_newuserdata(L, sizeof(JiveSurface *));
		*p = jive_surface_ref(srf);
		luaL_getmetatable(L, "JiveSurface");
		lua_setmetatable(L, -2);

		lua_setfield(L, -2, "surface");

		lua_pop(L, 1);

		next_jive_origin++;

		jevent.type = JIVE_EVENT_WINDOW_RESIZE;
		
		mouse_state = MOUSE_STATE_NONE;
		break;

	}
	*/

	default:
		return 0;
	}

	return do_dispatch_event(L, &jevent);
}