Skip to content

Commit

Permalink
fix stuck keys on ubuntu and on focus loss #142
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
denisfa authored and rkitover committed May 29, 2019
1 parent 3d57750 commit b0ec846
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
31 changes: 30 additions & 1 deletion src/wx/panel.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -919,6 +922,12 @@ GameArea::~GameArea()
}
}

void GameArea::OnKillFocus(wxFocusEvent& ev)
{
clear_input_press();
ev.Skip(true);
}

void GameArea::Pause()
{
if (paused)
Expand All @@ -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();
}
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/wx/wxvbam.h
Expand Up @@ -621,6 +621,7 @@ class GameArea : public wxPanel, public HiDPIAware {
void PaintEv(wxPaintEvent& ev);
void EraseBackground(wxEraseEvent& ev);
void OnSize(wxSizeEvent& ev);
void OnKillFocus(wxFocusEvent& ev);

#ifndef NO_FFMPEG
MediaRecorder snd_rec, vid_rec;
Expand Down

0 comments on commit b0ec846

Please sign in to comment.