Beispiel #1
0
/*
 * Shuts the SDL render backend down
 */
void
GLimp_Shutdown(void)
{
	/* Clear the backbuffer and make it
	   current. This may help some broken
	   video drivers like the AMD Catalyst
	   to avoid artifacts in unused screen
	   areas. */
	if (SDL_WasInit(SDL_INIT_VIDEO))
	{
		glClearColor(0.0, 0.0, 0.0, 0.0);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		GLimp_EndFrame();
	}

#ifdef X11GAMMA
	RestoreGamma();
#endif

	if (window)
	{
		/* cleanly ungrab input (needs window) */
		GLimp_GrabInput(false);

#if SDL_VERSION_ATLEAST(2, 0, 0)
		if(context)
		{
			SDL_GL_DeleteContext(context);
			context = NULL;
		}

		SDL_DestroyWindow(window);
#else
		SDL_FreeSurface(window);
#endif
	}

	window = NULL;

	if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
	{
		SDL_Quit();
	}
	else
	{
		SDL_QuitSubSystem(SDL_INIT_VIDEO);
	}

	gl_state.hwgamma = false;
}
Beispiel #2
0
/*
 * Updates the input queue state. Called every
 * frame by the client and does nearly all the
 * input magic.
 */
void
IN_Update(void)
{
	qboolean want_grab;
	SDL_Event event;
	unsigned int key;

	/* Get and process an event */
	while (SDL_PollEvent(&event))
	{

		switch (event.type)
		{
#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_MOUSEWHEEL:
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), true, true);
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), false, true);
				break;
#endif
			case SDL_MOUSEBUTTONDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if (event.button.button == 4)
				{
					Key_Event(K_MWHEELUP, true, true);
					Key_Event(K_MWHEELUP, false, true);
					break;
				}
				else if (event.button.button == 5)
				{
					Key_Event(K_MWHEELDOWN, true, true);
					Key_Event(K_MWHEELDOWN, false, true);
					break;
				}
#endif
				/* fall-through */
			case SDL_MOUSEBUTTONUP:
				switch (event.button.button)
				{
					case SDL_BUTTON_LEFT:
						key = K_MOUSE1;
						break;
					case SDL_BUTTON_MIDDLE:
						key = K_MOUSE3;
						break;
					case SDL_BUTTON_RIGHT:
						key = K_MOUSE2;
						break;
					case SDL_BUTTON_X1:
						key = K_MOUSE4;
						break;
					case SDL_BUTTON_X2:
						key = K_MOUSE5;
						break;
					default:
						return;
				}

				Key_Event(key, (event.type == SDL_MOUSEBUTTONDOWN), true);
				break;

			case SDL_MOUSEMOTION:
				if (cls.key_dest == key_game && (int) cl_paused->value == 0)
				{
					mouse_x += event.motion.xrel;
					mouse_y += event.motion.yrel;
				}
				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_TEXTINPUT:
				if ((event.text.text[0] >= ' ') &&
					(event.text.text[0] <= '~'))
				{
					Char_Event(event.text.text[0]);
				}

				break;
#endif

			case SDL_KEYDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if ((event.key.keysym.unicode >= SDLK_SPACE) &&
					 (event.key.keysym.unicode < SDLK_DELETE))
				{
					Char_Event(event.key.keysym.unicode);
				}
#endif
				/* fall-through */
			case SDL_KEYUP:
			{
				qboolean down = (event.type == SDL_KEYDOWN);

#if SDL_VERSION_ATLEAST(2, 0, 0)
				/* workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
				 * always map those physical keys (scancodes) to those keycodes anyway
				 * see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188 */
				SDL_Scancode sc = event.key.keysym.scancode;
				if (sc >= SDL_SCANCODE_1 && sc <= SDL_SCANCODE_0)
				{
					/* Note that the SDL_SCANCODEs are SDL_SCANCODE_1, _2, ..., _9, SDL_SCANCODE_0
					 * while in ASCII it's '0', '1', ..., '9' => handle 0 and 1-9 separately
					 * (quake2 uses the ASCII values for those keys) */
					int key = '0'; /* implicitly handles SDL_SCANCODE_0 */
					if (sc <= SDL_SCANCODE_9)
					{
						key = '1' + (sc - SDL_SCANCODE_1);
					}
					Key_Event(key, down, false);
				}
				else
#endif /* SDL2; (SDL1.2 doesn't have scancodes so nothing we can do there) */
				if ((event.key.keysym.sym >= SDLK_SPACE) &&
					(event.key.keysym.sym < SDLK_DELETE))
				{
					Key_Event(event.key.keysym.sym, down, false);
				}
				else
				{
					Key_Event(IN_TranslateSDLtoQ2Key(event.key.keysym.sym), down, true);
				}
			}
				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_WINDOWEVENT:
				if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ||
					event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
				{
					Key_MarkAllUp();
				}
				else if (event.window.event == SDL_WINDOWEVENT_MOVED)
				{
					// make sure GLimp_GetRefreshRate() will query from SDL again - the window might
					// be on another display now!
					glimp_refreshRate = -1;
				}

#else /* SDL1.2 */
			case SDL_ACTIVEEVENT:
				if(event.active.gain == 0 && (event.active.state & SDL_APPINPUTFOCUS))
				{
					Key_MarkAllUp();
				}
#endif
				break;
