Skip to content

Commit

Permalink
fix kbd controls on Mac + misc.
Browse files Browse the repository at this point in the history
After creating the drawing panel, call SetFocus() on it and use
Connect() to bind keyboard events from it. Add the wxWANTS_CHARS flag to
all DrawingArea subclasses so that wxEVT_CHAR_HOOK can be used instead
of wxEVT_KEY_DOWN, because it is more general and catches more keys.

Change the process_key_press function to return a bool indicating
whether a game control is currently pressed or not, this is used in the
key events to determine whether the event should be propagated or not.
If in a game key, do not propagate the event, otherwise it hits one of
the other controls and generates a beep sound.

The menu open/closed/highlighted events had to be turned off for Mac,
because the menubar is catching all keyboard events for some reason even
before they reach the drawing panel event handler. So on Mac the game
will not be paused when the menu is being used, this is not really a big
deal and can be fixed later.

Other improvements:

* do not bundle and link dylibs when CMAKE_BUILD_TYPE is not "Release",
  this makes for quicker debug builds

* finally make a generic PaintEv for the DrawingPanel abstract base
  class using dynamic_cast<> and Bind(), unfortunately this is not wx
  2.8 compatible

* set the default audio_buffers to 10 instead of 5, this completely or
  almost completely fixes sound stuttering during normal game play on
  Mac with OpenAL

* spew path info on startup only once
  • Loading branch information
