Qt: implement first Mouse Movement for keyboard pad handler

This commit is contained in:
Megamouse 2018-08-05 19:03:57 +02:00
parent 685eaedbf9
commit 1fbd918d59
4 changed files with 238 additions and 5 deletions

View File

@ -8,6 +8,11 @@ constexpr auto qstr = QString::fromStdString;
bool keyboard_pad_handler::Init()
{
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
m_last_mouse_move_left = now;
m_last_mouse_move_right = now;
m_last_mouse_move_up = now;
m_last_mouse_move_down = now;
return true;
}
@ -75,11 +80,13 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
bool is_max = pad->m_sticks[i].m_keyCodeMax == code;
bool is_min = pad->m_sticks[i].m_keyCodeMin == code;
u16 normalized_value = std::max(u16(1), static_cast<u16>(std::floor((double)value / 2.0)));
if (is_max)
m_stick_max[i] = pressed ? 255 : 128;
m_stick_max[i] = pressed ? 128 + normalized_value : 128;
if (is_min)
m_stick_min[i] = pressed ? 128 : 0;
m_stick_min[i] = pressed ? normalized_value : 0;
if (is_max || is_min)
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
@ -136,6 +143,9 @@ bool keyboard_pad_handler::eventFilter(QObject* target, QEvent* ev)
case QEvent::MouseButtonRelease:
mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
break;
case QEvent::MouseMove:
mouseMoveEvent(static_cast<QMouseEvent*>(ev));
break;
default:
break;
}
@ -221,6 +231,54 @@ void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed)
void keyboard_pad_handler::keyPressEvent(QKeyEvent* event)
{
if (event->modifiers() & Qt::AltModifier)
{
switch (event->key())
{
case Qt::Key_I:
m_deadzone_y = std::min(m_deadzone_y + 1, 255);
LOG_SUCCESS(GENERAL, "mouse move adjustment: deadzone y = %d", m_deadzone_y);
event->ignore();
return;
case Qt::Key_U:
m_deadzone_y = std::max(0, m_deadzone_y - 1);
LOG_SUCCESS(GENERAL, "mouse move adjustment: deadzone y = %d", m_deadzone_y);
event->ignore();
return;
case Qt::Key_Z:
m_deadzone_x = std::min(m_deadzone_x + 1, 255);
LOG_SUCCESS(GENERAL, "mouse move adjustment: deadzone x = %d", m_deadzone_x);
event->ignore();
return;
case Qt::Key_T:
m_deadzone_x = std::max(0, m_deadzone_x - 1);
LOG_SUCCESS(GENERAL, "mouse move adjustment: deadzone x = %d", m_deadzone_x);
event->ignore();
return;
case Qt::Key_K:
m_multi_y = std::min(m_multi_y + 0.1, 5.0);
LOG_SUCCESS(GENERAL, "mouse move adjustment: multiplier y = %.2f", m_multi_y);
event->ignore();
return;
case Qt::Key_J:
m_multi_y = std::max(0.0, m_multi_y - 0.1);
LOG_SUCCESS(GENERAL, "mouse move adjustment: multiplier y = %.2f", m_multi_y);
event->ignore();
return;
case Qt::Key_H:
m_multi_x = std::min(m_multi_x + 0.1, 5.0);
LOG_SUCCESS(GENERAL, "mouse move adjustment: multiplier x = %.2f", m_multi_x);
event->ignore();
return;
case Qt::Key_G:
m_multi_x = std::max(0.0, m_multi_x - 0.1);
LOG_SUCCESS(GENERAL, "mouse move adjustment: multiplier x = %.2f", m_multi_x);
event->ignore();
return;
default:
break;
}
}
processKeyEvent(event, 1);
}
@ -241,6 +299,63 @@ void keyboard_pad_handler::mouseReleaseEvent(QMouseEvent* event)
event->ignore();
}
void keyboard_pad_handler::mouseMoveEvent(QMouseEvent* event)
{
static int movement_x = 0;
static int movement_y = 0;
static int last_pos_x = 0;
static int last_pos_y = 0;
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);
movement_x = event->x() - p_delta.x();
movement_y = event->y() - p_delta.y();
}
else
{
movement_x = event->x() - last_pos_x;
movement_y = event->y() - last_pos_y;
last_pos_x = event->x();
last_pos_y = event->y();
}
movement_x = m_multi_x * (double)movement_x;
movement_y = m_multi_y * (double)movement_y;
if (movement_x < 0)
{
Key(mouse::move_right, 0);
Key(mouse::move_left, 1, std::min(m_deadzone_x + std::abs(movement_x), 255));
m_last_mouse_move_left = std::chrono::steady_clock::now();
}
else if (movement_x > 0)
{
Key(mouse::move_left, 0);
Key(mouse::move_right, 1, std::min(m_deadzone_x + movement_x, 255));
m_last_mouse_move_right = std::chrono::steady_clock::now();
}
// in Qt mouse up is equivalent to movement_y < 0
if (movement_y < 0)
{
Key(mouse::move_down, 0);
Key(mouse::move_up, 1, std::min(m_deadzone_y + std::abs(movement_y), 255));
m_last_mouse_move_up = std::chrono::steady_clock::now();
}
else if (movement_y > 0)
{
Key(mouse::move_up, 0);
Key(mouse::move_down, 1, std::min(m_deadzone_y + movement_y, 255));
m_last_mouse_move_down = std::chrono::steady_clock::now();
}
event->ignore();
}
std::vector<std::string> keyboard_pad_handler::ListDevices()
{
std::vector<std::string> list_devices;
@ -454,5 +569,37 @@ void keyboard_pad_handler::ThreadProc()
last_connection_status[i] = true;
connected++;
}
else
{
static std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
now = std::chrono::steady_clock::now();
double elapsed_left = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_left).count() / 1000.0;
double elapsed_right = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_right).count() / 1000.0;
double elapsed_up = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_up).count() / 1000.0;
double elapsed_down = std::chrono::duration_cast<std::chrono::microseconds>(now - m_last_mouse_move_down).count() / 1000.0;
// roughly 1-2 frames to process the next mouse move
if (elapsed_left > 30.0)
{
Key(mouse::move_left, 0);
m_last_mouse_move_left = now;
}
if (elapsed_right > 30.0)
{
Key(mouse::move_right, 0);
m_last_mouse_move_right = now;
}
if (elapsed_up> 30.0)
{
Key(mouse::move_up, 0);
m_last_mouse_move_up = now;
}
if (elapsed_down > 30.0)
{
Key(mouse::move_down, 0);
m_last_mouse_move_down = now;
}
}
}
}