#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_CONTROLLERBUTTONUP:
			case SDL_CONTROLLERBUTTONDOWN: /* Handle Controller Back button */
			{
				qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);
				if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK)
				{
					Key_Event(K_JOY_BACK, down, true);
				}
			}
				break;
			case SDL_CONTROLLERAXISMOTION:  /* Handle Controller Motion */
			{
				char *direction_type;
				float threshold = 0;
				float fix_value = 0;
				int axis_value = event.caxis.value;
				switch (event.caxis.axis)
				{
					/* left/right */
					case SDL_CONTROLLER_AXIS_LEFTX:
						direction_type = joy_axis_leftx->string;
						threshold = joy_axis_leftx_threshold->value;
						break;
						/* top/bottom */
					case SDL_CONTROLLER_AXIS_LEFTY:
						direction_type = joy_axis_lefty->string;
						threshold = joy_axis_lefty_threshold->value;
						break;
						/* second left/right */
					case SDL_CONTROLLER_AXIS_RIGHTX:
						direction_type = joy_axis_rightx->string;
						threshold = joy_axis_rightx_threshold->value;
						break;
						/* second top/bottom */
					case SDL_CONTROLLER_AXIS_RIGHTY:
						direction_type = joy_axis_righty->string;
						threshold = joy_axis_righty_threshold->value;
						break;
					case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
						direction_type = joy_axis_triggerleft->string;
						threshold = joy_axis_triggerleft_threshold->value;
						break;
					case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
						direction_type = joy_axis_triggerright->string;
						threshold = joy_axis_triggerright_threshold->value;
						break;
					default:
						direction_type = "none";
				}

				if (threshold > 0.9)
					threshold = 0.9;

				if (axis_value < 0 && (axis_value > (32768 * threshold)))
					axis_value = 0;
				else if (axis_value > 0 && (axis_value < (32768 * threshold)))
					axis_value = 0;

				// Smoothly ramp from dead zone to maximum value (from ioquake)
				// https://github.com/ioquake/ioq3/blob/master/code/sdl/sdl_input.c
				fix_value = ((float) abs(axis_value) / 32767.0f - threshold) / (1.0f - threshold);
				if (fix_value < 0.0f)
					fix_value = 0.0f;

				axis_value = (int) (32767 * ((axis_value < 0) ? -fix_value : fix_value));

				if (cls.key_dest == key_game && (int) cl_paused->value == 0)
				{
					if (strcmp(direction_type, "sidemove") == 0)
					{
						joystick_sidemove = axis_value * joy_sidesensitivity->value;
						// We need to be twice faster because with joystic we run...
						joystick_sidemove *= cl_sidespeed->value * 2.0f;
					}
					else if (strcmp(direction_type, "forwardmove") == 0)
					{
						joystick_forwardmove = axis_value * joy_forwardsensitivity->value;
						// We need to be twice faster because with joystic we run...
						joystick_forwardmove *= cl_forwardspeed->value * 2.0f;
					}
					else if (strcmp(direction_type, "yaw") == 0)
					{
						joystick_yaw = axis_value * joy_yawsensitivity->value;
						joystick_yaw *= cl_yawspeed->value;
					}
					else if (strcmp(direction_type, "pitch") == 0)
					{
						joystick_pitch = axis_value * joy_pitchsensitivity->value;
						joystick_pitch *= cl_pitchspeed->value;
					}
					else if (strcmp(direction_type, "updown") == 0)
					{
						joystick_up = axis_value * joy_upsensitivity->value;
						joystick_up *= cl_upspeed->value;
					}
				}

				if (strcmp(direction_type, "triggerleft") == 0)
				{
					qboolean new_left_trigger = abs(axis_value) > (32767 / 4);
					if (new_left_trigger != left_trigger)
					{
						left_trigger = new_left_trigger;
						Key_Event(K_TRIG_LEFT, left_trigger, true);
					}
				}
				else if (strcmp(direction_type, "triggerright") == 0)
				{
					qboolean new_right_trigger = abs(axis_value) > (32767 / 4);
					if (new_right_trigger != right_trigger)
					{
						right_trigger = new_right_trigger;
						Key_Event(K_TRIG_RIGHT, right_trigger, true);
					}
				}
			}
				break;
				/* Joystick can have more buttons than on general game controller
				 * so try to map not free buttons */
			case SDL_JOYBUTTONUP:
			case SDL_JOYBUTTONDOWN:
			{
				qboolean down = (event.type == SDL_JOYBUTTONDOWN);
				/* Ignore back button, we dont need event for such button */
				if (back_button_id == event.jbutton.button)
					return;
				if (event.jbutton.button <= (K_JOY32 - K_JOY1))
				{
					Key_Event(event.jbutton.button + K_JOY1, down, true);
				}
			}
				break;
			case SDL_JOYHATMOTION:
			{
				if (last_hat != event.jhat.value)
				{
					char diff = last_hat ^event.jhat.value;
					int i;
					for (i = 0; i < 4; i++)
					{
						if (diff & (1 << i))
						{
							/* check that we have button up for some bit */
							if (last_hat & (1 << i))
								Key_Event(i + K_HAT_UP, false, true);

							/* check that we have button down for some bit */
							if (event.jhat.value & (1 << i))
								Key_Event(i + K_HAT_UP, true, true);
						}
					}
					last_hat = event.jhat.value;
				}
			}
				break;
#endif
			case SDL_QUIT:
				Com_Quit();

				break;
		}
	}

	/* Grab and ungrab the mouse if the console or the menu is opened */
	if (in_grab->value == 3)
	{
		want_grab = windowed_mouse->value;
	}
	else
	{
		want_grab = (vid_fullscreen->value || in_grab->value == 1 ||
			(in_grab->value == 2 && windowed_mouse->value));
	}

	/* calling GLimp_GrabInput() each is a bit ugly but simple and should work.
	 * + the called SDL functions return after a cheap check, if there's
	 * nothing to do, anyway. */
	GLimp_GrabInput(want_grab);

	/* We need to save the frame time so other subsystems know the
	 * exact time of the last input events. */
	sys_frame_time = Sys_Milliseconds();
}
Beispiel #3
0
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent() {
	SDL_Event ev;
	sysEvent_t res = { };
	byte key;

	static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };

#if SDL_VERSION_ATLEAST(2, 0, 0)
	static char s[SDL_TEXTINPUTEVENT_TEXT_SIZE] = {0};
	static size_t s_pos = 0;

	if (s[0] != '\0') {
		res.evType = SE_CHAR;
		res.evValue = s[s_pos];

		++s_pos;

		if (!s[s_pos] || s_pos == SDL_TEXTINPUTEVENT_TEXT_SIZE) {
			memset(s, 0, sizeof(s));
			s_pos = 0;
		}

		return res;
	}
#endif

	static byte c = 0;

	if (c) {
		res.evType = SE_CHAR;
		res.evValue = c;

		c = 0;

		return res;
	}

	// loop until there is an event we care about (will return then) or no more events
	while(SDL_PollEvent(&ev)) {
		switch (ev.type) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
		case SDL_WINDOWEVENT:
			switch (ev.window.event) {
				case SDL_WINDOWEVENT_FOCUS_GAINED: {
						// unset modifier, in case alt-tab was used to leave window and ALT is still set
						// as that can cause fullscreen-toggling when pressing enter...
						SDL_Keymod currentmod = SDL_GetModState();
					
						int newmod = KMOD_NONE;
						if (currentmod & KMOD_CAPS) // preserve capslock
							newmod |= KMOD_CAPS;

						SDL_SetModState((SDL_Keymod)newmod);
					} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST

					GLimp_GrabInput(GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR);
					break;
				case SDL_WINDOWEVENT_FOCUS_LOST:
					GLimp_GrabInput(0);
					break;
			}

			continue; // handle next event
#else
		case SDL_ACTIVEEVENT:
			{
				int flags = 0;

				if (ev.active.gain) {
					flags = GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR;

					// unset modifier, in case alt-tab was used to leave window and ALT is still set
					// as that can cause fullscreen-toggling when pressing enter...
					SDLMod currentmod = SDL_GetModState();
					int newmod = KMOD_NONE;
					if (currentmod & KMOD_CAPS) // preserve capslock
						newmod |= KMOD_CAPS;

					SDL_SetModState((SDLMod)newmod);
				}

				GLimp_GrabInput(flags);
			}

			continue; // handle next event

		case SDL_VIDEOEXPOSE:
			continue; // handle next event
#endif

		case SDL_KEYDOWN:
			if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
				cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
				PushConsoleEvent("vid_restart");
				return res_none;
			}

			// fall through
		case SDL_KEYUP:
			key = mapkey(ev.key.keysym.sym);
#if !SDL_VERSION_ATLEAST(2, 0, 0)
			if (!key) {
				unsigned char c;
				// check if its an unmapped console key
				if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(false))) {
					key = c;
				} else if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(true))) {
					key = c;
				} else {
					if (ev.type == SDL_KEYDOWN)
						common->Warning("unmapped SDL key %d (0x%x)", ev.key.keysym.sym, ev.key.keysym.unicode);
					continue; // handle next event
				}
			}
#else
			if(!key) {
				if (ev.key.keysym.scancode == SDL_SCANCODE_GRAVE) { // TODO: always do this check?
					key = Sys_GetConsoleKey(true);
				} else {
					if (ev.type == SDL_KEYDOWN) {
						common->Warning("unmapped SDL key %d", ev.key.keysym.sym);
					}
					continue; // handle next event
				}
			}

#endif

			res.evType = SE_KEY;
			res.evValue = key;
			res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;

			kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));

#if SDL_VERSION_ATLEAST(2, 0, 0)
			if (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
				c = key;
#else
			if (ev.key.state == SDL_PRESSED && (ev.key.keysym.unicode & 0xff00) == 0)
				c = ev.key.keysym.unicode & 0xff;
#endif

			return res;

#if SDL_VERSION_ATLEAST(2, 0, 0)
		case SDL_TEXTINPUT:
			if (ev.text.text[0]) {
				res.evType = SE_CHAR;
				res.evValue = ev.text.text[0];

				if (ev.text.text[1] != '\0')
				{
					memcpy(s, ev.text.text, SDL_TEXTINPUTEVENT_TEXT_SIZE);
					s_pos = 1; // pos 0 is returned
				}
				return res;
			}

			continue; // handle next event
#endif

		case SDL_MOUSEMOTION:
			res.evType = SE_MOUSE;
			res.evValue = ev.motion.xrel;
			res.evValue2 = ev.motion.yrel;

			mouse_polls.Append(mouse_poll_t(M_DELTAX, ev.motion.xrel));
			mouse_polls.Append(mouse_poll_t(M_DELTAY, ev.motion.yrel));

			return res;

#if SDL_VERSION_ATLEAST(2, 0, 0)
		case SDL_MOUSEWHEEL:
			res.evType = SE_KEY;

			if (ev.wheel.y > 0) {
				res.evValue = K_MWHEELUP;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
			} else {
				res.evValue = K_MWHEELDOWN;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
			}

			res.evValue2 = 1;

			return res;
#endif

		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			res.evType = SE_KEY;

			switch (ev.button.button) {
			case SDL_BUTTON_LEFT:
				res.evValue = K_MOUSE1;
				mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_MIDDLE:
				res.evValue = K_MOUSE3;
				mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_RIGHT:
				res.evValue = K_MOUSE2;
				mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;

#if !SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_BUTTON_WHEELUP:
				res.evValue = K_MWHEELUP;
				if (ev.button.state == SDL_PRESSED)
					mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
				break;
			case SDL_BUTTON_WHEELDOWN:
				res.evValue = K_MWHEELDOWN;
				if (ev.button.state == SDL_PRESSED)
					mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
				break;
#endif
			}

			res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;

			return res;

		case SDL_QUIT:
			PushConsoleEvent("quit");
			return res_none;

		case SDL_USEREVENT:
			switch (ev.user.code) {
			case SE_CONSOLE:
				res.evType = SE_CONSOLE;
				res.evPtrLength = (intptr_t)ev.user.data1;
				res.evPtr = ev.user.data2;
				return res;
			default:
				common->Warning("unknown user event %u", ev.user.code);
				continue; // handle next event
			}
		default:
			common->Warning("unknown event %u", ev.type);
			continue; // handle next event
		}
	}

	return res_none;
}
Beispiel #4
0
/*
 * Updates the input queue state. Called every
 * frame by the client and does nearly all the
 * input magic.
 */
