add input device events
as a new subsystem that must be explicitly enabled/disabled
This commit is contained in:
parent
9f568987d0
commit
ab9fe0cb9a
3
DGL.C
3
DGL.C
|
@ -45,6 +45,8 @@ const char* dgl_last_error_message(void) {
|
|||
return "Failed to set mouse interrupt handler callback.";
|
||||
case DGL_MOUSE_INT_CALLBACK_RESTORE_FAILURE:
|
||||
return "Failed to restore original mouse interrupt handler callback.";
|
||||
case DGL_EVENTS_ALREADY_INITIALIZED:
|
||||
return "Input device events subsystem is already initialized.";
|
||||
case DGL_IO_ERROR:
|
||||
return "File IO error.";
|
||||
case DGL_PCX_BAD_FORMAT:
|
||||
|
@ -59,6 +61,7 @@ void dgl_set_error(DGL_ERROR error) {
|
|||
}
|
||||
|
||||
void _dgl_atexit(void) {
|
||||
events_shutdown();
|
||||
mouse_shutdown();
|
||||
keyboard_shutdown();
|
||||
video_shutdown();
|
||||
|
|
1
DGL.H
1
DGL.H
|
@ -18,6 +18,7 @@
|
|||
#include "dglmtx33.h"
|
||||
#include "dglutil.h"
|
||||
#include "dglpcx.h"
|
||||
#include "dglevent.h"
|
||||
|
||||
void dgl_init(void);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef enum {
|
|||
DGL_MOUSE_FREE_CALLBACK_FAILURE,
|
||||
DGL_MOUSE_INT_CALLBACK_SET_FAILURE,
|
||||
DGL_MOUSE_INT_CALLBACK_RESTORE_FAILURE,
|
||||
DGL_EVENTS_ALREADY_INITIALIZED,
|
||||
DGL_IO_ERROR,
|
||||
DGL_PCX_BAD_FORMAT
|
||||
} DGL_ERROR;
|
||||
|
|
69
DGLEVENT.C
Normal file
69
DGLEVENT.C
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "dglevent.h"
|
||||
#include "dglerror.h"
|
||||
#include "dglutil.h"
|
||||
#include <string.h>
|
||||
|
||||
volatile boolean _events_enabled;
|
||||
|
||||
volatile INPUTEVENT _events_buffer[EVENTS_BUFFER_SIZE];
|
||||
volatile int _events_buffer_start = 0;
|
||||
volatile int _events_buffer_end = 0;
|
||||
|
||||
boolean events_init(void) {
|
||||
if (_events_enabled) {
|
||||
dgl_set_error(DGL_EVENTS_ALREADY_INITIALIZED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
events_clear();
|
||||
_events_enabled = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
boolean events_shutdown(void) {
|
||||
if (!_events_enabled)
|
||||
return TRUE; // don't care
|
||||
|
||||
_events_enabled = FALSE;
|
||||
events_clear();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
boolean events_poll(INPUTEVENT **event) {
|
||||
if (events_is_empty())
|
||||
return FALSE;
|
||||
|
||||
int_disable();
|
||||
|
||||
*event = &_events_buffer[_events_buffer_start];
|
||||
|
||||
++_events_buffer_start;
|
||||
if (_events_buffer_start >= EVENTS_BUFFER_SIZE)
|
||||
_events_buffer_start = 0;
|
||||
|
||||
int_enable();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
boolean events_peek(INPUTEVENT **event) {
|
||||
if (events_is_empty())
|
||||
return FALSE;
|
||||
|
||||
*event = &_events_buffer[_events_buffer_start];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void events_clear(void) {
|
||||
int_disable();
|
||||
|
||||
memset(_events_buffer, 0, sizeof(_events_buffer));
|
||||
_events_buffer_start = 0;
|
||||
_events_buffer_end = 0;
|
||||
|
||||
int_enable();
|
||||
}
|
||||
|
102
DGLEVENT.H
Normal file
102
DGLEVENT.H
Normal file
|
@ -0,0 +1,102 @@
|
|||
#ifndef DGL_DGLEVENT_H_INCLUDED
|
||||
#define DGL_DGLEVENT_H_INCLUDED
|
||||
|
||||
#include "dglcmn.h"
|
||||
#include "dglkbrd.h"
|
||||
#include "dglmouse.h"
|
||||
|
||||
typedef byte EVENT_TYPE;
|
||||
|
||||
#define EVENT_TYPE_KEYBOARD 1
|
||||
#define EVENT_TYPE_MOUSE_MOTION 2
|
||||
#define EVENT_TYPE_MOUSE_BUTTON 3
|
||||
|
||||
typedef byte EVENT_ACTION;
|
||||
|
||||
#define EVENT_ACTION_PRESSED 1
|
||||
#define EVENT_ACTION_RELEASED 2
|
||||
#define EVENT_ACTION_HELD 3
|
||||
|
||||
typedef struct {
|
||||
KEY key;
|
||||
EVENT_ACTION action;
|
||||
} INPUTEVENT_KEYBOARD;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int x_delta;
|
||||
int y_delta;
|
||||
MOUSE_BUTTON buttons;
|
||||
} INPUTEVENT_MOUSE_MOTION;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
MOUSE_BUTTON button;
|
||||
EVENT_ACTION action;
|
||||
} INPUTEVENT_MOUSE_BUTTON;
|
||||
|
||||
typedef struct {
|
||||
EVENT_TYPE type;
|
||||
union {
|
||||
INPUTEVENT_KEYBOARD keyboard;
|
||||
INPUTEVENT_MOUSE_MOTION mouse_motion;
|
||||
INPUTEVENT_MOUSE_BUTTON mouse_button;
|
||||
};
|
||||
} INPUTEVENT;
|
||||
|
||||
extern volatile boolean _events_enabled;
|
||||
|
||||
#define EVENTS_BUFFER_SIZE 32
|
||||
|
||||
extern volatile INPUTEVENT _events_buffer[EVENTS_BUFFER_SIZE];
|
||||
extern volatile int _events_buffer_start;
|
||||
extern volatile int _events_buffer_end;
|
||||
|
||||
boolean events_init(void);
|
||||
boolean events_shutdown(void);
|
||||
static boolean events_is_initialized(void);
|
||||
|
||||
static boolean events_is_empty(void);
|
||||
|
||||
boolean events_poll(INPUTEVENT **event);
|
||||
boolean events_peek(INPUTEVENT **event);
|
||||
|
||||
void events_clear(void);
|
||||
|
||||
static void _events_push(INPUTEVENT **out_event);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static boolean events_is_initialized(void) {
|
||||
return _events_enabled;
|
||||
}
|
||||
|
||||
static boolean events_is_empty(void) {
|
||||
return (_events_buffer_start == _events_buffer_end);
|
||||
}
|
||||
|
||||
// only intended to be called from input device interrupt handler (the
|
||||
// usage is a little weird as a result)
|
||||
static void _events_push(INPUTEVENT **out_event) {
|
||||
*out_event = &_events_buffer[_events_buffer_end];
|
||||
|
||||
++_events_buffer_end;
|
||||
|
||||
// wrap around
|
||||
if (_events_buffer_end >= EVENTS_BUFFER_SIZE)
|
||||
_events_buffer_end = 0;
|
||||
|
||||
// is the events buffer full? (if the end meets up to the start, yes)
|
||||
if (_events_buffer_end == _events_buffer_start) {
|
||||
// move the start up. this ensures start always points to the oldest
|
||||
// event in the buffer
|
||||
++_events_buffer_start;
|
||||
if (_events_buffer_start >= EVENTS_BUFFER_SIZE)
|
||||
_events_buffer_start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
22
DGLKBRD.C
22
DGLKBRD.C
|
@ -1,4 +1,5 @@
|
|||
#include "dglkbrd.h"
|
||||
#include "dglevent.h"
|
||||
#include "dglutil.h"
|
||||
#include "dglerror.h"
|
||||
#include <string.h>
|
||||
|
@ -22,6 +23,7 @@
|
|||
#define KEYBRD_LED_CAPSLOCK 0x4
|
||||
|
||||
static boolean _installed = FALSE;
|
||||
static INPUTEVENT *keyboard_event;
|
||||
|
||||
volatile ubyte keys[128];
|
||||
|
||||
|
@ -63,6 +65,20 @@ static boolean send_kb_data(ubyte data) {
|
|||
return (result == 0xFA);
|
||||
}
|
||||
|
||||
static void push_keyboard_event(KEY key, EVENT_ACTION action) {
|
||||
if (_events_enabled) {
|
||||
// HACK: skipping extended (?) key extra keyscan code.
|
||||
// we only actually care about the subsequent key code...
|
||||
// (this is a terrible way to do this, doesn't handle all cases)
|
||||
if (key != 0x60) {
|
||||
_events_push(&keyboard_event);
|
||||
keyboard_event->type = EVENT_TYPE_KEYBOARD;
|
||||
keyboard_event->keyboard.key = key;
|
||||
keyboard_event->keyboard.action = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keyboard interrupt handler
|
||||
void interrupt far kb_int_handler(void) {
|
||||
// read scan code of key that was just pressed
|
||||
|
@ -72,8 +88,14 @@ void interrupt far kb_int_handler(void) {
|
|||
// the actual key scan code
|
||||
_key_scan &= 0x7f;
|
||||
keys[(int)_key_scan] = 0;
|
||||
push_keyboard_event(_key_scan, EVENT_ACTION_RELEASED);
|
||||
} else {
|
||||
if (keys[(int)_key_scan])
|
||||
push_keyboard_event(_key_scan, EVENT_ACTION_HELD);
|
||||
else {
|
||||
keys[(int)_key_scan] = 1;
|
||||
push_keyboard_event(_key_scan, EVENT_ACTION_PRESSED);
|
||||
}
|
||||
}
|
||||
|
||||
_key_last_scan = _key_scan;
|
||||
|
|
58
DGLMOUSE.C
58
DGLMOUSE.C
|
@ -1,4 +1,5 @@
|
|||
#include "dglmouse.h"
|
||||
#include "dglevent.h"
|
||||
#include "dglerror.h"
|
||||
#include <string.h>
|
||||
#include <dos.h>
|
||||
|
@ -6,11 +7,14 @@
|
|||
static boolean _installed = FALSE;
|
||||
static boolean _has_mouse = FALSE;
|
||||
|
||||
static INPUTEVENT *mouse_event;
|
||||
|
||||
volatile int mouse_x;
|
||||
volatile int mouse_y;
|
||||
volatile int mouse_buttons;
|
||||
volatile int mouse_delta_x;
|
||||
volatile int mouse_delta_y;
|
||||
volatile int mouse_prev_buttons;
|
||||
|
||||
static void reset_mouse_state(void) {
|
||||
mouse_x = 0;
|
||||
|
@ -18,6 +22,7 @@ static void reset_mouse_state(void) {
|
|||
mouse_buttons = 0;
|
||||
mouse_delta_x = 0;
|
||||
mouse_delta_y = 0;
|
||||
mouse_prev_buttons = 0;
|
||||
}
|
||||
|
||||
static boolean init_mouse_driver(void) {
|
||||
|
@ -38,11 +43,31 @@ static void update_mouse_state(void) {
|
|||
int386(0x33, ®s, ®s);
|
||||
mouse_x = (regs.w.cx / 2);
|
||||
mouse_y = regs.w.dx;
|
||||
mouse_prev_buttons = mouse_buttons;
|
||||
mouse_buttons = regs.w.bx;
|
||||
mouse_delta_x = 0;
|
||||
mouse_delta_y = 0;
|
||||
}
|
||||
|
||||
static void push_motion_event(void) {
|
||||
_events_push(&mouse_event);
|
||||
mouse_event->type = EVENT_TYPE_MOUSE_MOTION;
|
||||
mouse_event->mouse_motion.x = mouse_x;
|
||||
mouse_event->mouse_motion.y = mouse_y;
|
||||
mouse_event->mouse_motion.x_delta = mouse_delta_x;
|
||||
mouse_event->mouse_motion.y_delta = mouse_delta_y;
|
||||
mouse_event->mouse_motion.buttons = mouse_buttons;
|
||||
}
|
||||
|
||||
static void push_button_event(EVENT_ACTION action, MOUSE_BUTTON button) {
|
||||
_events_push(&mouse_event);
|
||||
mouse_event->type = EVENT_TYPE_MOUSE_BUTTON;
|
||||
mouse_event->mouse_button.x = mouse_x;
|
||||
mouse_event->mouse_button.y = mouse_y;
|
||||
mouse_event->mouse_button.action = action;
|
||||
mouse_event->mouse_button.button = button;
|
||||
}
|
||||
|
||||
#pragma off (check_stack)
|
||||
void __loadds far mouse_int_handler(int eax, int ebx, int ecx, int edx) {
|
||||
#pragma aux mouse_int_handler parm [eax] [ebx] [ecx] [edx]
|
||||
|
@ -50,7 +75,40 @@ void __loadds far mouse_int_handler(int eax, int ebx, int ecx, int edx) {
|
|||
mouse_delta_y = edx - mouse_y;
|
||||
mouse_x = (ecx / 2);
|
||||
mouse_y = edx;
|
||||
mouse_prev_buttons = mouse_buttons;
|
||||
mouse_buttons = ebx;
|
||||
|
||||
if (_events_enabled) {
|
||||
if (mouse_delta_x || mouse_delta_y) {
|
||||
push_motion_event();
|
||||
}
|
||||
|
||||
if (mouse_buttons != mouse_prev_buttons) {
|
||||
if ((mouse_buttons & MOUSE_LEFTBUTTON) !=
|
||||
(mouse_prev_buttons & MOUSE_LEFTBUTTON)) {
|
||||
if (mouse_buttons & MOUSE_LEFTBUTTON)
|
||||
push_button_event(EVENT_ACTION_PRESSED, MOUSE_LEFTBUTTON);
|
||||
else
|
||||
push_button_event(EVENT_ACTION_RELEASED, MOUSE_LEFTBUTTON);
|
||||
}
|
||||
|
||||
if ((mouse_buttons & MOUSE_RIGHTBUTTON) !=
|
||||
(mouse_prev_buttons & MOUSE_RIGHTBUTTON)) {
|
||||
if (mouse_buttons & MOUSE_RIGHTBUTTON)
|
||||
push_button_event(EVENT_ACTION_PRESSED, MOUSE_RIGHTBUTTON);
|
||||
else
|
||||
push_button_event(EVENT_ACTION_RELEASED, MOUSE_RIGHTBUTTON);
|
||||
}
|
||||
|
||||
if ((mouse_buttons & MOUSE_CENTERBUTTON) !=
|
||||
(mouse_prev_buttons & MOUSE_CENTERBUTTON)) {
|
||||
if (mouse_buttons & MOUSE_CENTERBUTTON)
|
||||
push_button_event(EVENT_ACTION_PRESSED, MOUSE_CENTERBUTTON);
|
||||
else
|
||||
push_button_event(EVENT_ACTION_RELEASED, MOUSE_CENTERBUTTON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma on (check_stack)
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "dglcmn.h"
|
||||
|
||||
typedef byte MOUSE_BUTTON;
|
||||
|
||||
#define MOUSE_LEFTBUTTON 0x01
|
||||
#define MOUSE_RIGHTBUTTON 0x02
|
||||
#define MOUSE_CENTERBUTTON 0x04
|
||||
|
|
1
MAKEFILE
1
MAKEFILE
|
@ -9,6 +9,7 @@ object_files = &
|
|||
dgl.obj &
|
||||
dgldraw.obj &
|
||||
dgldrawa.obj &
|
||||
dglevent.obj &
|
||||
dglgfx.obj &
|
||||
dglpal.obj &
|
||||
dglkbrd.obj &
|
||||
|
|
73
TEST/EVENTS.C
Normal file
73
TEST/EVENTS.C
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "events.h"
|
||||
#include "dgl.h"
|
||||
#include <stdio.h>
|
||||
#include "helpers.h"
|
||||
|
||||
void test_events(void) {
|
||||
boolean result;
|
||||
INPUTEVENT *event;
|
||||
|
||||
clrscr(0);
|
||||
delay(500);
|
||||
|
||||
result = keyboard_init();
|
||||
ASSERT(result == TRUE);
|
||||
result = mouse_init();
|
||||
ASSERT(result == TRUE);
|
||||
|
||||
ASSERT(events_is_initialized() == FALSE);
|
||||
|
||||
result = events_init();
|
||||
ASSERT(result == TRUE);
|
||||
ASSERT(events_is_initialized() == TRUE);
|
||||
|
||||
printf("Displaying events:\n\n");
|
||||
|
||||
while (!keys[1]) {
|
||||
if (!events_poll(&event))
|
||||
continue;
|
||||
|
||||
switch (event->type) {
|
||||
case EVENT_TYPE_KEYBOARD:
|
||||
printf("KEYBOARD: %2d - %d\n",
|
||||
event->keyboard.key,
|
||||
event->keyboard.action);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_MOUSE_MOTION:
|
||||
printf("MOUSE MOTION: %3d, %3d (%3d, %3d), %d\n",
|
||||
event->mouse_motion.x,
|
||||
event->mouse_motion.y,
|
||||
event->mouse_motion.x_delta,
|
||||
event->mouse_motion.y_delta,
|
||||
event->mouse_motion.buttons);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_MOUSE_BUTTON:
|
||||
printf("MOUSE BUTTON: %3d, %3d, %d - %d\n",
|
||||
event->mouse_button.x,
|
||||
event->mouse_button.y,
|
||||
event->mouse_button.button,
|
||||
event->mouse_button.action);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("** UNKNOWN: %d **\n", event->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = events_shutdown();
|
||||
ASSERT(result == TRUE);
|
||||
ASSERT(events_is_initialized() == FALSE);
|
||||
|
||||
result = mouse_shutdown();
|
||||
ASSERT(result == TRUE);
|
||||
result = keyboard_shutdown();
|
||||
ASSERT(result == TRUE);
|
||||
|
||||
printf("\nPress a key to continue...\n");
|
||||
|
||||
getch();
|
||||
}
|
||||
|
5
TEST/EVENTS.H
Normal file
5
TEST/EVENTS.H
Normal file
|
@ -0,0 +1,5 @@
|
|||
#ifndef DGL_TEST_EVENTS_H_INCLUDED
|
||||
#define DGL_TEST_EVENTS_H_INCLUDED
|
||||
|
||||
#endif
|
||||
|
|
@ -3,6 +3,7 @@ target_config = debug
|
|||
target_name = test
|
||||
|
||||
object_files = blit.obj &
|
||||
events.obj &
|
||||
fixed.obj &
|
||||
helpers.obj &
|
||||
kbrd.obj &
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "helpers.h"
|
||||
|
||||
#include "blit.h"
|
||||
#include "events.h"
|
||||
#include "fixed.h"
|
||||
#include "kbrd.h"
|
||||
#include "line.h"
|
||||
|
@ -43,6 +44,7 @@ int main(void) {
|
|||
|
||||
test_keyboard();
|
||||
test_mouse();
|
||||
test_events();
|
||||
test_fixed();
|
||||
test_vector2i();
|
||||
test_vector2f();
|
||||
|
|
Loading…
Reference in a new issue