mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-28 14:53:16 +00:00
272abade38
GL, and I still don't know exactly why.
491 lines
8.5 KiB
C
491 lines
8.5 KiB
C
/*
|
|
in_ggi.c
|
|
|
|
Input handling for ggi renderer.
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
Copyright (C) 1999 Marcus Sundberg [mackan@stacken.kth.se]
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
$Id$
|
|
*/
|
|
|
|
#define _BSD
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#ifdef HAVE_STRINGS_H
|
|
# include <strings.h>
|
|
#endif
|
|
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ggi/ggi.h>
|
|
|
|
#include "cl_input.h"
|
|
#include "client.h"
|
|
#include "cmd.h"
|
|
#include "console.h"
|
|
#include "cvar.h"
|
|
#include "host.h"
|
|
#include "input.h"
|
|
#include "joystick.h"
|
|
#include "keys.h"
|
|
#include "qargs.h"
|
|
#include "sys.h"
|
|
#include "view.h"
|
|
|
|
cvar_t *m_filter;
|
|
cvar_t *_windowed_mouse;
|
|
|
|
#define NUM_STDBUTTONS 3
|
|
#define NUM_BUTTONS 10
|
|
|
|
static qboolean mouse_avail;
|
|
static float mouse_x, mouse_y;
|
|
static float old_mouse_x, old_mouse_y;
|
|
static int p_mouse_x, p_mouse_y;
|
|
static float old_windowed_mouse;
|
|
|
|
static ggi_visual_t ggivis = NULL;
|
|
|
|
|
|
static int
|
|
XLateKey (ggi_key_event * ev)
|
|
{
|
|
int key = 0;
|
|
|
|
if (GII_KTYP (ev->label) == GII_KT_DEAD) {
|
|
ev->label = GII_KVAL (ev->label);
|
|
}
|
|
switch (ev->label) {
|
|
case GIIK_P9:
|
|
key = KP_PGUP;
|
|
break;
|
|
case GIIK_PageUp:
|
|
key = K_PGUP;
|
|
break;
|
|
|
|
case GIIK_P3:
|
|
key = KP_PGDN;
|
|
break;
|
|
case GIIK_PageDown:
|
|
key = K_PGDN;
|
|
break;
|
|
|
|
case GIIK_P7:
|
|
key = KP_HOME;
|
|
break;
|
|
case GIIK_Home:
|
|
key = K_HOME;
|
|
break;
|
|
|
|
case GIIK_P1:
|
|
key = KP_END;
|
|
break;
|
|
case GIIK_End:
|
|
key = K_END;
|
|
break;
|
|
|
|
case GIIK_P4:
|
|
key = KP_LEFTARROW;
|
|
break;
|
|
case GIIK_Left:
|
|
key = K_LEFTARROW;
|
|
break;
|
|
|
|
case GIIK_P6:
|
|
key = KP_RIGHTARROW;
|
|
break;
|
|
case GIIK_Right:
|
|
key = K_RIGHTARROW;
|
|
break;
|
|
|
|
case GIIK_P2:
|
|
key = KP_DOWNARROW;
|
|
break;
|
|
case GIIK_Down:
|
|
key = K_DOWNARROW;
|
|
break;
|
|
|
|
case GIIK_P8:
|
|
key = KP_UPARROW;
|
|
break;
|
|
case GIIK_Up:
|
|
key = K_UPARROW;
|
|
break;
|
|
|
|
case GIIK_P5:
|
|
key = KP_5;
|
|
break;
|
|
case GIIK_PBegin:
|
|
key = K_AUX32;
|
|
break;
|
|
|
|
case GIIK_P0:
|
|
key = KP_INS;
|
|
break;
|
|
case GIIK_Insert:
|
|
key = K_INS;
|
|
break;
|
|
|
|
case GIIK_PSeparator:
|
|
case GIIK_PDecimal:
|
|
key = KP_DEL;
|
|
break;
|
|
case GIIUC_Delete:
|
|
key = K_DEL;
|
|
break;
|
|
|
|
case GIIK_PStar:
|
|
key = KP_MULTIPLY;
|
|
break;
|
|
case GIIK_PPlus:
|
|
key = KP_PLUS;
|
|
break;
|
|
case GIIK_PMinus:
|
|
key = KP_MINUS;
|
|
break;
|
|
case GIIK_PSlash:
|
|
key = KP_DIVIDE;
|
|
break;
|
|
|
|
case GIIK_PEnter:
|
|
key = KP_ENTER;
|
|
break;
|
|
case GIIUC_Return:
|
|
key = K_ENTER;
|
|
break;
|
|
|
|
case GIIUC_Escape:
|
|
key = K_ESCAPE;
|
|
break;
|
|
|
|
case GIIUC_Tab:
|
|
key = K_TAB;
|
|
break;
|
|
|
|
case GIIK_F1:
|
|
key = K_F1;
|
|
break;
|
|
case GIIK_F2:
|
|
key = K_F2;
|
|
break;
|
|
case GIIK_F3:
|
|
key = K_F3;
|
|
break;
|
|
case GIIK_F4:
|
|
key = K_F4;
|
|
break;
|
|
case GIIK_F5:
|
|
key = K_F5;
|
|
break;
|
|
case GIIK_F6:
|
|
key = K_F6;
|
|
break;
|
|
case GIIK_F7:
|
|
key = K_F7;
|
|
break;
|
|
case GIIK_F8:
|
|
key = K_F8;
|
|
break;
|
|
case GIIK_F9:
|
|
key = K_F9;
|
|
break;
|
|
case GIIK_F10:
|
|
key = K_F10;
|
|
break;
|
|
case GIIK_F11:
|
|
key = K_F11;
|
|
break;
|
|
case GIIK_F12:
|
|
key = K_F12;
|
|
break;
|
|
|
|
case GIIUC_BackSpace:
|
|
key = K_BACKSPACE;
|
|
break;
|
|
|
|
case GIIK_ShiftL:
|
|
case GIIK_ShiftR:
|
|
key = K_SHIFT;
|
|
break;
|
|
|
|
case GIIK_Execute:
|
|
case GIIK_CtrlL:
|
|
case GIIK_CtrlR:
|
|
key = K_CTRL;
|
|
break;
|
|
|
|
case GIIK_AltL:
|
|
case GIIK_MetaL:
|
|
case GIIK_AltR:
|
|
case GIIK_MetaR:
|
|
case GIIK_AltGr:
|
|
case GIIK_ModeSwitch:
|
|
key = K_ALT;
|
|
break;
|
|
|
|
case GIIK_Caps:
|
|
key = K_CAPSLOCK;
|
|
break;
|
|
case GIIK_PrintScreen:
|
|
key = K_PRNTSCR;
|
|
break;
|
|
case GIIK_ScrollLock:
|
|
key = K_SCRLCK;
|
|
break;
|
|
case GIIK_Pause:
|
|
key = K_PAUSE;
|
|
break;
|
|
case GIIK_NumLock:
|
|
key = KP_NUMLCK;
|
|
break;
|
|
|
|
case GIIUC_Comma:
|
|
case GIIUC_Minus:
|
|
case GIIUC_Period:
|
|
key = ev->label;
|
|
break;
|
|
case GIIUC_Section:
|
|
key = '~';
|
|
break;
|
|
|
|
default:
|
|
if (ev->label >= 0 && ev->label <= 9)
|
|
return ev->label;
|
|
if (ev->label >= 'A' && ev->label <= 'Z') {
|
|
return ev->label - 'A' + 'a';
|
|
}
|
|
if (ev->label >= 'a' && ev->label <= 'z')
|
|
return ev->label;
|
|
|
|
if (ev->sym <= 0x7f) {
|
|
key = ev->sym;
|
|
if (key >= 'A' && key <= 'Z') {
|
|
key = key - 'A' + 'a';
|
|
}
|
|
return key;
|
|
}
|
|
if (ev->label <= 0x7f) {
|
|
return ev->label;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
static void
|
|
GetEvent (void)
|
|
{
|
|
ggi_event ev;
|
|
uint32 b;
|
|
|
|
ggiEventRead (ggivis, &ev, emAll);
|
|
switch (ev.any.type) {
|
|
case evKeyPress:
|
|
Key_Event (XLateKey (&ev.key), 0, true);
|
|
break;
|
|
|
|
case evKeyRelease:
|
|
Key_Event (XLateKey (&ev.key), 0, false);
|
|
break;
|
|
|
|
case evPtrRelative:
|
|
mouse_x += (float) ev.pmove.x;
|
|
mouse_y += (float) ev.pmove.y;
|
|
break;
|
|
|
|
case evPtrAbsolute:
|
|
mouse_x += (float) (ev.pmove.x - p_mouse_x);
|
|
mouse_y += (float) (ev.pmove.y - p_mouse_y);
|
|
p_mouse_x = ev.pmove.x;
|
|
p_mouse_y = ev.pmove.y;
|
|
break;
|
|
|
|
case evPtrButtonPress:
|
|
if (!mouse_avail)
|
|
return;
|
|
|
|
b = ev.pbutton.button - 1;
|
|
|
|
if (b < NUM_STDBUTTONS) {
|
|
Key_Event (K_MOUSE1 + b, 0, true);
|
|
} else if (b < NUM_STDBUTTONS + 2) {
|
|
b -= 3;
|
|
if (b)
|
|
Key_Event (K_MWHEELDOWN, 0, true);
|
|
else
|
|
Key_Event (K_MWHEELUP, 0, true);
|
|
} else if (b < NUM_BUTTONS) {
|
|
Key_Event (K_AUX32 - NUM_BUTTONS + b, 0, true);
|
|
}
|
|
break;
|
|
|
|
case evPtrButtonRelease:
|
|
if (!mouse_avail)
|
|
return;
|
|
|
|
b = ev.pbutton.button - 1;
|
|
|
|
if (b < NUM_STDBUTTONS) {
|
|
Key_Event (K_MOUSE1 + b, 0, false);
|
|
} else if (b < NUM_STDBUTTONS + 2) {
|
|
b -= 3;
|
|
if (b)
|
|
Key_Event (K_MWHEELDOWN, 0, false);
|
|
else
|
|
Key_Event (K_MWHEELUP, 0, false);
|
|
} else if (b < NUM_BUTTONS) {
|
|
Key_Event (K_AUX32 - NUM_BUTTONS + b, 0, false);
|
|
}
|
|
break;
|
|
|
|
#if 0
|
|
case ConfigureNotify:
|
|
//printf("config notify\n");
|
|
config_notify_width = ev.xconfigure.width;
|
|
config_notify_height = ev.xconfigure.height;
|
|
config_notify = 1;
|
|
break;
|
|
|
|
default:
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
IN_SendKeyEvents (void)
|
|
{
|
|
/* Get events from LibGGI */
|
|
if (ggivis) {
|
|
struct timeval t = { 0, 0 };
|
|
|
|
if (ggiEventPoll (ggivis, emAll, &t)) {
|
|
int i = ggiEventsQueued (ggivis, emAll);
|
|
|
|
while (i--)
|
|
GetEvent ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
IN_Init (void)
|
|
{
|
|
JOY_Init ();
|
|
|
|
old_windowed_mouse = -1; /* Force update */
|
|
if (COM_CheckParm ("-nomouse"))
|
|
return;
|
|
|
|
mouse_x = mouse_y = 0.0;
|
|
mouse_avail = 1;
|
|
}
|
|
|
|
void
|
|
IN_Init_Cvars (void)
|
|
{
|
|
JOY_Init_Cvars ();
|
|
|
|
_windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, "Have Quake grab the mouse from X when you play");
|
|
m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, "Mouse input filtering");
|
|
}
|
|
|
|
|
|
void
|
|
IN_Shutdown (void)
|
|
{
|
|
JOY_Shutdown ();
|
|
|
|
Con_Printf ("IN_Shutdown\n");
|
|
mouse_avail = 0;
|
|
}
|
|
|
|
|
|
void
|
|
IN_Commands (void)
|
|
{
|
|
JOY_Command ();
|
|
|
|
/* Only supported by LibGII 0.7 or later. */
|
|
#ifdef GII_CMDCODE_PREFER_RELPTR
|
|
if (old_windowed_mouse != _windowed_mouse->int_val) {
|
|
gii_event ev;
|
|
|
|
old_windowed_mouse = _windowed_mouse->int_val;
|
|
|
|
ev.cmd.size = sizeof (gii_cmd_nodata_event);
|
|
ev.cmd.type = evCommand;
|
|
ev.cmd.target = GII_EV_TARGET_ALL;
|
|
ev.cmd.code = _windowed_mouse->int_val ? GII_CMDCODE_PREFER_RELPTR
|
|
: GII_CMDCODE_PREFER_ABSPTR;
|
|
|
|
ggiEventSend (ggivis, &ev);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
IN_Move (usercmd_t *cmd)
|
|
{
|
|
JOY_Move (cmd);
|
|
|
|
if (!mouse_avail)
|
|
return;
|
|
|
|
if (m_filter->int_val) {
|
|
mouse_x = (mouse_x + old_mouse_x) * 0.5;
|
|
mouse_y = (mouse_y + old_mouse_y) * 0.5;
|
|
}
|
|
|
|
old_mouse_x = mouse_x;
|
|
old_mouse_y = mouse_y;
|
|
|
|
mouse_x *= sensitivity->value;
|
|
mouse_y *= sensitivity->value;
|
|
|
|
if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook))
|
|
cmd->sidemove += m_side->value * mouse_x;
|
|
else
|
|
cl.viewangles[YAW] -= m_yaw->value * mouse_x;
|
|
if (freelook)
|
|
V_StopPitchDrift ();
|
|
|
|
if (freelook && !(in_strafe.state & 1)) {
|
|
cl.viewangles[PITCH] += m_pitch->value * mouse_y;
|
|
cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80);
|
|
} else {
|
|
if ((in_strafe.state & 1) && noclip_anglehack)
|
|
cmd->upmove -= m_forward->value * mouse_y;
|
|
else
|
|
cmd->forwardmove -= m_forward->value * mouse_y;
|
|
}
|
|
mouse_x = mouse_y = 0.0;
|
|
}
|