fix kbd controls on Mac + misc.
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
This commit is contained in:
parent
e609bb9c8c
commit
a775cc409f
|
@ -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})
|
||||
|
|
|
@ -8,14 +8,9 @@ public:
|
|||
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
|
||||
|
@ -27,10 +22,6 @@ public:
|
|||
virtual ~GLDrawingPanel();
|
||||
|
||||
protected:
|
||||
void PaintEv2(wxPaintEvent& ev)
|
||||
{
|
||||
PaintEv(ev);
|
||||
}
|
||||
void DrawArea(wxWindowDC& dc);
|
||||
#if wxCHECK_VERSION(2, 9, 0)
|
||||
wxGLContext* ctx;
|
||||
|
@ -40,7 +31,6 @@ protected:
|
|||
int texsize;
|
||||
|
||||
DECLARE_CLASS()
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -50,15 +40,10 @@ public:
|
|||
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
|
||||
|
||||
|
@ -71,15 +56,10 @@ public:
|
|||
~CairoDrawingPanel();
|
||||
|
||||
protected:
|
||||
void PaintEv2(wxPaintEvent& ev)
|
||||
{
|
||||
PaintEv(ev);
|
||||
}
|
||||
void DrawArea(wxWindowDC&);
|
||||
cairo_surface_t* conv_surf;
|
||||
|
||||
DECLARE_CLASS()
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -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())) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -1153,6 +1161,8 @@ 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++) {
|
||||
|
@ -1160,8 +1170,10 @@ static void process_key_press(bool down, int key, int mod, int joy = 0)
|
|||
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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[] = {
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
@ -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)
|
||||
|
|
|
@ -630,10 +630,10 @@ public:
|
|||
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&);
|
||||
|
@ -651,13 +651,6 @@ protected:
|
|||
// 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()
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue