2013-09-14 20:20:57 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
#include <list>
|
2018-11-26 16:55:22 +01:00
|
|
|
#include "Utilities/mutex.h"
|
2018-06-07 09:59:27 +02:00
|
|
|
|
2016-02-01 22:51:09 +01:00
|
|
|
// TODO: HLE info (constants, structs, etc.) should not be available here
|
|
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
// is_supported
|
|
|
|
|
CELL_MOUSE_INFO_TABLET_NOT_SUPPORTED = 0,
|
|
|
|
|
CELL_MOUSE_INFO_TABLET_SUPPORTED = 1,
|
|
|
|
|
|
|
|
|
|
// mode
|
|
|
|
|
CELL_MOUSE_INFO_TABLET_MOUSE_MODE = 1,
|
|
|
|
|
CELL_MOUSE_INFO_TABLET_TABLET_MODE = 2,
|
|
|
|
|
};
|
|
|
|
|
|
2013-09-14 20:20:57 +02:00
|
|
|
enum MousePortStatus
|
|
|
|
|
{
|
2014-04-04 15:25:38 +02:00
|
|
|
CELL_MOUSE_STATUS_DISCONNECTED = 0x00000000,
|
|
|
|
|
CELL_MOUSE_STATUS_CONNECTED = 0x00000001,
|
2013-09-14 20:20:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum MouseDataUpdate
|
|
|
|
|
{
|
|
|
|
|
CELL_MOUSE_DATA_UPDATE = 1,
|
|
|
|
|
CELL_MOUSE_DATA_NON = 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum MouseButtonCodes
|
|
|
|
|
{
|
|
|
|
|
CELL_MOUSE_BUTTON_1 = 0x00000001,
|
|
|
|
|
CELL_MOUSE_BUTTON_2 = 0x00000002,
|
|
|
|
|
CELL_MOUSE_BUTTON_3 = 0x00000004,
|
|
|
|
|
CELL_MOUSE_BUTTON_4 = 0x00000008,
|
|
|
|
|
CELL_MOUSE_BUTTON_5 = 0x00000010,
|
|
|
|
|
CELL_MOUSE_BUTTON_6 = 0x00000020,
|
|
|
|
|
CELL_MOUSE_BUTTON_7 = 0x00000040,
|
|
|
|
|
CELL_MOUSE_BUTTON_8 = 0x00000080,
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-28 03:18:35 +02:00
|
|
|
static const u32 MAX_MICE = 127;
|
|
|
|
|
static const u32 MOUSE_MAX_DATA_LIST_NUM = 8;
|
|
|
|
|
static const u32 MOUSE_MAX_CODES = 64;
|
2013-09-14 20:20:57 +02:00
|
|
|
|
|
|
|
|
struct MouseInfo
|
|
|
|
|
{
|
|
|
|
|
u32 max_connect;
|
|
|
|
|
u32 now_connect;
|
|
|
|
|
u32 info;
|
2018-06-07 09:59:27 +02:00
|
|
|
u32 mode[MAX_MICE]; // TODO: tablet support
|
|
|
|
|
u32 tablet_is_supported[MAX_MICE]; // TODO: tablet support
|
2014-08-28 03:18:35 +02:00
|
|
|
u16 vendor_id[MAX_MICE];
|
|
|
|
|
u16 product_id[MAX_MICE];
|
|
|
|
|
u8 status[MAX_MICE];
|
2013-09-14 20:20:57 +02:00
|
|
|
};
|
|
|
|
|
|
2014-08-28 03:18:35 +02:00
|
|
|
struct MouseRawData
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
|
|
|
|
s32 len;
|
2014-08-28 03:18:35 +02:00
|
|
|
u8 data[MOUSE_MAX_CODES];
|
2013-09-14 20:20:57 +02:00
|
|
|
|
2014-08-28 03:18:35 +02:00
|
|
|
MouseRawData()
|
2013-09-14 20:20:57 +02:00
|
|
|
: len(0)
|
2019-01-02 16:12:01 +01:00
|
|
|
, data()
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-28 03:18:35 +02:00
|
|
|
struct MouseData
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
|
|
|
|
u8 update;
|
|
|
|
|
u8 buttons;
|
|
|
|
|
s8 x_axis;
|
|
|
|
|
s8 y_axis;
|
|
|
|
|
s8 wheel;
|
|
|
|
|
s8 tilt; // (TODO)
|
|
|
|
|
|
2014-08-28 03:18:35 +02:00
|
|
|
MouseData()
|
2013-09-14 20:20:57 +02:00
|
|
|
: update(0)
|
|
|
|
|
, buttons(0)
|
|
|
|
|
, x_axis(0)
|
|
|
|
|
, y_axis(0)
|
|
|
|
|
, wheel(0)
|
|
|
|
|
, tilt(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
struct MouseTabletData
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
s32 len;
|
|
|
|
|
u8 data[MOUSE_MAX_CODES];
|
2013-09-14 20:20:57 +02:00
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
MouseTabletData()
|
|
|
|
|
: len(0)
|
2019-01-02 16:12:01 +01:00
|
|
|
, data()
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
using MouseTabletDataList = std::list<MouseTabletData>;
|
|
|
|
|
using MouseDataList = std::list<MouseData>;
|
|
|
|
|
|
2013-09-14 20:20:57 +02:00
|
|
|
struct Mouse
|
|
|
|
|
{
|
2018-08-10 20:24:33 +02:00
|
|
|
s32 x_pos;
|
|
|
|
|
s32 y_pos;
|
2018-08-04 14:37:32 +02:00
|
|
|
u8 buttons; // actual mouse button positions
|
2013-09-14 20:20:57 +02:00
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
MouseTabletDataList m_tablet_datalist;
|
|
|
|
|
MouseDataList m_datalist;
|
2014-08-28 03:18:35 +02:00
|
|
|
MouseRawData m_rawdata;
|
2013-09-14 20:20:57 +02:00
|
|
|
|
|
|
|
|
Mouse()
|
2019-01-02 16:12:01 +01:00
|
|
|
: x_pos(0)
|
|
|
|
|
, y_pos(0)
|
|
|
|
|
, buttons(0)
|
|
|
|
|
, m_tablet_datalist()
|
|
|
|
|
, m_datalist()
|
2013-09-14 20:20:57 +02:00
|
|
|
, m_rawdata()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class MouseHandlerBase
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
MouseInfo m_info;
|
2014-03-31 16:18:44 +02:00
|
|
|
std::vector<Mouse> m_mice;
|
2018-08-04 14:37:32 +02:00
|
|
|
std::chrono::steady_clock::time_point last_update;
|
|
|
|
|
|
|
|
|
|
bool is_time_for_update(double elapsed_time = 10.0) // 4-10 ms, let's use 10 for now
|
|
|
|
|
{
|
|
|
|
|
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
|
|
|
|
double elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count() / 1000.0;
|
|
|
|
|
|
|
|
|
|
if (elapsed > elapsed_time)
|
|
|
|
|
{
|
|
|
|
|
last_update = now;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2013-09-14 20:20:57 +02:00
|
|
|
|
|
|
|
|
public:
|
2018-11-26 16:55:22 +01:00
|
|
|
shared_mutex mutex;
|
2018-08-04 14:37:32 +02:00
|
|
|
|
2016-02-01 22:51:09 +01:00
|
|
|
virtual void Init(const u32 max_connect) = 0;
|
2015-11-14 17:34:20 +01:00
|
|
|
virtual ~MouseHandlerBase() = default;
|
2013-09-14 20:20:57 +02:00
|
|
|
|
|
|
|
|
void Button(u8 button, bool pressed)
|
|
|
|
|
{
|
2018-09-03 21:28:33 +02:00
|
|
|
std::lock_guard lock(mutex);
|
2018-08-04 14:37:32 +02:00
|
|
|
|
|
|
|
|
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MouseDataList& datalist = GetDataList(p);
|
|
|
|
|
|
|
|
|
|
if (datalist.size() > MOUSE_MAX_DATA_LIST_NUM)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
datalist.pop_front();
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
if (pressed)
|
2018-08-04 14:37:32 +02:00
|
|
|
m_mice[p].buttons |= button;
|
2018-06-07 09:59:27 +02:00
|
|
|
else
|
2018-08-04 14:37:32 +02:00
|
|
|
m_mice[p].buttons &= ~button;
|
|
|
|
|
|
|
|
|
|
MouseData new_data;
|
|
|
|
|
new_data.update = CELL_MOUSE_DATA_UPDATE;
|
|
|
|
|
new_data.buttons = m_mice[p].buttons;
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
datalist.push_back(new_data);
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Scroll(const s8 rotation)
|
|
|
|
|
{
|
2018-09-03 21:28:33 +02:00
|
|
|
std::lock_guard lock(mutex);
|
2018-08-04 14:37:32 +02:00
|
|
|
|
|
|
|
|
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MouseDataList& datalist = GetDataList(p);
|
|
|
|
|
|
|
|
|
|
if (datalist.size() > MOUSE_MAX_DATA_LIST_NUM)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
datalist.pop_front();
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
MouseData new_data;
|
|
|
|
|
new_data.update = CELL_MOUSE_DATA_UPDATE;
|
|
|
|
|
new_data.wheel = rotation / 120; //120=event.GetWheelDelta()
|
2018-08-04 14:37:32 +02:00
|
|
|
new_data.buttons = m_mice[p].buttons;
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
datalist.push_back(new_data);
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 20:24:33 +02:00
|
|
|
void Move(const s32 x_pos_new, const s32 y_pos_new, const bool is_qt_fullscreen = false, s32 x_delta = 0, s32 y_delta = 0)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-09-03 21:28:33 +02:00
|
|
|
std::lock_guard lock(mutex);
|
2018-08-04 14:37:32 +02:00
|
|
|
|
|
|
|
|
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
|
2013-09-14 20:20:57 +02:00
|
|
|
{
|
2018-06-07 09:59:27 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2013-09-14 20:20:57 +02:00
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
MouseDataList& datalist = GetDataList(p);
|
2013-09-14 20:20:57 +02:00
|
|
|
|
2018-06-07 09:59:27 +02:00
|
|
|
if (datalist.size() > MOUSE_MAX_DATA_LIST_NUM)
|
|
|
|
|
{
|
|
|
|
|
datalist.pop_front();
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
MouseData new_data;
|
|
|
|
|
new_data.update = CELL_MOUSE_DATA_UPDATE;
|
2018-08-04 14:37:32 +02:00
|
|
|
new_data.buttons = m_mice[p].buttons;
|
2018-06-07 09:59:27 +02:00
|
|
|
|
2018-08-10 20:24:33 +02:00
|
|
|
if (!is_qt_fullscreen)
|
2018-08-04 14:37:32 +02:00
|
|
|
{
|
2018-08-10 20:24:33 +02:00
|
|
|
x_delta = x_pos_new - m_mice[p].x_pos;
|
|
|
|
|
y_delta = y_pos_new - m_mice[p].y_pos;
|
2018-08-04 14:37:32 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-10 20:24:33 +02:00
|
|
|
new_data.x_axis = static_cast<s8>(std::clamp(x_delta, -127, 128));
|
|
|
|
|
new_data.y_axis = static_cast<s8>(std::clamp(y_delta, -127, 128));
|
|
|
|
|
|
|
|
|
|
m_mice[p].x_pos = x_pos_new;
|
|
|
|
|
m_mice[p].y_pos = y_pos_new;
|
2018-06-07 09:59:27 +02:00
|
|
|
|
|
|
|
|
/*CellMouseRawData& rawdata = GetRawData(p);
|
|
|
|
|
rawdata.data[rawdata.len % CELL_MOUSE_MAX_CODES] = 0; // (TODO)
|
|
|
|
|
rawdata.len++;*/
|
|
|
|
|
|
|
|
|
|
datalist.push_back(new_data);
|
2013-09-14 20:20:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MouseInfo& GetInfo() { return m_info; }
|
2014-03-31 16:18:44 +02:00
|
|
|
std::vector<Mouse>& GetMice() { return m_mice; }
|
2018-06-07 09:59:27 +02:00
|
|
|
MouseDataList& GetDataList(const u32 mouse) { return m_mice[mouse].m_datalist; }
|
|
|
|
|
MouseTabletDataList& GetTabletDataList(const u32 mouse) { return m_mice[mouse].m_tablet_datalist; }
|
2014-08-28 03:18:35 +02:00
|
|
|
MouseRawData& GetRawData(const u32 mouse) { return m_mice[mouse].m_rawdata; }
|
2015-09-26 22:46:04 +02:00
|
|
|
};
|