/*
Simple DirectMedia Layer
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/**
* \file SDL_touch.h
*
* Include file for SDL touch event handling.
*/
#ifndef _SDL_touch_h
#define _SDL_touch_h
#include "SDL_stdinc.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
typedef Sint64 SDL_TouchID;
typedef Sint64 SDL_FingerID;
typedef struct SDL_Finger
{
SDL_FingerID id;
float x;
float y;
float pressure;
} SDL_Finger;
/* Used as the device ID for mouse events simulated with touch input */
#define SDL_TOUCH_MOUSEID ((Uint32)-1)
/* Function prototypes */
/**
* \brief Get the number of registered touch devices.
*/
extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void);
/**
* \brief Get the touch ID with the given index, or 0 if the index is invalid.
*/
extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index);
/**
* \brief Get the number of active fingers for a given touch device.
*/
extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID);
/**
* \brief Get the finger object of the given touch, with the given index.
*/
extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include "close_code.h"
#endif /* _SDL_touch_h */
<// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Brad Hughes
//============================================================
//
// input_win32.cpp - Win32 input implementation
//
//============================================================
#include "input_module.h"
#include "modules/osdmodule.h"
#if defined(OSD_WINDOWS)
// standard windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winioctl.h>
#include <tchar.h>
#undef interface
#include <mutex>
// MAME headers
#include "emu.h"
#include "osdepend.h"
#include "ui/ui.h"
#include "strconv.h"
// MAMEOS headers
#include "winmain.h"
#include "window.h"
#include "input_common.h"
#include "input_windows.h"
//============================================================
// win32_keyboard_device
//============================================================
// This device is purely event driven so the implementation is in the module
class win32_keyboard_device : public event_based_device<KeyPressEventArgs>
{
public:
keyboard_state keyboard;
win32_keyboard_device(running_machine& machine, const char *name, input_module &module)
: event_based_device(machine, name, DEVICE_CLASS_KEYBOARD, module),
keyboard({{0}})
{
}
void reset() override
{
memset(&keyboard, 0, sizeof(keyboard));
}
protected:
void process_event(KeyPressEventArgs &args) override
{
keyboard.state[args.scancode] = args.event_id == INPUT_EVENT_KEYDOWN ? 0x80 : 0x00;
}
};
//============================================================
// keyboard_input_win32 - win32 keyboard input module
//============================================================
class keyboard_input_win32 : public wininput_module
{
private:
public:
keyboard_input_win32()
: wininput_module(OSD_KEYBOARDINPUT_PROVIDER, "win32")
{
}
virtual void input_init(running_machine &machine) override
{
// Add a single win32 keyboard device that we'll monitor using Win32
win32_keyboard_device *devinfo = devicelist()->create_device<win32_keyboard_device>(machine, "Win32 Keyboard 1", *this);
keyboard_trans_table &table = keyboard_trans_table::instance();
// populate it
for (int keynum = 0; keynum < MAX_KEYS; keynum++)
{
input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
char name[20];
// generate/fetch the name
_snprintf(name, ARRAY_LENGTH(name), "Scan%03d", keynum);
// add the item to the device
devinfo->device()->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
}
}
bool handle_input_event(input_event eventid, void *eventdata) override
{
if (!input_enabled())
return FALSE;
KeyPressEventArgs *args = nullptr;
switch (eventid)
{
case INPUT_EVENT_KEYDOWN:
case INPUT_EVENT_KEYUP:
args = (KeyPressEventArgs*)eventdata;
for (int i = 0; i < devicelist()->size(); i++)
downcast<win32_keyboard_device*>(devicelist()->at(i))->queue_events(args, 1);
return TRUE;
default:
return FALSE;
}
}
};
//============================================================
// win32_mouse_device
//============================================================
struct win32_mouse_state
{
POINT last_point;
};
class win32_mouse_device : public event_based_device<MouseButtonEventArgs>
{
public:
mouse_state mouse;
win32_mouse_state win32_mouse;
win32_mouse_device(running_machine& machine, const char *name, input_module &module)
: event_based_device(machine, name, DEVICE_CLASS_MOUSE, module),
mouse({0}),
win32_mouse({{0}})
{
}
void poll() override
{
event_based_device::poll();
CURSORINFO cursor_info = {0};
cursor_info.cbSize = sizeof(CURSORINFO);
GetCursorInfo(&cursor_info);
// We only take over the mouse if the cursor isn't showing
// This should happen anyway in mouse mode
if (!(cursor_info.flags & CURSOR_SHOWING))
{
// We measure the position change from the previously set center position
mouse.lX = (cursor_info.ptScreenPos.x - win32_mouse.last_point.x) * INPUT_RELATIVE_PER_PIXEL;
mouse.lY = (cursor_info.ptScreenPos.y - win32_mouse.last_point.y) * INPUT_RELATIVE_PER_PIXEL;
RECT window_pos = {0};
GetWindowRect(win_window_list->m_hwnd, &window_pos);
// We reset the cursor position to the middle of the window each frame
win32_mouse.last_point.x = window_pos.left + (window_pos.right - window_pos.left) / 2;
win32_mouse.last_point.y = window_pos.top + (window_pos.bottom - window_pos.top) / 2;
SetCursorPos(win32_mouse.last_point.x, win32_mouse.last_point.y);
}
}
void reset() override
{
memset(&mouse, 0, sizeof(mouse));
memset(&win32_mouse, 0, sizeof(win32_mouse));
}
protected:
void process_event(MouseButtonEventArgs &args) override
{
// set the button state
mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
// Make sure we have a fresh mouse position on button down
if (args.keydown)
module().poll_if_necessary(machine());
}
};
//============================================================
// mouse_input_win32 - win32 mouse input module
//============================================================
class mouse_input_win32 : public wininput_module
{
public:
mouse_input_win32()
: wininput_module(OSD_MOUSEINPUT_PROVIDER, "win32")
{
}
virtual void input_init(running_machine &machine) override
{
win32_mouse_device *devinfo;
int axisnum, butnum;
if (!input_enabled() || !mouse_enabled())
return;
// allocate a device
devinfo = devicelist()->create_device<win32_mouse_device>(machine, "Win32 Mouse 1", *this);
if (devinfo == NULL)
return;
// populate the axes
for (axisnum = 0; axisnum < 2; axisnum++)
{
devinfo->device()->add_item(default_axis_name[axisnum], (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
}
// populate the buttons
for (butnum = 0; butnum < 2; butnum++)
{
devinfo->device()->add_item(default_button_name(butnum), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
}
}
bool handle_input_event(input_event eventid, void *eventdata) override
{
if (!input_enabled() || !mouse_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
return FALSE;
auto args = static_cast<MouseButtonEventArgs*>(eventdata);
for (int i = 0; i < devicelist()->size(); i++)
downcast<win32_mouse_device*>(devicelist()->at(i))->queue_events(args, 1);
return TRUE;
}
};
//============================================================
// win32_lightgun_device
//============================================================
class win32_lightgun_device : public event_based_device<MouseButtonEventArgs>
{
private:
BOOL m_lightgun_shared_axis_mode;
int m_gun_index;
public:
mouse_state mouse;
win32_lightgun_device(running_machine& machine, const char *name, input_module &module)
: event_based_device(machine, name, DEVICE_CLASS_LIGHTGUN, module),
m_lightgun_shared_axis_mode(FALSE),
m_gun_index(0)
{
m_lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun();
// Since we are about to be added to the list, the current size is the zero-based index of where we will be
m_gun_index = downcast<wininput_module&>(module).devicelist()->size();
}
void poll() override
{
event_based_device::poll();
INT32 xpos = 0, ypos = 0;
POINT mousepos;
// if we are using the shared axis hack, the data is updated via Windows messages only
if (m_lightgun_shared_axis_mode)
return;
// get the cursor position and transform into final results
GetCursorPos(&mousepos);
if (win_window_list != NULL)
{
RECT client_rect;
// get the position relative to the window
GetClientRect(win_window_list->m_hwnd, &client_rect);
ScreenToClient(win_window_list->m_hwnd, &mousepos);
// convert to absolute coordinates
xpos = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
ypos = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
}
// update the X/Y positions
mouse.lX = xpos;
mouse.lY = ypos;
}
void reset() override
{
memset(&mouse, 0, sizeof(mouse));
}
protected:
void process_event(MouseButtonEventArgs &args) override
{
// Are we in shared axis mode?
if (m_lightgun_shared_axis_mode)
{
handle_shared_axis_mode(args);
}
else
{
// In non-shared axis mode, just update the button state
mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
}
}
private:
void handle_shared_axis_mode(MouseButtonEventArgs &args)
{
int button = args.button;
// We only handle the first four buttons in shared axis mode
if (button > 3)
return;
// First gun doesn't handle buttons 2 & 3
if (button >= 2 && m_gun_index == 0)
return;
// Second gun doesn't handle buttons 0 & 1
if (button < 2 && m_gun_index == 1)
return;
// Adjust the button if we're the second lightgun
int logical_button = m_gun_index == 1 ? button - 2 : button;
// set the button state
mouse.rgbButtons[logical_button] = args.keydown ? 0x80 : 0x00;
if (args.keydown)
{
RECT client_rect;
POINT mousepos;
// get the position relative to the window
GetClientRect(win_window_list->m_hwnd, &client_rect);
mousepos.x = args.xpos;
mousepos.y = args.ypos;
ScreenToClient(win_window_list->m_hwnd, &mousepos);
// convert to absolute coordinates
mouse.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
mouse.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
}
}
};
//============================================================
// lightgun_input_win32 - win32 lightgun input module
//============================================================
class lightgun_input_win32 : public wininput_module
{
public:
lightgun_input_win32()
: wininput_module(OSD_LIGHTGUNINPUT_PROVIDER, "win32")
{
}
int init_internal() override
{
return 0;
}
virtual void input_init(running_machine &machine) override
{
int max_guns = downcast<windows_options&>(machine.options()).dual_lightgun() ? 2 : 1;
// allocate the lightgun devices
for (int gunnum = 0; gunnum < max_guns; gunnum++)
{
static const char *const gun_names[] = { "Win32 Gun 1", "Win32 Gun 2" };
win32_lightgun_device *devinfo;
int axisnum, butnum;
// allocate a device
devinfo = devicelist()->create_device<win32_lightgun_device>(machine, gun_names[gunnum], *this);
if (devinfo == NULL)
break;
// populate the axes
for (axisnum = 0; axisnum < 2; axisnum++)
{
devinfo->device()->add_item(default_axis_name[axisnum], (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
}
// populate the buttons
for (butnum = 0; butnum < 2; butnum++)
{
devinfo->device()->add_item(default_button_name(butnum), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
}
}
}
bool handle_input_event(input_event eventid, void* eventdata) override
{
if (!input_enabled() || !lightgun_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
return false;
for (int i = 0; i < devicelist()->size(); i++)
downcast<win32_lightgun_device*>(devicelist()->at(i))->queue_events(static_cast<MouseButtonEventArgs*>(eventdata), 1);
return true;
}
};
#else
MODULE_NOT_SUPPORTED(keyboard_input_win32, OSD_KEYBOARDINPUT_PROVIDER, "win32")
MODULE_NOT_SUPPORTED(mouse_input_win32, OSD_MOUSEINPUT_PROVIDER, "win32")
MODULE_NOT_SUPPORTED(lightgun_input_win32, OSD_LIGHTGUNINPUT_PROVIDER, "win32")
#endif
MODULE_DEFINITION(KEYBOARDINPUT_WIN32, keyboard_input_win32)
MODULE_DEFINITION(MOUSEINPUT_WIN32, mouse_input_win32)
MODULE_DEFINITION(LIGHTGUNINPUT_WIN32, lightgun_input_win32)