void
IN_Update(void)
{
	qboolean want_grab;
	SDL_Event event;
 	unsigned int key;

	/* Get and process an event */
	while (SDL_PollEvent(&event))
	{

		switch (event.type)
		{
#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_MOUSEWHEEL:
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), true, true);
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), false, true);
				break;
#endif
			case SDL_MOUSEBUTTONDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if (event.button.button == 4)
				{
					Key_Event(K_MWHEELUP, true, true);
					Key_Event(K_MWHEELUP, false, true);
					break;
				}
				else if (event.button.button == 5)
				{
					Key_Event(K_MWHEELDOWN, true, true);
					Key_Event(K_MWHEELDOWN, false, true);
					break;
				}
#endif
			case SDL_MOUSEBUTTONUP:
				switch( event.button.button )
				{
					case SDL_BUTTON_LEFT:
						key = K_MOUSE1;
						break;
					case SDL_BUTTON_MIDDLE:
						key = K_MOUSE3;
						break;
					case SDL_BUTTON_RIGHT:
						key = K_MOUSE2;
						break;
					case SDL_BUTTON_X1:
						key = K_MOUSE4;
						break;
					case SDL_BUTTON_X2:
						key = K_MOUSE5;
						break;
					default:
						return;
				}

				Key_Event(key, (event.type == SDL_MOUSEBUTTONDOWN), true);
				break;

			case SDL_MOUSEMOTION:
                if (cls.key_dest == key_game && (int)cl_paused->value == 0) {
                    mouse_x += event.motion.xrel;
                    mouse_y += event.motion.yrel;
                }
				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_TEXTINPUT:
				if ((event.text.text[0] >= SDLK_SPACE) &&
					 (event.text.text[0] < SDLK_DELETE))
				{
					Char_Event(event.text.text[0]);
				}

				break;
#endif

			case SDL_KEYDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if ((event.key.keysym.unicode >= SDLK_SPACE) &&
					 (event.key.keysym.unicode < SDLK_DELETE))
				{
					Char_Event(event.key.keysym.unicode);
				}
#endif

				if ((event.key.keysym.sym >= SDLK_SPACE) &&
					 (event.key.keysym.sym < SDLK_DELETE))
				{
					Key_Event(event.key.keysym.sym, true, false);
				}
				else
				{
					Key_Event(IN_TranslateSDLtoQ2Key(event.key.keysym.sym), true, true);
				}

				break;

			case SDL_KEYUP:

				if ((event.key.keysym.sym >= SDLK_SPACE) &&
					 (event.key.keysym.sym < SDLK_DELETE))
				{
					Key_Event(event.key.keysym.sym, false, false);
				}
				else
				{
					Key_Event(IN_TranslateSDLtoQ2Key(event.key.keysym.sym), false, true);
				}

				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_WINDOWEVENT:
				if(event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
				{
					Key_MarkAllUp();
				}

#else // SDL1.2
			case SDL_ACTIVEEVENT:
				if(event.active.gain == 0 && (event.active.state & SDL_APPINPUTFOCUS))
				{
					Key_MarkAllUp();
				}
#endif
				break;
		}
	}

	/* Grab and ungrab the mouse if the* console or the menu is opened */
	want_grab = (vid_fullscreen->value || in_grab->value == 1 ||
			(in_grab->value == 2 && windowed_mouse->value));
	/* calling GLimp_GrabInput() each is a but ugly but simple and should work.
	 * + the called SDL functions return after a cheap check, if there's
	 * nothing to do, anyway
	 */
	GLimp_GrabInput(want_grab);
}
Beispiel #5
0
/*
 * Updates the input queue state. Called every
 * frame by the client and does nearly all the
 * input magic.
 */