View File

@ -6,6 +6,14 @@
#include <QWindow>
#include <QKeyEvent>
enum mouse
{
move_left = 0x05555550,
move_right = 0x05555551,
move_up = 0x05555552,
move_down = 0x05555553
};
class keyboard_pad_handler final : public QObject, public PadHandlerBase
{
// Unique button names for the config files and our pad settings dialog
@ -39,6 +47,11 @@ class keyboard_pad_handler final : public QObject, public PadHandlerBase
{ Qt::ExtraButton22 , "Mouse 22" },
{ Qt::ExtraButton23 , "Mouse 23" },
{ Qt::ExtraButton24 , "Mouse 24" },
{ mouse::move_left , "Mouse MLeft" },
{ mouse::move_right , "Mouse MRight" },
{ mouse::move_up , "Mouse MUp" },
{ mouse::move_down , "Mouse MDown" },
};
public:
@ -52,6 +65,7 @@ public:
void keyReleaseEvent(QKeyEvent* event);
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
bool eventFilter(QObject* obj, QEvent* ev) override;
@ -77,4 +91,14 @@ private:
std::vector<std::shared_ptr<Pad>> bindings;
u8 m_stick_min[4] = { 0, 0, 0, 0 };
u8 m_stick_max[4] = { 128, 128, 128, 128 };
// Mouse Movements
std::chrono::steady_clock::time_point m_last_mouse_move_left;
std::chrono::steady_clock::time_point m_last_mouse_move_right;
std::chrono::steady_clock::time_point m_last_mouse_move_up;
std::chrono::steady_clock::time_point m_last_mouse_move_down;
int m_deadzone_x = 60;
int m_deadzone_y = 60;
double m_multi_x = 2;
double m_multi_y = 2.5;
};

