[input] Create QF input library using keys.c

This refactors (as such) keys.c so that it no longer depends on console
or gib, and pulls keys out of video targets. The eventual plan is to
move all high-level general input handling into libQFinput, and probably
low-level (eg, /dev/input handling for joysticks etc on Linux).

Fixes #8
This commit is contained in:
Bill Currie 2021-07-05 16:26:07 +09:00
parent ddc6f6bcb0
commit e81d690b51
26 changed files with 197 additions and 109 deletions

View file

@ -97,7 +97,6 @@ void Con_Init (const char *plugin_name);
void Con_ExecLine (const char *line);
void Con_ProcessInput (void);
void Con_KeyEvent (knum_t key, short unicode, qboolean down);
void Con_SetOrMask (int mask);
void Con_NewMap (void);

View file

@ -564,6 +564,31 @@ typedef struct keytarget_s {
extern int keydown[QFK_LAST];
/** Callback for handling key events based on keydest.
\param key The key that was pressed or released for this event.
\param unicode The unicode value of the key.
\param down True if a press event, false if a release event.
\param data Callback specific data pointer as passed to Key_SetKeyDest
*/
typedef void (*key_event_t) (knum_t key, short unicode, qboolean down,
void *data);
/** Set the fallback key event handler callback for the specified keydest.
The fallback is for handling keys that have not been bound, thus allowing
the callback to handle large numbers of keys without having to create many
explicit bindings (eg, console input).
If no callback has been set for a specific keydest, then the key event
is simply ignored.
\param keydest The keydest for which the callback will be set.
\param callback The function to be called when an event occurs.
\param data Opaque data pointerer passed to the callback.
*/
void Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data);
struct cbuf_s;
void Key_Init (struct cbuf_s *cb);
@ -693,11 +718,15 @@ int Key_StringToKeynum (const char *str) __attribute__((pure));
struct progs_s;
//FIXME location
/** Add the Key builtins to the specified progs instance.
*/
void Key_Progs_Init (struct progs_s *pr);
void RUA_Key_Init (struct progs_s *pr);
#endif
//FIXME location
void GIB_Key_Init (void);
///@}
#endif//__QF_keys_h

View file

@ -30,7 +30,6 @@
#include <stdarg.h>
#include <QF/keys.h>
#include <QF/plugin.h>
#include <QF/qtypes.h>
@ -38,7 +37,6 @@ typedef struct console_funcs_s {
void (*init) (void);
void (*print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0)));
void (*process_input) (void);
void (*key_event) (knum_t key, short unicode, qboolean down);
void (*draw_console) (void);
void (*check_resize) (void);
void (*new_map) (void);

View file

@ -6,6 +6,7 @@ include libs/gib/Makemodule.am
include libs/audio/Makemodule.am
include libs/image/Makemodule.am
include libs/models/Makemodule.am
include libs/input/Makemodule.am
include libs/video/Makemodule.am
include libs/console/Makemodule.am
include libs/entity/Makemodule.am

View file

