fix cellMouse lag + fullscreen mouse

This commit is contained in:
Megamouse 2018-08-04 14:37:32 +02:00
parent aaea9d6946
commit 1a5b950d8b
3 changed files with 83 additions and 26 deletions

View file

@ -4,6 +4,9 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/Io/MouseHandler.h"
#include "Utilities/sema.h"
#include "cellMouse.h"
extern logs::channel sys_io;
@ -159,6 +162,8 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
semaphore_lock lock(handler->mutex);
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
@ -168,7 +173,15 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
// TODO: check if (current_info.mode[port_no] != CELL_MOUSE_INFO_TABLET_MOUSE_MODE) has any impact
MouseData& current_data = handler->GetDataList(port_no).front();
MouseDataList& data_list = handler->GetDataList(port_no);
if (data_list.size() == 0)
{
*data = {};
return CELL_OK;
}
const MouseData current_data = data_list.front();
data->update = current_data.update;
data->buttons = current_data.buttons;
data->x_axis = current_data.x_axis;
@ -176,10 +189,7 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
data->wheel = current_data.wheel;
data->tilt = current_data.tilt;
current_data.update = CELL_MOUSE_DATA_NON;
current_data.x_axis = 0;
current_data.y_axis = 0;
current_data.wheel = 0;
data_list.pop_front();
return CELL_OK;
}
@ -200,6 +210,8 @@ s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
semaphore_lock lock(handler->mutex);
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
@ -221,13 +233,10 @@ s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
data->list[i].y_axis = it->y_axis;
data->list[i].wheel = it->wheel;
data->list[i].tilt = it->tilt;
it->update = CELL_MOUSE_DATA_NON;
it->x_axis = 0;
it->y_axis = 0;
it->wheel = 0;
}
list.clear();
return CELL_OK;
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <list>
#include "Utilities/sema.h"
// TODO: HLE info (constants, structs, etc.) should not be available here
@ -108,6 +109,7 @@ struct Mouse
{
s16 x_pos;
s16 y_pos;
u8 buttons; // actual mouse button positions
MouseTabletDataList m_tablet_datalist;
MouseDataList m_datalist;
@ -127,14 +129,32 @@ class MouseHandlerBase
protected:
MouseInfo m_info;
std::vector<Mouse> m_mice;
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;
}
public:
semaphore<> mutex;
virtual void Init(const u32 max_connect) = 0;
virtual ~MouseHandlerBase() = default;
void Button(u8 button, bool pressed)
{
for(u32 p=0; p < (u32)m_mice.size(); ++p)
semaphore_lock lock(mutex);
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
{
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
{
@ -148,13 +168,14 @@ public:
datalist.pop_front();
}
if (pressed)
m_mice[p].buttons |= button;
else
m_mice[p].buttons &= ~button;
MouseData new_data;
new_data.update = CELL_MOUSE_DATA_UPDATE;
if (pressed)
new_data.buttons |= button;
else
new_data.buttons &= ~button;
new_data.buttons = m_mice[p].buttons;
datalist.push_back(new_data);
}
@ -162,7 +183,9 @@ public:
void Scroll(const s8 rotation)
{
for(u32 p=0; p < (u32)m_mice.size(); ++p)
semaphore_lock lock(mutex);
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
{
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
{
@ -179,14 +202,17 @@ public:
MouseData new_data;
new_data.update = CELL_MOUSE_DATA_UPDATE;
new_data.wheel = rotation / 120; //120=event.GetWheelDelta()
new_data.buttons = m_mice[p].buttons;
datalist.push_back(new_data);
}
}
void Move(const s16 x_pos_new, const s16 y_pos_new)
void Move(const s32 x_pos_new, const s32 y_pos_new, bool is_qt_fullscreen = false)
{
for(u32 p=0; p < (u32)m_mice.size(); ++p)
semaphore_lock lock(mutex);
for (u32 p = 0; p < (u32)m_mice.size(); ++p)
{
if (m_info.status[p] != CELL_MOUSE_STATUS_CONNECTED)
{
@ -202,11 +228,21 @@ public:
MouseData new_data;
new_data.update = CELL_MOUSE_DATA_UPDATE;
new_data.x_axis += x_pos_new - m_mice[p].x_pos;
new_data.y_axis += y_pos_new - m_mice[p].y_pos;
new_data.buttons = m_mice[p].buttons;
m_mice[p].x_pos = x_pos_new;
m_mice[p].y_pos = y_pos_new;
if (is_qt_fullscreen)
{
new_data.x_axis = static_cast<s8>(std::clamp(x_pos_new, -127, 128));
new_data.y_axis = static_cast<s8>(std::clamp(y_pos_new, -127, 128));
}
else
{
new_data.x_axis = static_cast<s8>(std::clamp(x_pos_new - m_mice[p].x_pos, -127, 128));
new_data.y_axis = static_cast<s8>(std::clamp(y_pos_new - m_mice[p].y_pos, -127, 128));
m_mice[p].x_pos = x_pos_new;
m_mice[p].y_pos = y_pos_new;
}
/*CellMouseRawData& rawdata = GetRawData(p);
rawdata.data[rawdata.len % CELL_MOUSE_MAX_CODES] = 0; // (TODO)

View file

@ -1,6 +1,7 @@
#include "basic_mouse_handler.h"
#include <QApplication>
#include <QCursor>
void basic_mouse_handler::Init(const u32 max_connect)
{
@ -83,11 +84,22 @@ void basic_mouse_handler::MouseButtonUp(QMouseEvent* event)
void basic_mouse_handler::MouseScroll(QWheelEvent* event)
{
// Woo lads, Qt handles multidimensional scrolls. Just gonna grab the x for now. Not sure if this works. TODO: Test
MouseHandlerBase::Scroll(event->angleDelta().x());
MouseHandlerBase::Scroll(event->angleDelta().y());
}
void basic_mouse_handler::MouseMove(QMouseEvent* event)
{
MouseHandlerBase::Move(event->x(), event->y());
if (is_time_for_update())
{
if (m_target && m_target->visibility() == QWindow::Visibility::FullScreen)
{
QPoint p_delta = m_target->geometry().topLeft() + QPoint(m_target->width() / 2, m_target->height() / 2);
QCursor::setPos(p_delta);
MouseHandlerBase::Move(event->x() - p_delta.x(), event->y() - p_delta.y(), true);
}
else
{
MouseHandlerBase::Move(event->x(), event->y());
}
}
}