Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt: implement first Mouse Movement for keyboard pad handler #4957

Merged
merged 4 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
163 changes: 161 additions & 2 deletions rpcs3/keyboard_pad_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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_Y:
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);
}

Expand All @@ -241,6 +299,75 @@ 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 && m_target->isActive())
{
// get the screen dimensions
const QSize screen = m_target->size();

// get the center of the screen in global coordinates
QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2);

// reset the mouse to the center for consistent results since edge movement won't be registered
QCursor::setPos(m_target->screen(), p_center);

// convert the center into screen coordinates
p_center = m_target->mapFromGlobal(p_center);

// get the delta of the mouse position to the screen center
const QPoint p_delta = event->pos() - p_center;

movement_x = p_delta.x();
movement_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;
Expand Down Expand Up @@ -454,5 +581,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;
}
}
}
}
24 changes: 24 additions & 0 deletions rpcs3/keyboard_pad_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -52,6 +65,7 @@ class keyboard_pad_handler final : public QObject, public PadHandlerBase
void keyReleaseEvent(QKeyEvent* event);
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);

bool eventFilter(QObject* obj, QEvent* ev) override;

Expand All @@ -77,4 +91,14 @@ class keyboard_pad_handler final : public QObject, public PadHandlerBase
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;
};
62 changes: 60 additions & 2 deletions rpcs3/rpcs3qt/pad_settings_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
}
Expand Down
6 changes: 5 additions & 1 deletion rpcs3/rpcs3qt/pad_settings_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ private Q_SLOTS:
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;

Expand All @@ -147,6 +150,7 @@ private Q_SLOTS:
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;
};