rkitover committed Nov 3, 2016
1 parent e609bb9 commit a775cc4
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 69 deletions.
8 changes: 6 additions & 2 deletions src/wx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,12 @@ if(APPLE)
SET(MACOSX_BUNDLE_ICON_FILE ${VBAM_ICON})
SET_SOURCE_FILES_PROPERTIES(${VBAM_ICON_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

ADD_CUSTOM_COMMAND(TARGET visualboyadvance-m POST_BUILD
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/osx/third_party_libs_tool "$<TARGET_FILE_DIR:visualboyadvance-m>/../..")
# budle dylibs and relink them for releasing .app
# but only in Release mode
IF(CMAKE_BUILD_TYPE STREQUAL "Release")
ADD_CUSTOM_COMMAND(TARGET visualboyadvance-m POST_BUILD
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/osx/third_party_libs_tool "$<TARGET_FILE_DIR:visualboyadvance-m>/../..")
ENDIF()
endif(APPLE)

SET(WX_EXE_NAME visualboyadvance-m-wx${CMAKE_EXECUTABLE_SUFFIX})
20 changes: 0 additions & 20 deletions src/wx/drawing.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,9 @@ class BasicDrawingPanel : public DrawingPanel, public wxPanel {
BasicDrawingPanel(wxWindow* parent, int _width, int _height);

protected:
void PaintEv2(wxPaintEvent& ev)
{
PaintEv(ev);
}
void DrawArea(wxWindowDC& dc);

DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};

#ifndef NO_OGL
Expand All @@ -27,10 +22,6 @@ class GLDrawingPanel : public DrawingPanel, public wxGLCanvas {
virtual ~GLDrawingPanel();

protected:
void PaintEv2(wxPaintEvent& ev)
{
PaintEv(ev);
}
void DrawArea(wxWindowDC& dc);
#if wxCHECK_VERSION(2, 9, 0)
wxGLContext* ctx;
Expand All @@ -40,7 +31,6 @@ class GLDrawingPanel : public DrawingPanel, public wxGLCanvas {
int texsize;

DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif

Expand All @@ -50,15 +40,10 @@ class DXDrawingPanel : public DrawingPanel, public wxPanel {
DXDrawingPanel(wxWindow* parent, int _width, int _height);

protected:
void PaintEv2(wxPaintEvent& ev)
{
PaintEv(ev);
}
void DrawArea(wxWindowDC&);
void DrawingPanelInit();

DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif

Expand All @@ -71,15 +56,10 @@ class CairoDrawingPanel : public DrawingPanel, public wxPanel {
~CairoDrawingPanel();

protected:
void PaintEv2(wxPaintEvent& ev)
{
PaintEv(ev);
}
void DrawArea(wxWindowDC&);
cairo_surface_t* conv_surf;

DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif

Expand Down
5 changes: 4 additions & 1 deletion src/wx/opts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,10 @@ opts_t::opts_t()
if (max_threads < 0)
max_threads = 2;

audio_buffers = 5;
// 10 fixes stuttering on mac with openal, as opposed to 5
// also should be better for modern hardware in general
audio_buffers = 10;

sound_en = 0x30f;
sound_vol = 100;
sound_qual = 1;
Expand Down
66 changes: 35 additions & 31 deletions src/wx/panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,6 @@ void GameArea::OnIdle(wxIdleEvent& event)

wxWindow* w = panel->GetWindow();
w->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
w->Enable(false); // never give it the keyboard focus
w->SetSize(wxSize(basic_width, basic_height));

if (maxScale)
Expand All @@ -1045,6 +1044,13 @@ void GameArea::OnIdle(wxIdleEvent& event)
// if user changed Display/Scale config, this needs to run
AdjustMinSize();
AdjustSize(false);

// set focus to panel
w->SetFocus();

// capture keyboard events
w->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(GameArea::OnKeyDown), NULL, this);
w->Connect(wxEVT_KEY_UP, wxKeyEventHandler(GameArea::OnKeyUp), NULL, this);
}

if (!paused && (!pauseWhenInactive || wxGetApp().frame->HasFocus())) {
Expand Down Expand Up @@ -1125,8 +1131,10 @@ static uint32_t bmask[NUM_KEYS] = {

static wxJoyKeyBinding_v keys_pressed;

static void process_key_press(bool down, int key, int mod, int joy = 0)
static bool process_key_press(bool down, int key, int mod, int joy = 0)
{
static bool in_game_key = false;

// check if key is already pressed
int kpno;

Expand All @@ -1137,14 +1145,14 @@ static void process_key_press(bool down, int key, int mod, int joy = 0)
if (kpno < keys_pressed.size()) {
// double press is noop
if (down)
return;
return in_game_key;

// otherwise forget it
keys_pressed.erase(keys_pressed.begin() + kpno);
} else {
// double release is noop
if (!down)
return;
return in_game_key;

// otherwise remember it
// c++0x
Expand All @@ -1153,15 +1161,19 @@ static void process_key_press(bool down, int key, int mod, int joy = 0)
keys_pressed.push_back(jb);
}

bool matched_game_key = false;

// find all game keys this is bound to
for (int i = 0; i < 4; i++)
for (int j = 0; j < NUM_KEYS; j++) {
wxJoyKeyBinding_v& b = gopts.joykey_bindings[i][j];

for (int k = 0; k < b.size(); k++)
if (b[k].key == key && b[k].mod == mod && b[k].joy == joy) {
if (down)
if (down) {
joypress[i] |= bmask[j];
matched_game_key = true;
}
else {
// only release if no others pressed
int k2;
Expand All @@ -1178,25 +1190,29 @@ static void process_key_press(bool down, int key, int mod, int joy = 0)
break;
}

if (k2 == b.size())
if (k2 == b.size()) {
joypress[i] &= ~bmask[j];
matched_game_key = true;
}
}

break;
}
}

in_game_key = matched_game_key;

return in_game_key;
}

void GameArea::OnKeyDown(wxKeyEvent& ev)
{
process_key_press(true, ev.GetKeyCode(), 0 /* ev.GetModifiers() */);
ev.Skip(); // process accelerators
ev.Skip(!process_key_press(true, ev.GetKeyCode(), 0 /* ev.GetModifiers() */));
}

void GameArea::OnKeyUp(wxKeyEvent& ev)
{
process_key_press(false, ev.GetKeyCode(), 0 /* ev.GetModifiers() */);
ev.Skip(); // process accelerators
ev.Skip(!process_key_press(false, ev.GetKeyCode(), 0 /* ev.GetModifiers() */));
}

void GameArea::OnSDLJoy(wxSDLJoyEvent& ev)
Expand Down Expand Up @@ -1378,6 +1394,11 @@ DrawingPanel::DrawingPanel(int _width, int _height)

void DrawingPanel::DrawingPanelInit()
{
wxWindow* w = dynamic_cast<wxWindow*>(this);

// this is not 2.8 compatible, sorry
w->Bind(wxEVT_PAINT, &DrawingPanel::PaintEv, this);

did_init = true;
}

Expand Down Expand Up @@ -1894,13 +1915,9 @@ DrawingPanel::~DrawingPanel()

IMPLEMENT_CLASS2(BasicDrawingPanel, DrawingPanel, wxPanel)

BEGIN_EVENT_TABLE(BasicDrawingPanel, wxPanel)
EVT_PAINT(BasicDrawingPanel::PaintEv2)
END_EVENT_TABLE()

BasicDrawingPanel::BasicDrawingPanel(wxWindow* parent, int _width, int _height)
: wxPanel(parent, wxID_ANY, wxPoint(0, 0), parent->GetSize(),
wxFULL_REPAINT_ON_RESIZE)
wxFULL_REPAINT_ON_RESIZE | wxWANTS_CHARS)
, DrawingPanel(_width, _height)
{
// wxImage is 24-bit RGB, so 24-bit is preferred. Filters require
Expand Down Expand Up @@ -1980,11 +1997,6 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)

IMPLEMENT_CLASS2(GLDrawingPanel, DrawingPanel, wxGLCanvas)

// this would be easier in 2.9
BEGIN_EVENT_TABLE(GLDrawingPanel, wxGLCanvas)
EVT_PAINT(GLDrawingPanel::PaintEv2)
END_EVENT_TABLE()

// This is supposed to be the default, but DOUBLEBUFFER doesn't seem to be
// turned on by default for wxGTK.
static int glopts[] = {
Expand All @@ -2001,7 +2013,7 @@ static int glopts[] = {

GLDrawingPanel::GLDrawingPanel(wxWindow* parent, int _width, int _height)
: glc(parent, wxID_ANY, glopts, wxPoint(0, 0), parent->GetSize(),
wxFULL_REPAINT_ON_RESIZE)
wxFULL_REPAINT_ON_RESIZE | wxWANTS_CHARS)
, DrawingPanel(_width, _height)
{
#ifdef __WXMAC__
Expand Down Expand Up @@ -2166,13 +2178,9 @@ void GLDrawingPanel::DrawArea(wxWindowDC& dc)

IMPLEMENT_CLASS(CairoDrawingPanel, DrawingPanel)

BEGIN_EVENT_TABLE(CairoDrawingPanel, wxPanel)
EVT_PAINT(CairoDrawingPanel::PaintEv2)
END_EVENT_TABLE()

CairoDrawingPanel::CairoDrawingPanel(wxWindow* parent, int _width, int _height)
: wxPanel(parent, wxID_ANY, wxPoint(0, 0), parent->GetSize(),
wxFULL_REPAINT_ON_RESIZE)
wxFULL_REPAINT_ON_RESIZE | wxWANTS_CHARS)
, DrawingPanel(_width, _height)
{
conv_surf = NULL;
Expand Down Expand Up @@ -2295,13 +2303,9 @@ void CairoDrawingPanel::DrawArea(wxWindowDC& dc)

IMPLEMENT_CLASS(DXDrawingPanel, DrawingPanel)

BEGIN_EVENT_TABLE(DXDrawingPanel, wxPanel)
EVT_PAINT(DXDrawingPanel::PaintEv2)
END_EVENT_TABLE()

DXDrawingPanel::DXDrawingPanel(wxWindow* parent, int _width, int _height)
: wxPanel(parent, wxID_ANY, wxPoint(0, 0), parent->GetSize(),
wxFULL_REPAINT_ON_RESIZE)
wxFULL_REPAINT_ON_RESIZE | wxWANTS_CHARS)
, DrawingPanel(_width, _height)
{
// FIXME: implement
Expand Down
26 changes: 19 additions & 7 deletions src/wx/wxvbam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,19 @@ static void get_config_path(wxPathList& path, bool exists = true)
path.Add(s); \
} while (0)

vbamDebug("GetUserLocalDataDir(): %s", static_cast<const char*>(stdp.GetUserLocalDataDir().utf8_str()));
vbamDebug("GetUserDataDir(): %s", static_cast<const char*>(stdp.GetUserDataDir().utf8_str()));
vbamDebug("GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()): %s", static_cast<const char*>(stdp.GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()).utf8_str()));
vbamDebug("GetResourcesDir(): %s", static_cast<const char*>(stdp.GetResourcesDir().utf8_str()));
vbamDebug("GetDataDir(): %s", static_cast<const char*>(stdp.GetDataDir().utf8_str()));
vbamDebug("GetLocalDataDir(): %s", static_cast<const char*>(stdp.GetLocalDataDir().utf8_str()));
vbamDebug("GetPluginsDir(): %s", static_cast<const char*>(stdp.GetPluginsDir().utf8_str()));
static bool debug_dumped = false;

if (!debug_dumped) {
vbamDebug("GetUserLocalDataDir(): %s", static_cast<const char*>(stdp.GetUserLocalDataDir().utf8_str()));
vbamDebug("GetUserDataDir(): %s", static_cast<const char*>(stdp.GetUserDataDir().utf8_str()));
vbamDebug("GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()): %s", static_cast<const char*>(stdp.GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()).utf8_str()));
vbamDebug("GetResourcesDir(): %s", static_cast<const char*>(stdp.GetResourcesDir().utf8_str()));
vbamDebug("GetDataDir(): %s", static_cast<const char*>(stdp.GetDataDir().utf8_str()));
vbamDebug("GetLocalDataDir(): %s", static_cast<const char*>(stdp.GetLocalDataDir().utf8_str()));
vbamDebug("GetPluginsDir(): %s", static_cast<const char*>(stdp.GetPluginsDir().utf8_str()));

debug_dumped = true;
}

// NOTE: this does not support XDG (freedesktop.org) paths
add_path(GetUserLocalDataDir());
Expand Down Expand Up @@ -591,10 +597,16 @@ EVT_CONTEXT_MENU(MainFrame::OnMenu)
EVT_ACTIVATE(MainFrame::OnActivate)
// requires DragAcceptFiles(true); even then may not do anything
EVT_DROP_FILES(MainFrame::OnDropFile)

// pause game if menu pops up
//
// this causes problems with keyboard game keys on mac, disable for now
#ifndef __WXMAC__
EVT_MENU_OPEN(MainFrame::MenuPopped)
EVT_MENU_CLOSE(MainFrame::MenuPopped)
EVT_MENU_HIGHLIGHT_ALL(MainFrame::MenuPopped)
#endif

END_EVENT_TABLE()

void MainFrame::OnActivate(wxActivateEvent& event)
Expand Down
9 changes: 1 addition & 8 deletions src/wx/wxvbam.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,10 @@ class DrawingPanel : public wxObject, public HiDPIAware {
void DrawArea(uint8_t** pixels);

// using dynamic_cast<> to not force trivial reimplementation in concrete classes
// TODO: figure something out for PaintEv as well
virtual wxWindow* GetWindow() { return dynamic_cast<wxWindow*>(this); }
virtual void Delete() { (dynamic_cast<wxWindow*>(this))->Destroy(); }

void PaintEv(wxPaintEvent& ev);
protected:
virtual void DrawArea(wxWindowDC&) = 0;
virtual void DrawOSD(wxWindowDC&);
Expand All @@ -651,13 +651,6 @@ class DrawingPanel : public wxObject, public HiDPIAware {
// largest buffer required is 32-bit * (max width + 1) * (max height + 2)
uint8_t delta[257 * 4 * 226];

// following can't work in 2.8 as intended
// inheriting from wxEvtHandler is required, but also breaks subclasses
// due to lack of virtual inheritance (2.9 drops wxEvtHandler req)
// so each child must have a paint event handler (not override of this,
// but it's not virtual anyway, so that won't happen) that calls this
void PaintEv(wxPaintEvent& ev);

DECLARE_ABSTRACT_CLASS()
};

Expand Down

0 comments on commit a775cc4

Please sign in to comment.