fix stuck keys on ubuntu and on focus loss #142

In the `OnKeyDown` event handler, check if the key is actually pressed
using `wxGetKeyState()`, because for some reason on Ubuntu 18
spurious events are generated when the key is not actually pressed.

Also, if a game is paused by the frontend while a key is being pressed,
the key will remain active for the game when unpaused. This is an
issue because the key will likely be released outside of the game zone;
therefore, we would not process the key release for the game itself.

The same bug happens if clicking outside of the game zone while
holding a key.

For the case of a directional key, this means a continuous movement
in the direction of the key pressed before the pause until the key
is pressed and released.
This commit is contained in:
Edênis Freindorfer Azevedo 2019-05-29 16:08:18 -03:00 committed by Rafael Kitover
parent 3d57750c16
commit b0ec84693e
2 changed files with 31 additions and 1 deletions

View File

@ -16,6 +16,9 @@
#include "filters.h"
#include "wxvbam.h"
// release all buttons currently pressed
static void clear_input_press();
int emulating;
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
@ -919,6 +922,12 @@ GameArea::~GameArea()
}
}
void GameArea::OnKillFocus(wxFocusEvent& ev)
{
clear_input_press();
ev.Skip(true);
}
void GameArea::Pause()
{
if (paused)
@ -932,6 +941,11 @@ void GameArea::Pause()
paused = was_paused = true;
// when the game is paused like this, we should not allow any
// input to remain pressed, because they could be released
// outside of the game zone and we would not know about it.
clear_input_press();
if (loaded != IMAGE_UNKNOWN)
soundPause();
}
@ -1022,6 +1036,9 @@ void GameArea::OnIdle(wxIdleEvent& event)
// the userdata is freed on disconnect/destruction
this->Connect(wxEVT_SIZE, wxSizeEventHandler(GameArea::OnSize), NULL, this);
// we need to check if the buttons stayed pressed when focus the panel
w->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(GameArea::OnKillFocus), NULL, this);
w->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
w->SetSize(wxSize(basic_width, basic_height));
@ -1141,6 +1158,16 @@ static uint32_t bmask[NUM_KEYS] = {
static wxJoyKeyBinding_v keys_pressed;
static void clear_input_press()
{
int i;
for (i = 0; i < 4; ++i)
{
joypress[i] = 0;
}
keys_pressed.clear();
}
struct game_key {
int player;
int key_num;
@ -1257,7 +1284,9 @@ static void draw_black_background(wxWindow* win) {
void GameArea::OnKeyDown(wxKeyEvent& ev)
{
if (process_key_press(true, ev.GetKeyCode(), ev.GetModifiers())) {
// check if the key is pressed indeed and then process it
wxKeyCode keyCode = (wxKeyCode)ev.GetKeyCode();
if (wxGetKeyState(keyCode) && process_key_press(true, ev.GetKeyCode(), ev.GetModifiers())) {
ev.Skip(false);
ev.StopPropagation();
wxWakeUpIdle();

View File

@ -621,6 +621,7 @@ protected:
void PaintEv(wxPaintEvent& ev);
void EraseBackground(wxEraseEvent& ev);
void OnSize(wxSizeEvent& ev);
void OnKillFocus(wxFocusEvent& ev);
#ifndef NO_FFMPEG
MediaRecorder snd_rec, vid_rec;