View File

@ -456,6 +456,7 @@ void pad_settings_dialog::ReactivateButtons()
if (m_padButtons->button(m_button_id))
{
m_padButtons->button(m_button_id)->setPalette(m_palette);
m_padButtons->button(m_button_id)->releaseMouse();
}
m_button_id = button_ids::id_pad_begin;
@ -528,7 +529,7 @@ void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
ReactivateButtons();
}
void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
void pad_settings_dialog::mouseReleaseEvent(QMouseEvent* event)
{
if (m_handler->m_type != pad_handler::keyboard)
{
@ -553,13 +554,67 @@ void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
ReactivateButtons();
}
void pad_settings_dialog::mouseMoveEvent(QMouseEvent* event)
{
if (m_handler->m_type != pad_handler::keyboard)
{
return;
}
if (m_button_id == button_ids::id_pad_begin)
{
return;
}
if (m_button_id <= button_ids::id_pad_begin || m_button_id >= button_ids::id_pad_end)
{
LOG_NOTICE(HLE, "Pad Settings: Handler Type: %d, Unknown button ID: %d", static_cast<int>(m_handler->m_type), m_button_id);
}
else
{
QPoint mouse_pos = QCursor::pos();
int delta_x = mouse_pos.x() - m_last_pos.x();
int delta_y = mouse_pos.y() - m_last_pos.y();
u32 key = 0;
if (delta_x > 100)
{
key = mouse::move_right;
}
else if (delta_x < -100)
{
key = mouse::move_left;
}
else if (delta_y > 100)
{
key = mouse::move_down;
}
else if (delta_y < -100)
{
key = mouse::move_up;
}
if (key != 0)
{
m_cfg_entries[m_button_id].key = ((keyboard_pad_handler*)m_handler.get())->GetMouseName(key);
m_cfg_entries[m_button_id].text = qstr(m_cfg_entries[m_button_id].key);
ReactivateButtons();
}
}
}
bool pad_settings_dialog::eventFilter(QObject* object, QEvent* event)
{
// Disabled buttons should not absorb mouseclicks
if (event->type() == QEvent::MouseButtonPress)
if (event->type() == QEvent::MouseButtonRelease)
{
event->ignore();
}
if (event->type() == QEvent::MouseMove)
{
mouseMoveEvent((QMouseEvent*)event);
}
return QDialog::eventFilter(object, event);
}
@ -637,9 +692,12 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
ui->chooseHandler->setFocusPolicy(Qt::ClickFocus);
ui->chooseDevice->setFocusPolicy(Qt::ClickFocus);
m_last_pos = QCursor::pos();
m_button_id = id;
m_padButtons->button(m_button_id)->setText(tr("[ Waiting %1 ]").arg(MAX_SECONDS));
m_padButtons->button(m_button_id)->setPalette(QPalette(Qt::blue));
m_padButtons->button(m_button_id)->grabMouse();
SwitchButtons(false); // disable all buttons, needed for using Space, Enter and other specific buttons
m_timer.start(1000);
}

View File

@ -122,6 +122,9 @@ private:
int m_seconds = MAX_SECONDS;
QTimer m_timer;
// Mouse Move
QPoint m_last_pos;
// Input timer. Its Callback handles the input
QTimer m_timer_input;
@ -147,6 +150,7 @@ private:
protected:
/** Handle keyboard handler input */
void keyPressEvent(QKeyEvent *keyEvent) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
bool eventFilter(QObject* object, QEvent* event) override;
};