void
IN_Update(void)
{
	qboolean want_grab;
	SDL_Event event;
 	unsigned int key;

	/* Get and process an event */
	while (SDL_PollEvent(&event))
	{

		switch (event.type)
		{
#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_MOUSEWHEEL:
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), true, true);
				Key_Event((event.wheel.y > 0 ? K_MWHEELUP : K_MWHEELDOWN), false, true);
				break;
#endif
			case SDL_MOUSEBUTTONDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if (event.button.button == 4)
				{
					Key_Event(K_MWHEELUP, true, true);
					Key_Event(K_MWHEELUP, false, true);
					break;
				}
				else if (event.button.button == 5)
				{
					Key_Event(K_MWHEELDOWN, true, true);
					Key_Event(K_MWHEELDOWN, false, true);
					break;
				}
#endif
				/* fall-through */
			case SDL_MOUSEBUTTONUP:
				switch( event.button.button )
				{
					case SDL_BUTTON_LEFT:
						key = K_MOUSE1;
						break;
					case SDL_BUTTON_MIDDLE:
						key = K_MOUSE3;
						break;
					case SDL_BUTTON_RIGHT:
						key = K_MOUSE2;
						break;
					case SDL_BUTTON_X1:
						key = K_MOUSE4;
						break;
					case SDL_BUTTON_X2:
						key = K_MOUSE5;
						break;
					default:
						return;
				}

				Key_Event(key, (event.type == SDL_MOUSEBUTTONDOWN), true);
				break;

			case SDL_MOUSEMOTION:
                if (cls.key_dest == key_game && (int)cl_paused->value == 0) {
                    mouse_x += event.motion.xrel;
                    mouse_y += event.motion.yrel;
                }
				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_TEXTINPUT:
				if((event.text.text[0] >= ' ') &&
				   (event.text.text[0] <= '~'))
				{
					Char_Event(event.text.text[0]);
				}

				break;
#endif

			case SDL_KEYDOWN:
#if !SDL_VERSION_ATLEAST(2, 0, 0)
				if ((event.key.keysym.unicode >= SDLK_SPACE) &&
					 (event.key.keysym.unicode < SDLK_DELETE))
				{
					Char_Event(event.key.keysym.unicode);
				}
#endif
				/* fall-through */
			case SDL_KEYUP:
			{
				qboolean down = (event.type == SDL_KEYDOWN);

#if SDL_VERSION_ATLEAST(2, 0, 0)
				/* workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
				 * always map those physical keys (scancodes) to those keycodes anyway
				 * see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188 */
				SDL_Scancode sc = event.key.keysym.scancode;
				if(sc >= SDL_SCANCODE_1 && sc <= SDL_SCANCODE_0)
				{
					/* Note that the SDL_SCANCODEs are SDL_SCANCODE_1, _2, ..., _9, SDL_SCANCODE_0
					 * while in ASCII it's '0', '1', ..., '9' => handle 0 and 1-9 separately
					 * (quake2 uses the ASCII values for those keys) */
					int key = '0'; /* implicitly handles SDL_SCANCODE_0 */
					if(sc <= SDL_SCANCODE_9)
					{
						key = '1' + (sc - SDL_SCANCODE_1);
					}
					Key_Event(key, down, false);
				}
				else
#endif /* SDL2; (SDL1.2 doesn't have scancodes so nothing we can do there) */
				   if((event.key.keysym.sym >= SDLK_SPACE) &&
				      (event.key.keysym.sym < SDLK_DELETE))
				{
					Key_Event(event.key.keysym.sym, down, false);
				}
				else
				{
					Key_Event(IN_TranslateSDLtoQ2Key(event.key.keysym.sym), down, true);
				}
			}
				break;

#if SDL_VERSION_ATLEAST(2, 0, 0)
			case SDL_WINDOWEVENT:
				if(event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
				{
					Key_MarkAllUp();
				}

#else /* SDL1.2 */
			case SDL_ACTIVEEVENT:
				if(event.active.gain == 0 && (event.active.state & SDL_APPINPUTFOCUS))
				{
					Key_MarkAllUp();
				}
#endif
				break;
		}
	}

	/* Grab and ungrab the mouse if the* console or the menu is opened */
	want_grab = (vid_fullscreen->value || in_grab->value == 1 ||
			(in_grab->value == 2 && windowed_mouse->value));
	/* calling GLimp_GrabInput() each is a but ugly but simple and should work.
	 * + the called SDL functions return after a cheap check, if there's
	 * nothing to do, anyway
	 */
	GLimp_GrabInput(want_grab);
}
Beispiel #6
0
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent() {
	SDL_Event ev;
	sysEvent_t res = { };
	byte key;

	static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };

	static char *s = NULL;
	static size_t s_pos = 0;

	if (s) {
		res.evType = SE_CHAR;
		res.evValue = s[s_pos];

		s_pos++;
		if (!s[s_pos]) {
			free(s);
			s = NULL;
			s_pos = 0;
		}

		return res;
	}

	static byte c = 0;

	if (c) {
		res.evType = SE_CHAR;
		res.evValue = c;

		c = 0;

		return res;
	}

	if (SDL_PollEvent(&ev)) {
		switch (ev.type) {
		case SDL_WINDOWEVENT:
			switch (ev.window.event) {
			        case SDL_WINDOWEVENT_SHOWN:
					SDL_Log("Window %d shown", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_HIDDEN:
					SDL_Log("Window %d hidden", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_EXPOSED:
					SDL_Log("Window %d exposed", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_MOVED:
					SDL_Log("Window %d moved to %d,%d",
							ev.window.windowID, ev.window.data1,
							ev.window.data2);
					break;
				case SDL_WINDOWEVENT_RESIZED:
					SDL_Log("Window %d resized to %dx%d",
							ev.window.windowID, ev.window.data1,
							ev.window.data2);
					break;
				case SDL_WINDOWEVENT_MINIMIZED:
					SDL_Log("Window %d minimized", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_MAXIMIZED:
					SDL_Log("Window %d maximized", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_RESTORED:
					SDL_Log("Window %d restored", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_ENTER:
					SDL_Log("Mouse entered window %d",
							ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_LEAVE:
					SDL_Log("Mouse left window %d", ev.window.windowID);
					break;
				case SDL_WINDOWEVENT_FOCUS_GAINED:
					SDL_Log("Window %d gained keyboard focus",
							ev.window.windowID);
					cvarSystem->SetCVarBool( "com_pause", false );
					GLimp_GrabInput(GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR);
					break;
				case SDL_WINDOWEVENT_FOCUS_LOST:
					SDL_Log("Window %d lost keyboard focus",
							ev.window.windowID);
					cvarSystem->SetCVarBool( "com_pause", true );
					GLimp_GrabInput(0);
					break;
				case SDL_WINDOWEVENT_CLOSE:
					SDL_Log("Window %d closed", ev.window.windowID);
					break;
				default:
					SDL_Log("Window %d got unknown event %d",
							ev.window.windowID, ev.window.event);
					break;
			}

			return res_none;

		case SDL_KEYDOWN:
			if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
				cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
				PushConsoleEvent("vid_restart");
				/*
				 * FIXME vid_restart
				 */

				return res_none;
			}

			// fall through
		case SDL_KEYUP:
			key = mapkey(ev.key.keysym.sym);
			if(!key) {
				if (ev.key.keysym.scancode == SDL_SCANCODE_GRAVE) {
					key = Sys_GetConsoleKey(true);
				} else {
					if (ev.type == SDL_KEYDOWN) {
						common->Warning("unmapped SDL key %d", ev.key.keysym.sym);
					return res_none;
					}

				}
			}

			res.evType = SE_KEY;
			res.evValue = key;
			res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;

			kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));

			if (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
				c = key;

			return res;

		case SDL_TEXTINPUT:
			if (ev.text.text && *ev.text.text) {
				if (!ev.text.text[1])
					c = *ev.text.text;
				else
					s = strdup(ev.text.text);
			}

			return res_none;
		case SDL_TEXTEDITING:
		  SDL_StartTextInput();
		  SDL_Log("SDL_TextEditingEvent");
		  //SDL_StopTextInput();
		  break;
		case SDL_SYSWMEVENT:
		  SDL_Log("SDL_SYSWMEVENT");
		  break;
		case SDL_CLIPBOARDUPDATE:
		  SDL_Log("SDL_CLIPBOARDUPDATE");
		  break;

		case SDL_MOUSEMOTION:
			res.evType = SE_MOUSE;
			res.evValue = ev.motion.xrel;
			res.evValue2 = ev.motion.yrel;

			mouse_polls.Append(mouse_poll_t(M_DELTAX, ev.motion.xrel));
			mouse_polls.Append(mouse_poll_t(M_DELTAY, ev.motion.yrel));

			return res;

		case SDL_MOUSEWHEEL:
			res.evType = SE_KEY;

			if (ev.wheel.y > 0) {
				res.evValue = K_MWHEELUP;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
			} else {
				res.evValue = K_MWHEELDOWN;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
			}

			res.evValue2 = 1;

			return res;

		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			res.evType = SE_KEY;

			switch (ev.button.button) {
			case SDL_BUTTON_LEFT:
				res.evValue = K_MOUSE1;
				mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_MIDDLE:
				res.evValue = K_MOUSE3;
				mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_RIGHT:
				res.evValue = K_MOUSE2;
				mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;

			}

			res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;

			return res;

		case SDL_QUIT:
			PushConsoleEvent("quit");
			SDL_Quit();
			return res_none;

		case SDL_USEREVENT:
			switch (ev.user.code) {
			case SE_CONSOLE:
				res.evType = SE_CONSOLE;
				res.evPtrLength = (intptr_t)ev.user.data1;
				res.evPtr = ev.user.data2;
				return res;
			default:
				common->Warning("unknown user event %u", ev.user.code);
				return res_none;
			}
		default:
			common->Warning("unknown event %u", ev.type);
			return res_none;
		}
	}

	return res_none;
}
Beispiel #7
0
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent() {
	SDL_Event ev;
	sysEvent_t res = { };
	byte key;

	static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };

	// process any overflow.
	if (event_overflow.Num() > 0)
	{
		res = event_overflow[0];
		event_overflow.RemoveIndex(0);
		return res;
	}

	// overflow text input.
	static char *s = NULL;
	static size_t s_pos = 0;

	if (s) {
		res.evType = SE_CHAR;
		res.evValue = s[s_pos];

		s_pos++;
		if (!s[s_pos]) {
			free(s);
			s = NULL;
			s_pos = 0;
		}

		return res;
	}

	static byte c = 0;

	if (c) {
		res.evType = SE_CHAR;
		res.evValue = c;

		c = 0;

		return res;
	}

    bool getNext = true;
	while (SDL_PollEvent(&ev) && getNext) {
        getNext = false;
		switch (ev.type) {
#ifdef __WINDOWS__ // on windows we need to grab the hwnd.
		case SDL_SYSWMEVENT:
			if (win32.hWnd == NULL)
			{
				win32.hWnd = ev.syswm.msg->msg.win.hwnd;
			}
			getNext = true; // try to get a decent event.
			break;
#endif
		case SDL_WINDOWEVENT:
			switch (ev.window.event) {
				case SDL_WINDOWEVENT_FOCUS_GAINED: {
						// unset modifier, in case alt-tab was used to leave window and ALT is still set
						// as that can cause fullscreen-toggling when pressing enter...
						SDL_Keymod currentmod = SDL_GetModState();
					
						int newmod = KMOD_NONE;
						if (currentmod & KMOD_CAPS) // preserve capslock
							newmod |= KMOD_CAPS;

						SDL_SetModState((SDL_Keymod)newmod);
					} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST

					GLimp_GrabInput(GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR);
					break;
				case SDL_WINDOWEVENT_FOCUS_LOST:
					GLimp_GrabInput(0);
					break;
			}

			return res_none;

		case SDL_KEYDOWN:
			if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
				cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
				PushConsoleEvent("vid_restart");
				return res_none;
			}

			// fall through
		case SDL_KEYUP:
			key = mapkey(ev.key.keysym.sym);
			if(!key) {
				if (ev.key.keysym.scancode == SDL_SCANCODE_GRAVE) {
					key = Sys_GetConsoleKey(true);
				} else {
					if (ev.type == SDL_KEYDOWN) {
						common->Warning("unmapped SDL key %d", ev.key.keysym.sym);
            			getNext = true; // try to get a decent event.
						break;
					}

				}
			}

			res.evType = SE_KEY;
			res.evValue = key;
			res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;

			kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));

			if ( (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
				|| SDL_GetEventState(SDL_TEXTINPUT) == SDL_DISABLE)
				c = key;

			return res;

		case SDL_TEXTINPUT:
			if (ev.text.text && *ev.text.text) {

				res.evType = SE_CHAR;
				res.evValue = *ev.text.text;
				
				// if there are more characters hold onto them for later events.
				if (ev.text.text[1] != 0)
					s = strdup(ev.text.text+1);

				return res;
			}

			getNext = true; // try to get a decent event.
			break;

		case SDL_MOUSEMOTION:
			if (g_inputGrabbed)
			{
				res.evType = SE_MOUSE;

				res.evValue = ev.motion.xrel;
				res.evValue2 = ev.motion.yrel;

				mouse_polls.Append(mouse_poll_t(M_DELTAX, ev.motion.xrel));
				mouse_polls.Append(mouse_poll_t(M_DELTAY, ev.motion.yrel));
			
				return res;
			}

			getNext = true;
			break;

		case SDL_MOUSEWHEEL:
			if (g_inputGrabbed)
			{
				res.evType = SE_KEY;

				if (ev.wheel.y > 0) {
					res.evValue = K_MWHEELUP;
					mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
				} else {
					res.evValue = K_MWHEELDOWN;
					mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
				}

				res.evValue2 = 1;

				return res;
			}

			getNext = true;
			break;

		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			if (g_inputGrabbed)
			{
				res.evType = SE_KEY;

				switch (ev.button.button) {
				case SDL_BUTTON_LEFT:
					res.evValue = K_MOUSE1;
					mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
					break;
				case SDL_BUTTON_MIDDLE:
					res.evValue = K_MOUSE3;
					mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
					break;
				case SDL_BUTTON_RIGHT:
					res.evValue = K_MOUSE2;
					mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
					break;
				}

				res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;

				return res;
			}

			getNext = true;
			break;

		case SDL_CONTROLLERBUTTONDOWN:
		case SDL_CONTROLLERBUTTONUP:
			{
				sys_jEvents jEvent =  mapjoybutton( (SDL_GameControllerButton)ev.cbutton.button);
				joystick_polls.Append(joystick_poll_t(	jEvent,
														ev.cbutton.state == SDL_PRESSED ? 1 : 0) );

				res.evType = SE_KEY;
				res.evValue2 = ev.cbutton.state == SDL_PRESSED ? 1 : 0;
				if ( ( jEvent >= J_ACTION1 ) && ( jEvent <= J_ACTION_MAX ) ) {
					res.evValue = K_JOY1 + ( jEvent - J_ACTION1 );
					return res;
				} else if ( ( jEvent >= J_DPAD_UP ) && ( jEvent <= J_DPAD_RIGHT ) ) {
					res.evValue = K_JOY_DPAD_UP + ( jEvent - J_DPAD_UP );
					return res;
				}

				getNext = true; // try to get a decent event.
			}
			break;

		case SDL_CONTROLLERAXISMOTION:
			{
				const int range = 16384;

				sys_jEvents jEvent = mapjoyaxis( (SDL_GameControllerAxis)ev.caxis.axis);
				joystick_polls.Append(joystick_poll_t(	jEvent, ev.caxis.value) );

				if ( jEvent == J_AXIS_LEFT_X ) {
					PushButton( K_JOY_STICK1_LEFT, ( ev.caxis.value < -range ) );
					PushButton( K_JOY_STICK1_RIGHT, ( ev.caxis.value > range ) );
				} else if ( jEvent == J_AXIS_LEFT_Y ) {
					PushButton( K_JOY_STICK1_UP, ( ev.caxis.value < -range ) );
					PushButton( K_JOY_STICK1_DOWN, ( ev.caxis.value > range ) );
				} else if ( jEvent == J_AXIS_RIGHT_X ) {
					PushButton( K_JOY_STICK2_LEFT, ( ev.caxis.value < -range ) );
					PushButton( K_JOY_STICK2_RIGHT, ( ev.caxis.value > range ) );
				} else if ( jEvent == J_AXIS_RIGHT_Y ) {
					PushButton( K_JOY_STICK2_UP, ( ev.caxis.value < -range ) );
					PushButton( K_JOY_STICK2_DOWN, ( ev.caxis.value > range ) );
				} else if ( jEvent == J_AXIS_LEFT_TRIG ) {
					PushButton( K_JOY_TRIGGER1, ( ev.caxis.value > range ) );
				} else if ( jEvent == J_AXIS_RIGHT_TRIG ) {
					PushButton( K_JOY_TRIGGER2, ( ev.caxis.value > range ) );
				}
				if ( jEvent >= J_AXIS_MIN && jEvent <= J_AXIS_MAX ) {
					int axis = jEvent - J_AXIS_MIN;
					int percent = ( ev.caxis.value * 16 ) / range;
					if ( joyAxis[axis] != percent ) {
						joyAxis[axis] = percent;
						res.evType = SE_JOYSTICK;
						res.evValue = axis;
						res.evValue2 = percent;
						return res;
					}
				}

				getNext = true; // try to get a decent event.
			}
			break;

		case SDL_JOYDEVICEADDED:
			SDL_GameControllerOpen( ev.jdevice.which );
			// TODO: hot swapping maybe.
			//lbOnControllerPlugIn(event.jdevice.which);
			break;

		case SDL_JOYDEVICEREMOVED:
			// TODO: hot swapping maybe.
			//lbOnControllerUnPlug(event.jdevice.which);
			break;

		case SDL_QUIT:
			PushConsoleEvent("quit");
			return res_none;

		case SDL_USEREVENT:
			switch (ev.user.code) {
			case SE_CONSOLE:
				res.evType = SE_CONSOLE;
				res.evPtrLength = (intptr_t)ev.user.data1;
				res.evPtr = ev.user.data2;
				return res;
			default:
				common->Warning("unknown user event %u", ev.user.code);
            	getNext = true; // try to get a decent event.
            	break;
			}
		default:
            getNext = true; // try to get a decent event.
            break;
		}
	}

	return res_none;
}
Beispiel #8
0
/*
================
Sys_GetEvent
================
*/
sysEvent_t Sys_GetEvent() {
	SDL_Event ev;
	sysEvent_t res = { };
	byte key;

	static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };

	static char *s = NULL;
	static size_t s_pos = 0;

	if (s) {
		res.evType = SE_CHAR;
		res.evValue = s[s_pos];

		s_pos++;
		if (!s[s_pos]) {
			free(s);
			s = NULL;
			s_pos = 0;
		}

		return res;
	}

	static byte c = 0;

	if (c) {
		res.evType = SE_CHAR;
		res.evValue = c;

		c = 0;

		return res;
	}

	if (SDL_PollEvent(&ev)) {
		switch (ev.type) {
		case SDL_WINDOWEVENT:
			switch (ev.window.event) {
				case SDL_WINDOWEVENT_FOCUS_GAINED:
					{
						// unset modifier, in case alt-tab was used to leave window and ALT is still set
						// as that can cause fullscreen-toggling when pressing enter...
						SDL_Keymod currentmod = SDL_GetModState();
						int newmod = KMOD_NONE;
						if (currentmod & KMOD_CAPS) // preserve capslock
							newmod |= KMOD_CAPS;

						SDL_SetModState((SDL_Keymod)newmod);

						GLimp_GrabInput(GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR);
						break;
					}
				case SDL_WINDOWEVENT_FOCUS_LOST:
					GLimp_GrabInput(0);
					break;
			}

			return res_none;

		case SDL_KEYDOWN:
			if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
				cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
				PushConsoleEvent("vid_restart");
				return res_none;
			}

			// fall through
		case SDL_KEYUP:
			key = mapkey(ev.key.keysym.sym);

			if (!key) {
				unsigned char c;

				// check if its an unmapped console key
				if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(false))) {
					key = c;
				} else if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(true))) {
					key = c;
				} else {
					if (ev.type == SDL_KEYDOWN)
						common->Warning("unmapped SDL key %d (0x%x)", ev.key.keysym.sym, ev.key.keysym.unicode);
					return res_none;
				}
			}

			res.evType = SE_KEY;
			res.evValue = key;
			res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;

			kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));

			if (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
				c = key;

			return res;

		case SDL_TEXTINPUT:
			if (ev.text.text && *ev.text.text) {
				if (!ev.text.text[1])
					c = *ev.text.text;
				else
					s = strdup(ev.text.text);
			}

			return res_none;

		case SDL_MOUSEMOTION:
			res.evType = SE_MOUSE;
			res.evValue = ev.motion.xrel;
			res.evValue2 = ev.motion.yrel;

			mouse_polls.Append(mouse_poll_t(M_DELTAX, ev.motion.xrel));
			mouse_polls.Append(mouse_poll_t(M_DELTAY, ev.motion.yrel));

			return res;

		case SDL_MOUSEWHEEL:
			res.evType = SE_KEY;

			if (ev.wheel.y > 0) {
				res.evValue = K_MWHEELUP;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
			} else {
				res.evValue = K_MWHEELDOWN;
				mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
			}

			res.evValue2 = 1;

			return res;

		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			res.evType = SE_KEY;

			switch (ev.button.button) {
			case SDL_BUTTON_LEFT:
				res.evValue = K_MOUSE1;
				mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_MIDDLE:
				res.evValue = K_MOUSE3;
				mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;
			case SDL_BUTTON_RIGHT:
				res.evValue = K_MOUSE2;
				mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
				break;

			}

			res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;

			return res;

		case SDL_QUIT:
			PushConsoleEvent("quit");
			return res_none;

		case SDL_USEREVENT:
			switch (ev.user.code) {
			case SE_CONSOLE:
				res.evType = SE_CONSOLE;
				res.evPtrLength = (intptr_t)ev.user.data1;
				res.evPtr = ev.user.data2;
				return res;
			default:
				common->Warning("unknown user event %u", ev.user.code);
				return res_none;
			}
		default:
			common->Warning("unknown event %u", ev.type);
			return res_none;
		}
	}

	return res_none;
}