@ -445,7 +445,7 @@ C_Print (const char *fmt, va_list args)
}
static void
C_KeyEvent (knum_t key, short unicode, qboolean down)
C_KeyEvent (knum_t key, short unicode, qboolean down, void *data)
{
inputline_t *il;
@ -821,6 +821,9 @@ C_Init (void)
#endif
Key_KeydestCallback (con_keydest_callback);
Key_SetKeyEvent (key_message, C_KeyEvent, 0);
Key_SetKeyEvent (key_menu, C_KeyEvent, 0);
Key_SetKeyEvent (key_console, C_KeyEvent, 0);
Menu_Init ();
con_notifytime = Cvar_Get ("con_notifytime", "3", CVAR_NONE, NULL,
@ -946,7 +949,6 @@ static general_funcs_t plugin_info_general_funcs = {
static console_funcs_t plugin_info_console_funcs = {
.print = C_Print,
.process_input = C_ProcessInput,
.key_event = C_KeyEvent,
.draw_console = C_DrawConsole,
.check_resize = C_CheckResize,
.new_map = C_NewMap,

View file

@ -172,13 +172,6 @@ Con_ProcessInput (void)
}
}
VISIBLE void
Con_KeyEvent (knum_t key, short unicode, qboolean down)
{
if (con_module)
con_module->functions->console->key_event (key, unicode, down);
}
VISIBLE void
Con_SetOrMask (int mask)
{

View file

@ -587,7 +587,7 @@ Menu_Init (void)
RUA_Init (&menu_pr_state, 1);
InputLine_Progs_Init (&menu_pr_state);
Key_Progs_Init (&menu_pr_state);
RUA_Key_Init (&menu_pr_state);
GIB_Progs_Init (&menu_pr_state);
PR_Cmds_Init (&menu_pr_state);
R_Progs_Init (&menu_pr_state);

View file

@ -793,7 +793,6 @@ static general_data_t plugin_info_general_data;
static console_funcs_t plugin_info_console_funcs = {
.print = C_Print,
.process_input = C_ProcessInput,
.key_event = C_KeyEvent,
.draw_console = C_DrawConsole,
.check_resize = C_CheckResize,
.new_map = C_NewMap,

View file

@ -2,7 +2,9 @@ gib_deps= \
libs/ruamoko/libQFruamoko.la \
libs/util/libQFutil.la
lib_LTLIBRARIES += libs/gib/libQFgib.la
lib_LTLIBRARIES += \
libs/gib/libQFgib.la \
libs/gib/libQFgib_client.la
libs_gib_libQFgib_la_LDFLAGS= $(lib_ldflags)
libs_gib_libQFgib_la_LIBADD= $(gib_deps)
@ -27,3 +29,9 @@ libs_gib_libQFgib_la_SOURCES= \
libs/gib/ops.c \
libs/gib/exp.c \
libs/gib/regex.c
libs_gib_libQFgib_client_la_LDFLAGS= $(lib_ldflags)
libs_gib_libQFgib_client_la_LIBADD= libs/gib/libQFgib.la
libs_gib_libQFgib_client_la_DEPENDENCIES= libs/gib/libQFgib.la ${gib_deps}
libs_gib_libQFgib_client_la_SOURCES= \
libs/gib/gib_keys.c

77
libs/gib/gib_keys.c Normal file
View file

@ -0,0 +1,77 @@
/*
gib_keys.c
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2002 Brian Koropoff <brianhk@cs.washington.edu>
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
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
*/
#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 "QF/cbuf.h"
#include "QF/cmd.h"
#include "QF/keys.h"
#include "QF/sys.h"
#include "QF/gib.h"
#include "compat.h"
#include "old_keys.h"
static void
Key_GIB_Bind_Get_f (void)
{
const char *key, *cmd;
imt_t *imt;
int k;
if (GIB_Argc () != 2) {
GIB_USAGE ("key");
return;
}
key = OK_TranslateKeyName (GIB_Argv (1));
if ((k = Key_StringToKeynum (key)) == -1) {
GIB_Error ("bind", "bind::get: invalid key %s", key);
return;
}
imt = Key_FindIMT ("imt_mod");
if (!imt || !(cmd = Key_GetBinding (imt, k)))
GIB_Return ("");
else
GIB_Return (cmd);
}
void
GIB_Key_Init (void)
{
GIB_Builtin_Add ("bind::get", Key_GIB_Bind_Get_f);
}

8
libs/input/Makemodule.am Normal file
View file

@ -0,0 +1,8 @@
lib_LTLIBRARIES += libs/input/libQFinput.la
libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags)
libs_input_libQFinput_la_LIBADD= $(input_deps)
libs_input_libQFinput_la_DEPENDENCIES= $(input_deps)
libs_input_libQFinput_la_SOURCES= \
libs/input/keys.c \
libs/input/old_keys.c

View file

@ -41,22 +41,14 @@
#include "QF/cbuf.h"
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/csqc.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/keys.h"
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/gib.h"
#include "compat.h"
#include "old_keys.h"
#define U __attribute__ ((used))
static U void (*const key_progs_init)(struct progs_s *) = Key_Progs_Init;
#undef U
/* key up events are sent even if in console mode */
static keydest_t key_dest = key_console;
@ -669,21 +661,6 @@ Key_Game (knum_t key, short unicode)
return false;
}
/*
Key_Console
Interactive line editing and console scrollback
*/
static void
Key_Console (knum_t key, short unicode)
{
// escape is un-bindable
if (keydown[key] == 1 && key && Key_Game (key, unicode))
return;
Con_KeyEvent (key, unicode, keydown[key]);
}
VISIBLE int
Key_StringToKeynum (const char *str)
{
@ -957,32 +934,6 @@ Key_Bind_f (void)
}
}
static void
Key_GIB_Bind_Get_f (void)
{
const char *key, *cmd;
imt_t *imt;
int k;
if (GIB_Argc () != 2) {
GIB_USAGE ("key");
return;
}
key = OK_TranslateKeyName (GIB_Argv (1));
if ((k = Key_StringToKeynum (key)) == -1) {
GIB_Error ("bind", "bind::get: invalid key %s", key);
return;
}
imt = Key_FindIMT ("imt_mod");
if (!imt || !(cmd = Key_GetBinding (imt, k)))
GIB_Return ("");
else
GIB_Return (cmd);
}
static void
in_key_togglemenu_f (cvar_t *var)
{
@ -1165,6 +1116,19 @@ keyhelp_f (void)
keyhelp = 1;
}
static key_event_t key_event_handlers[key_last] = { };
static void *key_event_data[key_last] = { };
VISIBLE void
Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data)
{
if (keydest < 0 || keydest >= key_last) {
Sys_Error ("Key_SetKeyEvent: invalid keydest: %d", keydest);
}
key_event_handlers[keydest] = callback;
key_event_data[keydest] = data;
}
/*
Key_Event
@ -1188,32 +1152,29 @@ Key_Event (knum_t key, short unicode, qboolean down)
keydown[key] = 0;
}
// handle escape specially, so the user can never unbind it
if (key == key_togglemenu || key == key_toggleconsole) {
Key_Console (key, unicode);
// handle menu and console toggle keys specially so the user can never
// override or unbind them
//FIXME maybe still a tad over-coupled. Use callbacks for menu and console
//toggles? Should keys know anything about menu and console?
if (key_dest != key_menu && key == key_togglemenu && keydown[key] == 1) {
Cbuf_AddText (cbuf, "togglemenu");
return;
} else if (key_dest != key_console && key == key_toggleconsole
&& keydown[key] == 1) {
Cbuf_AddText (cbuf, "toggleconsole");
return;
}
if (!down && Key_Game (key, unicode))
return;
// if not a consolekey, send to the interpreter no matter what mode is
switch (key_dest) {
case key_game:
case key_demo:
Key_Game (key, unicode);
return;
case key_message:
case key_menu:
case key_console:
Key_Console (key, unicode);
return;
case key_unfocused:
return;
case key_last:
break; // should not happen, so hit the error
if (key_dest < 0 || key_dest >= key_last) {
Sys_Error ("Bad key_dest");
}
if (!Key_Game (key, unicode)) {
if (key_event_handlers[key_dest]) {
key_event_handlers[key_dest] (key, unicode, down,
key_event_data[key_dest]);
}
}
Sys_Error ("Bad key_dest");
}
VISIBLE void
@ -1344,9 +1305,6 @@ Key_Init (cbuf_t *cb)
Cmd_AddCommand ("keyhelp", keyhelp_f, "display the keyname for the next "
"RECOGNIZED key-press. If the key pressed produces no "
"output, " PACKAGE_NAME " does not recognise that key.");
GIB_Builtin_Add ("bind::get", Key_GIB_Bind_Get_f);
}
void
@ -1371,7 +1329,7 @@ Key_GetBinding (imt_t *imt, knum_t key)
VISIBLE void
Key_SetKeyDest(keydest_t kd)
{
if ((int) kd < key_unfocused || kd >= key_last) {
if (kd < 0 || kd >= key_last) {
Sys_Error ("Bad key_dest: %d", kd);
}
Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]);

View file

@ -2,7 +2,9 @@ ruamoko_rua_libs= \
libs/gamecode/libQFgamecode.la \
libs/util/libQFutil.la
lib_LTLIBRARIES += libs/ruamoko/libQFruamoko.la
lib_LTLIBRARIES += \
libs/ruamoko/libQFruamoko.la \
libs/ruamoko/libQFruamoko_client.la
libs_ruamoko_libQFruamoko_la_LDFLAGS= $(lib_ldflags)
libs_ruamoko_libQFruamoko_la_LIBADD= $(ruamoko_rua_libs)
@ -25,3 +27,12 @@ libs_ruamoko_libQFruamoko_la_SOURCES= \
libs/ruamoko/rua_set.c \
libs/ruamoko/rua_stdlib.c \
libs/ruamoko/rua_string.c
libs_ruamoko_libQFruamoko_client_la_LDFLAGS= $(lib_ldflags)
libs_ruamoko_libQFruamoko_client_la_LIBADD= \
libs/ruamoko/libQFruamoko.la
libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \
libs/ruamoko/libQFruamoko.la \
$(ruamoko_rua_libs)
libs_ruamoko_libQFruamoko_client_la_SOURCES= \
libs/ruamoko/rua_keys.c

View file

@ -1,7 +1,7 @@
/*
bi_keys.c
rua_keys.c
CSQC key-api builtins
Ruamoko key-api builtins
Copyright (C) 1996-1997 Id Software, Inc.
@ -168,7 +168,7 @@ static builtin_t builtins[] = {
};
void
Key_Progs_Init (progs_t *pr)
RUA_Key_Init (progs_t *pr)
{
PR_RegisterBuiltins (pr, builtins);
}

View file

@ -31,7 +31,6 @@
#include <stdlib.h>
#include <math.h>
#include "QF/console.h"
#include "QF/mathlib.h"
#include "QF/sys.h"
#include "QF/vid.h"

View file

@ -28,7 +28,6 @@
# include "config.h"
#endif
#include "QF/console.h"
#include "QF/cvar.h"
#include "QF/mathlib.h"
#include "QF/qargs.h"

View file

@ -58,9 +58,6 @@ EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(j
libs_video_targets_libvid_common_la_SOURCES = \
libs/video/targets/in_common.c \
libs/video/targets/in_event.c \
libs/video/targets/keys.c \
libs/video/targets/old_keys.c \
libs/video/targets/pr_keys.c \
libs/video/targets/vid.c
libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@
libs_video_targets_libvid_common_la_LDFLAGS= @STATIC@

View file

@ -45,6 +45,8 @@ nq_cl_plugin_LIBS= \
@client_static_plugin_libs@
nq_client_LIBFILES= \
libs/gib/libQFgib_client.la \
libs/ruamoko/libQFruamoko_client.la \
libs/entity/libQFentity.la \
libs/video/targets/libQFjs.la \
libs/audio/libQFcd.la \
@ -62,6 +64,7 @@ nq_common_LIBFILES= \
libs/ruamoko/libQFruamoko.la \
libs/gamecode/libQFgamecode.la \
libs/ui/libQFui.la \
libs/input/libQFinput.la \
libs/util/libQFutil.la
nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES)

View file

@ -864,6 +864,7 @@ Host_Init (void)
Sys_Init ();
GIB_Init (true);
GIB_Key_Init ();
COM_ParseConfig (host_cbuf);
Host_Init_Memory ();

View file

@ -53,6 +53,11 @@ int viewentity;
vid_render_data_t *r_data;
vid_render_funcs_t *r_funcs;
void
GIB_Key_Init (void)
{
}
void
Key_KeydestCallback (keydest_callback_t *callback)
{

View file

@ -87,6 +87,8 @@ qw_cl_plugin_LIBS= \
qw_client_LIBS= \
libs/qw/libqw.a \
libs/gib/libQFgib_client.la \
libs/ruamoko/libQFruamoko_client.la \
libs/net/libnet_chan.la \
libs/entity/libQFentity.la \
libs/console/libQFconsole.la \
@ -97,6 +99,7 @@ qw_client_LIBS= \
libs/gib/libQFgib.la \
libs/ruamoko/libQFruamoko.la \
libs/ui/libQFui.la \
libs/input/libQFinput.la \
libs/util/libQFutil.la
qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \
libs/client/libQFclient.la

View file

@ -1771,6 +1771,7 @@ Host_Init (void)
Sys_Init ();
GIB_Init (true);
GIB_Key_Init ();
COM_ParseConfig (cl_cbuf);
CL_Init_Memory ();

View file

@ -42,12 +42,9 @@ qwaq_app_dat_src= \
ruamoko/qwaq/ui/view.r \
ruamoko/qwaq/ui/window.r
#FIXME this coupling is horrible
qwaq_curses_libs= \
libs/video/targets/libvid_common.la \
libs/console/libQFconsole.la \
libs/ui/libQFui.la \
libs/gib/libQFgib.la
libs/input/libQFinput.la
ruamoko_qwaq_qwaq_curses_SOURCES= \
ruamoko/qwaq/builtins/main.c \
@ -68,6 +65,7 @@ qwaq_client_libs= \
$(top_builddir)/libs/entity/libQFentity.la \
$(top_builddir)/libs/console/libQFconsole.la \
$(top_builddir)/libs/ui/libQFui.la \
$(top_builddir)/libs/input/libQFinput.la \
$(top_builddir)/libs/video/targets/libQFjs.la \
$(top_builddir)/libs/audio/libQFcd.la \
$(top_builddir)/libs/audio/libQFsound.la \
@ -75,11 +73,11 @@ qwaq_client_libs= \
qwaq_x11_libs= \
$(qwaq_cl_plugin_libs) \
${top_builddir}/libs/ruamoko/libQFruamoko_client.la \
$(top_builddir)/libs/video/renderer/libQFrenderer.la \
$(top_builddir)/libs/models/libQFmodels.la \
$(top_builddir)/libs/video/targets/libQFx11.la \
$(qwaq_client_libs) \
$(top_builddir)/libs/gib/libQFgib.la
$(qwaq_client_libs)
ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c
ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \
$(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \

View file

@ -386,7 +386,6 @@ common_builtins_init (progs_t *pr)
}
static progsinit_f main_app[] = {
Key_Progs_Init,
BI_Init,
common_builtins_init,
QWAQ_EditBuffer_Init,

View file

@ -195,7 +195,7 @@ BI_Init (progs_t *pr)
Mod_Init ();
R_Init ();
R_Progs_Init (pr);
Key_Progs_Init (pr);
RUA_Key_Init (pr);
S_Progs_Init (pr);
Con_Init ("client");