Descent3/ddio_win/winmouse.cpp
2024-04-15 21:43:29 -06:00

901 lines
24 KiB
C++

// ----------------------------------------------------------------------------
// Mouse Interface
// ----------------------------------------------------------------------------
#include <stdlib.h>
#include "DDAccess.h"
#include "pserror.h"
#include "mono.h"
#include "ddio.h"
#include "ddio_win.h"
#include "Application.h"
#include "psclass.h"
#include "Macros.h"
typedef struct t_mse_button_info
{
bool is_down[N_MSEBTNS];
ubyte down_count[N_MSEBTNS];
ubyte up_count[N_MSEBTNS];
DWORD time_down[N_MSEBTNS]; // in milliseconds windows ticks
DWORD time_up[N_MSEBTNS];
}
t_mse_button_info;
typedef struct t_mse_event
{
short btn;
short state;
}
t_mse_event;
#define MOUSE_ZMIN 0 // mouse wheel z min and max (increments of 120 = 10 units)
#define MOUSE_ZMAX 1200
#define N_DIMSEBTNS 4 // # of REAL mouse buttons
#define MSEBTN_WHL_UP (N_DIMSEBTNS) // button index for mouse wheel up
#define MSEBTN_WHL_DOWN (N_DIMSEBTNS+1) // button index for mouse wheel down
// taken from winuser.h
#ifndef WHEEL_DELTA
#define WHEEL_DELTA 120
#endif
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x20a
#endif
// ----------------------------------------------------------------------------
static bool DDIO_mouse_init = 0;
static struct mses_state
{
LPDIRECTINPUTDEVICE lpdimse;
RECT brect; // limit rectangle of absolute mouse coords
short x, y, z; // current x,y,z in absolute mouse coords
short cx, cy, cz; // prior values of x,y,z from last mouse frame
short zmin, zmax; // 3 dimensional mouse devices use this
int btn_mask, btn_flags; // btn_flags are the avaiable buttons on this device in mask form.
bool emulated; // are we emulating direct input?
bool acquired;
bool suspended;
sbyte cursor_count;
float x_aspect, y_aspect; // used in calculating coordinates returned from ddio_MouseGetState
HANDLE hmseevt; // signaled if mouse input is awaiting.
short dx, dy, dz, imm_dz;
short mode; // mode of mouse operation.
short nbtns, naxis; // device caps.
} DDIO_mouse_state;
static t_mse_button_info DIM_buttons;
static tQueue<t_mse_event, 16> MB_queue;
// ----------------------------------------------------------------------------
// di_mouse initialization.
LPDIRECTINPUTDEVICE dimouse_Init(LPDIRECTINPUT lpdi, HWND hwnd);
// di_mouse close
void dimouse_Shutdown(LPDIRECTINPUTDEVICE lpdimse);
// di_mouse acquire device, returns acquisition state of device
bool dimouse_Acquire(LPDIRECTINPUTDEVICE lpdimse, bool acquire);
// returns device data.
void dimouse_GetDeviceData(LPDIRECTINPUTDEVICE lpdimse);
// emulated get device state
void winmouse_GetDeviceData(POINT &pt);
inline void DDIOShowCursor(BOOL show)
{
if (show)
{
if (DDIO_mouse_state.cursor_count == -1)
{
ShowCursor(TRUE);
}
DDIO_mouse_state.cursor_count = 0;
}
else
{
if (DDIO_mouse_state.cursor_count == 0)
{
ShowCursor(FALSE);
}
DDIO_mouse_state.cursor_count = -1;
}
}
// ---------------------------------------------------------------------------
// Initialization Functions
extern bool w32_mouseman_hack;
bool ddio_MouseInit()
{
tWin32OS os;
int major, minor;
// see if we need to emulate directinput.
os = oeWin32Application::version(&major, &minor);
DDIO_mouse_state.emulated = (os == WinNT && major < 5) ? true : false;
DDIO_mouse_state.lpdimse = NULL;
if (w32_mouseman_hack)
{
DDIO_mouse_state.emulated = true;
}
if (!DDIO_mouse_state.emulated)
{
// initialize direct input version? attempt acquisition if so
DDIO_mouse_state.lpdimse = dimouse_Init(DInputData.lpdi, (HWND)DInputData.app->m_hWnd);
if (DDIO_mouse_state.lpdimse)
{
DDIO_mouse_state.acquired = dimouse_Acquire(DDIO_mouse_state.lpdimse, true);
}
}
else {
DDIO_mouse_state.nbtns = 3;
DDIO_mouse_state.naxis = 2;
DDIO_mouse_state.btn_flags = (MOUSE_LB+MOUSE_RB+MOUSE_CB);
if (DDIO_mouse_state.naxis >= 3 || w32_mouseman_hack)
{
DDIO_mouse_state.zmin = MOUSE_ZMIN;
DDIO_mouse_state.zmax = MOUSE_ZMAX;
DDIO_mouse_state.nbtns = N_DIMSEBTNS+2; // 2 next button slots reserved for mouse wheel.
DDIO_mouse_state.btn_flags |= (1<<MSEBTN_WHL_UP);
DDIO_mouse_state.btn_flags |= (1<<MSEBTN_WHL_DOWN);
}
}
// standard initialization
DDIO_mouse_state.emulated = (DDIO_mouse_state.lpdimse) ? false : true;
DDIO_mouse_state.cursor_count = ShowCursor(TRUE); // get initial count
while (DDIO_mouse_state.cursor_count >= 0) // hide cursor until truly hidden.
{
DDIO_mouse_state.cursor_count = ShowCursor(FALSE);
}
ddio_MouseMode(MOUSE_STANDARD_MODE);
DDIO_mouse_state.suspended = false;
ddio_MouseReset();
DDIO_mouse_init = true;
return true;
}
// here we deinitialize our Mouse from DirectInput.
void ddio_MouseClose()
{
if (!DDIO_mouse_init)
return;
// direct input shutdown.
if (DDIO_mouse_state.emulated == false)
{
dimouse_Shutdown(DDIO_mouse_state.lpdimse);
}
DDIO_mouse_init = false;
}
// get device caps
int ddio_MouseGetCaps(int *btn, int *axis)
{
*btn = (int)DDIO_mouse_state.nbtns;
*axis = (int)DDIO_mouse_state.naxis;
return DDIO_mouse_state.btn_flags;
}
void ddio_MouseMode(int mode)
{
if (mode == MOUSE_EXCLUSIVE_MODE)
{
DDIOShowCursor(FALSE);
}
else if (mode == MOUSE_STANDARD_MODE)
{
DDIOShowCursor(TRUE);
}
else
{
Int3();
return;
}
DDIO_mouse_state.mode = mode;
}
// ddio_MouseReset
// resets the mouse system, resetting boundaries to application window size, and mouse pointer
// to the center of the screen.
void ddio_MouseQueueFlush()
{
ZeroMemory(&DIM_buttons, sizeof(DIM_buttons));
MB_queue.flush();
}
void ddio_MouseReset()
{
tWin32AppInfo appi;
DInputData.app->get_info(&appi);
DDIO_mouse_state.cx = appi.wnd_x + (appi.wnd_w/2);
DDIO_mouse_state.cy = appi.wnd_y + (appi.wnd_h/2);
SetRect(&DDIO_mouse_state.brect, 0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
DDIO_mouse_state.zmin = MOUSE_ZMIN;
DDIO_mouse_state.zmax = MOUSE_ZMAX;
// set up new coordinates for mouse pointer.
DDIO_mouse_state.btn_mask = 0;
DDIO_mouse_state.dx = 0;
DDIO_mouse_state.dy = 0;
DDIO_mouse_state.dz = 0;
DDIO_mouse_state.imm_dz = 0;
DDIO_mouse_state.x = (short)(DDIO_mouse_state.brect.right-DDIO_mouse_state.brect.left)/2;
DDIO_mouse_state.y = (short)(DDIO_mouse_state.brect.bottom-DDIO_mouse_state.brect.top)/2;
DDIO_mouse_state.z = (DDIO_mouse_state.zmax = DDIO_mouse_state.zmin)/2;
DDIO_mouse_state.cz = 0;
DDIO_mouse_state.x_aspect = 1.0f;
DDIO_mouse_state.y_aspect = 1.0f;
// reset button states
ddio_MouseQueueFlush();
}
// gets limits on the position of the mouse cursor (or atleast what's returned from GetState)
void ddio_MouseGetLimits(int *left, int *top, int *right, int *bottom, int *zmin, int *zmax)
{
*left = DDIO_mouse_state.brect.left;
*top = DDIO_mouse_state.brect.top;
*right = DDIO_mouse_state.brect.right;
*bottom = DDIO_mouse_state.brect.bottom;
if (zmin)
*zmin = DDIO_mouse_state.zmin;
if (zmax)
*zmax = DDIO_mouse_state.zmax;
}
// sets limits on the position of the mouse cursor (or atleast what's returned from GetState)
void ddio_MouseSetLimits(int left, int top, int right, int bottom, int zmin, int zmax)
{
bool zaxis = (DDIO_mouse_state.naxis >= 3);
SetRect(&DDIO_mouse_state.brect, left, top, right, bottom);
DDIO_mouse_state.zmin = (!zmin && zaxis) ? MOUSE_ZMIN : zmin;
DDIO_mouse_state.zmax = (!zmax && zaxis) ? MOUSE_ZMAX : zmax;
DDIO_mouse_state.cx = left+ (right-left)/2;
DDIO_mouse_state.cy = top +(bottom-top)/2;
}
// virtual coordinate system for mouse (match to video resolution set for optimal mouse usage.
void ddio_MouseSetVCoords(int width, int height)
{
ddio_MouseSetLimits(0,0,width,height);
}
/* x, y = absolute mouse position
dx, dy = mouse deltas since last call
return value is mouse button mask
*/
int ddio_MouseGetState(int *x, int *y, int *dx, int *dy, int *z, int *dz)
{
int btn_mask = DDIO_mouse_state.btn_mask;
// get return values.
if (x) *x = DDIO_mouse_state.x;
if (y) *y = DDIO_mouse_state.y;
if (z) *z = DDIO_mouse_state.z;
if (dx) *dx = DDIO_mouse_state.dx;
if (dy) *dy = DDIO_mouse_state.dy;
if (dz) *dz = DDIO_mouse_state.dz;
#ifdef _DEBUG
mprintf_at((4,0,0, "MSE:X:%04d Y:%04d dX:%04d dY:%04d WM_MOUSEWHEEL:%04d", DDIO_mouse_state.x, DDIO_mouse_state.y, DDIO_mouse_state.dx, DDIO_mouse_state.dy, w32_msewhl_delta));
#endif
DDIO_mouse_state.dx = 0;
DDIO_mouse_state.dy = 0;
DDIO_mouse_state.dz = 0;
DDIO_mouse_state.btn_mask = 0;
return btn_mask;
}
// gets a mouse button event, returns false if none.
bool ddio_MouseGetEvent(int *btn, bool *state)
{
t_mse_event evt;
if (MB_queue.recv(&evt)) {
*btn = (int)evt.btn;
*state = evt.state ? true : false;
return true;
}
return false;
}
// return mouse button down time.
float ddio_MouseBtnDownTime(int btn)
{
DWORD ticks, curticks = GetTickCount();
ASSERT(btn >=0 && btn < N_MSEBTNS);
if (DIM_buttons.is_down[btn]) {
ticks = curticks - DIM_buttons.time_down[btn];
DIM_buttons.time_down[btn] = curticks;
}
else {
ticks = DIM_buttons.time_up[btn] - DIM_buttons.time_down[btn];
DIM_buttons.time_down[btn] = 0;
DIM_buttons.time_up[btn] = 0;
}
return (float)(ticks/1000.0f);
}
// return mouse button down time
int ddio_MouseBtnDownCount(int btn)
{
if (btn < 0 || btn >= N_MSEBTNS) return 0;
int n_downs = DIM_buttons.down_count[btn];
if (n_downs) {
DIM_buttons.down_count[btn] = 0;
}
return n_downs;
}
// return mouse button up count
int ddio_MouseBtnUpCount(int btn)
{
if (btn < 0 || btn >= N_MSEBTNS) return 0;
int n_ups = DIM_buttons.up_count[btn];
DIM_buttons.up_count[btn] = 0;
return n_ups;
}
///////////////////////////////////////////////////////////////////////////////
// called by ddio system.
///////////////////////////////////////////////////////////////////////////////
void ddio_InternalMouseFrame()
{
DWORD res;
POINT pt;
if (!DDIO_mouse_init)
return;
if (DDIO_mouse_state.suspended) {
DDIO_mouse_state.btn_mask = 0;
DDIO_mouse_state.dx = 0;
DDIO_mouse_state.dy = 0;
DDIO_mouse_state.dz = 0;
return;
}
GetCursorPos(&pt);
// in emulation mode
if (DDIO_mouse_state.emulated)
{
winmouse_GetDeviceData(pt);
}
else
{
// check if event has been signaled.
res = WaitForSingleObject(DDIO_mouse_state.hmseevt, 0);
switch (res)
{
case WAIT_OBJECT_0:
dimouse_GetDeviceData(DDIO_mouse_state.lpdimse);
ResetEvent(DDIO_mouse_state.hmseevt); // clear for next frame.
break;
}
}
// create button mask now that DIM_buttons should be valid.
int btn_mask = 0;
if (DIM_buttons.is_down[0]) btn_mask |= MOUSE_LB;
if (DIM_buttons.is_down[1]) btn_mask |= MOUSE_RB;
if (DIM_buttons.is_down[2]) btn_mask |= MOUSE_CB;
if (DIM_buttons.is_down[3]) btn_mask |= MOUSE_B4;
if (DIM_buttons.is_down[4]) btn_mask |= MOUSE_B5;
if (DIM_buttons.is_down[5]) btn_mask |= MOUSE_B6;
if (DIM_buttons.is_down[6]) btn_mask |= MOUSE_B7;
if (DIM_buttons.is_down[7]) btn_mask |= MOUSE_B8;
// reset button states for wheel up and down, since we're emulating them.
DIM_buttons.is_down[MSEBTN_WHL_UP] = false;
DIM_buttons.is_down[MSEBTN_WHL_DOWN] = false;
DDIO_mouse_state.btn_mask = btn_mask;
// cleanup for specific mouse modes.
if (DDIO_mouse_state.mode == MOUSE_STANDARD_MODE)
{
// figure out where the top-left of the screen is
RECT clientRect;
GetClientRect( (HWND)DInputData.app->m_hWnd, &clientRect );
POINT topLeftWindow;
topLeftWindow.x = clientRect.left;
topLeftWindow.y = clientRect.top;
ClientToScreen( (HWND)DInputData.app->m_hWnd, &topLeftWindow );
// if in standard mode, don't use x,y,z retrieved from dimouse_GetDeviceData
DDIO_mouse_state.x = (short)(pt.x - topLeftWindow.x);
DDIO_mouse_state.y = (short)(pt.y - topLeftWindow.y);
DDIO_mouse_state.z = 0;
}
if (DDIO_mouse_state.mode == MOUSE_EXCLUSIVE_MODE)
{
if (pt.x != DDIO_mouse_state.cx || pt.y != DDIO_mouse_state.cy)
{
SetCursorPos(DDIO_mouse_state.cx, DDIO_mouse_state.cy);
}
}
// check bounds of mouse cursor.
if (DDIO_mouse_state.x < DDIO_mouse_state.brect.left)
DDIO_mouse_state.x = (short)DDIO_mouse_state.brect.left;
if (DDIO_mouse_state.x >= DDIO_mouse_state.brect.right)
DDIO_mouse_state.x = (short)DDIO_mouse_state.brect.right-1;
if (DDIO_mouse_state.y < DDIO_mouse_state.brect.top)
DDIO_mouse_state.y = (short)DDIO_mouse_state.brect.top;
if (DDIO_mouse_state.y >= DDIO_mouse_state.brect.bottom)
DDIO_mouse_state.y = (short)DDIO_mouse_state.brect.bottom-1;
if (DDIO_mouse_state.z > DDIO_mouse_state.zmax)
DDIO_mouse_state.z = (short)DDIO_mouse_state.zmax;
if (DDIO_mouse_state.z < DDIO_mouse_state.zmin)
DDIO_mouse_state.z = (short)DDIO_mouse_state.zmin;
}
// used to prevent mouse input from being registered
void ddio_InternalMouseSuspend()
{
if (!DDIO_mouse_init) return;
if (DDIO_mouse_state.lpdimse) {
DDIO_mouse_state.acquired = dimouse_Acquire(DDIO_mouse_state.lpdimse, false);
}
DDIO_mouse_state.suspended = true;
}
void ddio_InternalMouseResume()
{
if (!DDIO_mouse_init) return;
if (DDIO_mouse_state.lpdimse) {
DDIO_mouse_state.acquired = dimouse_Acquire(DDIO_mouse_state.lpdimse, true);
}
DDIO_mouse_state.suspended = false;
}
///////////////////////////////////////////////////////////////////////////////
// DirectInput mouse interface
///////////////////////////////////////////////////////////////////////////////
#define DINPUT_BUFFERSIZE 64
// di_mouse initialization.
LPDIRECTINPUTDEVICE dimouse_Init(LPDIRECTINPUT lpdi, HWND hwnd)
{
LPDIRECTINPUTDEVICE lpdimse;
HRESULT hr;
HANDLE hevt;
DIDEVCAPS devcaps;
DIPROPDWORD dipropdw = {
{
sizeof(DIPROPDWORD),
sizeof(DIPROPHEADER),
0,
DIPH_DEVICE,
},
DIPROPAXISMODE_REL
};
int i;
DDIO_mouse_state.hmseevt = NULL;
// see if we need to emulate directinput.
int major, minor;
tWin32OS os = oeWin32Application::version(&major, &minor);
if (os == WinNT && major < 5) {
return NULL;
}
// see if we can get the keyboard device.
hr = lpdi->CreateDevice(GUID_SysMouse, &lpdimse, NULL);
if (hr != DI_OK) {
DDIO_MESSAGE((hr, "DI_Mouse initialization failed."));
return NULL;
}
hr = lpdimse->SetDataFormat(&c_dfDIMouse);
if (hr != DI_OK) {
DDIO_MESSAGE((hr, "DI_Mouse data format specification failed."));
lpdimse->Release();
return NULL;
}
// set key buffer size
hr = lpdimse->SetProperty(DIPROP_AXISMODE, &dipropdw.diph);
if (FAILED(hr)) {
DDIO_MESSAGE((hr, "DI_mouse relative mode failed.."));
lpdimse->Release();
return NULL;
}
hr = lpdimse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
if (hr != DI_OK) {
DDIO_MESSAGE((hr, "DI_Mouse set cooperative level failed."));
lpdimse->Release();
return NULL;
}
// enable event notification.
hevt = CreateEvent(NULL, TRUE, FALSE, "DDIOMouseEvent");
if (!hevt) {
DDIO_MESSAGE((0, "DI_mouse data event create failed."));
lpdimse->Release();
return NULL;
}
hr = lpdimse->SetEventNotification(hevt);
if (FAILED(hr)) {
DDIO_MESSAGE((0, "DI_mouse event notification failed."));
CloseHandle(hevt);
lpdimse->Release();
return NULL;
}
// use buffered input.
DIPROPDWORD dipdw =
{
// the header
{
sizeof(DIPROPDWORD), // diph.dwSize
sizeof(DIPROPHEADER), // diph.dwHeaderSize
0, // diph.dwObj
DIPH_DEVICE, // diph.dwHow
},
// the data
DINPUT_BUFFERSIZE, // dwData
};
hr = lpdimse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
if (FAILED(hr)) {
DDIO_MESSAGE((hr, "DI_mouse Set buffer size(SysMouse)"));
CloseHandle(hevt);
lpdimse->Release();
return NULL;
}
// we have a handle
DDIO_mouse_state.hmseevt = hevt;
// determine if there's a mousewheel (z-axis) attached.
devcaps.dwSize = sizeof(DIDEVCAPS);
hr = lpdimse->GetCapabilities(&devcaps);
if (FAILED(hr) || !CHECK_FLAG(devcaps.dwFlags, DIDC_ATTACHED)) {
DDIO_MESSAGE((hr, "DI_mouse: GetCaps failed"));
CloseHandle(hevt);
lpdimse->Release();
return NULL;
}
DDIO_mouse_state.naxis = (short)((devcaps.dwAxes > 3) ? 3 : devcaps.dwAxes);
DDIO_mouse_state.nbtns = N_DIMSEBTNS; // cap at max number of buttons directinput accepts for mice
DDIO_mouse_state.btn_flags = 0;
for (i = 0; (i < (int)devcaps.dwButtons) && (i < N_DIMSEBTNS); i++)
{
DDIO_mouse_state.btn_flags |= (1<<i);
}
if (DDIO_mouse_state.naxis >= 3) {
DDIO_mouse_state.zmin = MOUSE_ZMIN;
DDIO_mouse_state.zmax = MOUSE_ZMAX;
DDIO_mouse_state.nbtns = N_DIMSEBTNS+2; // 2 next button slots reserved for mouse wheel.
DDIO_mouse_state.btn_flags |= (1<<MSEBTN_WHL_UP);
DDIO_mouse_state.btn_flags |= (1<<MSEBTN_WHL_DOWN);
}
return lpdimse;
}
// di_mouse close
void dimouse_Shutdown(LPDIRECTINPUTDEVICE lpdimse)
{
if (lpdimse) {
if (DDIO_mouse_state.hmseevt) {
lpdimse->SetEventNotification(NULL);
CloseHandle(DDIO_mouse_state.hmseevt);
DDIO_mouse_state.hmseevt = NULL;
}
lpdimse->Release();
}
}
// di_mouse acquire device, returns acquisition state of device
bool dimouse_Acquire(LPDIRECTINPUTDEVICE lpdimse, bool acquire)
{
HRESULT hr = acquire ? lpdimse->Acquire() : lpdimse->Unacquire();
if (FAILED(hr)) {
mprintf((0, "ACK: %x\n", hr));
}
return (acquire && SUCCEEDED(hr)) ? true : false;
}
// returns device data.
void dimouse_GetDeviceData(LPDIRECTINPUTDEVICE lpdimse)
{
DIDEVICEOBJECTDATA diobjdata[DINPUT_BUFFERSIZE];
DWORD diobjitems = DINPUT_BUFFERSIZE;
HRESULT hr;
int i;
DDIO_mouse_state.dx = 0;
DDIO_mouse_state.dy = 0;
DDIO_mouse_state.dz = 0;
// don't read if suspended!
if (DDIO_mouse_state.suspended) {
return;
}
// attempt to acquire device.
if (!DDIO_mouse_state.acquired) {
DDIO_mouse_state.acquired = dimouse_Acquire(lpdimse, true);
}
// read device.
if (DDIO_mouse_state.acquired) {
hr = lpdimse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), diobjdata, &diobjitems, 0);
if (SUCCEEDED(hr)) {
// read and translate data
for (i =0; i < (int)diobjitems; i++)
{
int idx=-1;
t_mse_event evt;
switch (diobjdata[i].dwOfs)
{
case DIMOFS_X:
DDIO_mouse_state.x += (int)diobjdata[i].dwData;
DDIO_mouse_state.dx += (int)diobjdata[i].dwData;
break;
case DIMOFS_Y:
DDIO_mouse_state.y += (int)diobjdata[i].dwData;
DDIO_mouse_state.dy += (int)diobjdata[i].dwData;
break;
case DIMOFS_Z:
// for z, simulate mouse press for emulated mouse buttons.
DDIO_mouse_state.z += (int)diobjdata[i].dwData;
DDIO_mouse_state.dz += (int)diobjdata[i].dwData;
DDIO_mouse_state.imm_dz += (int)diobjdata[i].dwData;
// mprintf((0, "Zmse=%d\n", diobjdata[i].dwData));
if (DDIO_mouse_state.imm_dz >=WHEEL_DELTA) {
idx = MSEBTN_WHL_UP;
DDIO_mouse_state.imm_dz = 0;
}
else if (DDIO_mouse_state.imm_dz <= (-WHEEL_DELTA)) {
idx = MSEBTN_WHL_DOWN;
DDIO_mouse_state.imm_dz = 0;
}
if (idx != -1) {
DIM_buttons.down_count[idx]++;
DIM_buttons.up_count[idx]++;
DIM_buttons.is_down[idx] = true; // reset in internal mouse frame.
DIM_buttons.time_down[idx] = diobjdata[i].dwTimeStamp;
DIM_buttons.time_up[idx] = (diobjdata[i].dwTimeStamp+100); // 10th of a second.
}
break;
case DIMOFS_BUTTON0: idx = (idx==-1) ? 0 : idx;
case DIMOFS_BUTTON1: idx = (idx==-1) ? 1 : idx;
case DIMOFS_BUTTON2: idx = (idx==-1) ? 2 : idx;
case DIMOFS_BUTTON3: idx = (idx==-1) ? 3 : idx;
evt.btn = (short)idx;
if ((diobjdata[i].dwData & 0x80) && !DIM_buttons.is_down[idx]) {
DIM_buttons.down_count[idx]++;
DIM_buttons.is_down[idx] = true;
DIM_buttons.time_down[idx] = diobjdata[i].dwTimeStamp;
evt.state = 1;
MB_queue.send(evt);
}
else if (!(diobjdata[i].dwData & 0x80) && DIM_buttons.is_down[idx]) {
DIM_buttons.up_count[idx]++;
DIM_buttons.is_down[idx] = false;
DIM_buttons.time_up[idx] = diobjdata[i].dwTimeStamp;
evt.state = 0;
MB_queue.send(evt);
}
break;
default:
mprintf((0, "di:unknown mouse event (%x,%x)\n", diobjdata[i].dwOfs, diobjdata[i].dwData));
break;
}
}
}
else if (hr == DIERR_INPUTLOST) {
DDIO_mouse_state.acquired = dimouse_Acquire(lpdimse, true);
}
else {
DDIO_MESSAGE((hr, "DI_mouse unable to read."));
}
}
}
// emulated get device state
void winmouse_GetDeviceData(POINT &pt)
{
t_mse_event evt;
short mode = DDIO_mouse_state.mode;
DDIO_mouse_state.dx = (short)pt.x - ((mode==MOUSE_STANDARD_MODE) ? DDIO_mouse_state.x : DDIO_mouse_state.cx);
DDIO_mouse_state.dy = (short)pt.y - ((mode==MOUSE_STANDARD_MODE) ? DDIO_mouse_state.y : DDIO_mouse_state.cy);
DDIO_mouse_state.dz = 0;
if ((ushort)GetKeyState(VK_LBUTTON) & 0x8000) {
if (!DIM_buttons.is_down[0]) {
DIM_buttons.down_count[0]++;
DIM_buttons.time_down[0] = GetTickCount();
DIM_buttons.is_down[0] = true;
evt.btn = 0;
evt.state = true;
MB_queue.send(evt);
mprintf((0, "MOUSE Button 0: Down\n"));
}
}
else if (DIM_buttons.is_down[0]) {
DIM_buttons.up_count[0]++;
DIM_buttons.is_down[0] = false;
DIM_buttons.time_up[0] = GetTickCount();
evt.btn = 0;
evt.state = false;
MB_queue.send(evt);
mprintf((0, "MOUSE Button 0: Up\n"));
}
if ((ushort)GetKeyState(VK_RBUTTON) & 0x8000) {
if (!DIM_buttons.is_down[1]) {
DIM_buttons.down_count[1]++;
DIM_buttons.time_down[1] = GetTickCount();
DIM_buttons.is_down[1] = true;
evt.btn = 1;
evt.state = true;
MB_queue.send(evt);
}
}
else if (DIM_buttons.is_down[1]) {
DIM_buttons.up_count[1]++;
DIM_buttons.is_down[1] = false;
DIM_buttons.time_up[1] = GetTickCount();
evt.btn = 1;
evt.state = false;
MB_queue.send(evt);
}
if ((ushort)GetKeyState(VK_MBUTTON) & 0x8000) {
if (!DIM_buttons.is_down[2]) {
DIM_buttons.down_count[2]++;
DIM_buttons.time_down[2] = GetTickCount();
DIM_buttons.is_down[2] = true;
evt.btn = 2;
evt.state = true;
MB_queue.send(evt);
}
}
else if (DIM_buttons.is_down[2]) {
DIM_buttons.up_count[2]++;
DIM_buttons.is_down[2] = false;
DIM_buttons.time_up[2] = GetTickCount();
evt.btn = 2;
evt.state = false;
MB_queue.send(evt);
}
if (mode == MOUSE_EXCLUSIVE_MODE) {
DDIO_mouse_state.x += DDIO_mouse_state.dx;
DDIO_mouse_state.y += DDIO_mouse_state.dy;
DDIO_mouse_state.z += DDIO_mouse_state.dz;
}
int idx = -1;
DDIO_mouse_state.imm_dz += w32_msewhl_delta;
if (DDIO_mouse_state.imm_dz >=WHEEL_DELTA) {
idx = MSEBTN_WHL_UP;
DDIO_mouse_state.imm_dz = 0;
}
else if (DDIO_mouse_state.imm_dz <= (-WHEEL_DELTA)) {
idx = MSEBTN_WHL_DOWN;
DDIO_mouse_state.imm_dz = 0;
}
if (idx != -1) {
DIM_buttons.down_count[idx]++;
DIM_buttons.up_count[idx]++;
DIM_buttons.is_down[idx] = true; // reset in internal mouse frame.
DIM_buttons.time_down[idx] = GetTickCount();
DIM_buttons.time_up[idx] = (DIM_buttons.time_down[idx]+100); // 10th of a second.
mprintf((0, "registered mouse wheel event %d\n", idx));
}
}
///////////////////////////////////////////////////////////////////////////////
char Ctltext_MseBtnBindings[N_MSEBTNS][32] = {
"mse-l\0\0\0\0\0\0\0\0\0\0\0\0",
"mse-r\0\0\0\0\0\0\0\0\0\0\0\0",
"mse-c\0\0\0\0\0\0\0\0\0\0\0\0",
"mse-b4\0\0\0\0\0\0\0\0\0\0\0",
"msew-u\0\0\0\0\0\0\0\0\0\0\0",
"msew-d\0\0\0\0\0\0\0\0\0\0\0",
"",""
};
char Ctltext_MseAxisBindings[][32] = {
"mse-X\0\0\0\0\0\0\0\0\0\0\0\0",
"mse-Y\0\0\0\0\0\0\0\0\0\0\0\0",
"msewheel\0\0\0\0\0\0\0\0\0\0"
};
// returns string to binding.
const char *ddio_MouseGetBtnText(int btn)
{
if (btn >=N_MSEBTNS || btn < 0) return ("");
return Ctltext_MseBtnBindings[btn];
}
const char *ddio_MouseGetAxisText(int axis)
{
if (axis >= (sizeof(Ctltext_MseAxisBindings)/sizeof(char*)) || axis < 0) return ("");
return Ctltext_MseAxisBindings[axis];
}