mirror of https://github.com/PCSX2/pcsx2.git
* Hopeful fix for DX10 memory leaks.
* Likely fix for various plugin configuration button hangs/crashes. * Worked on the new GS window text label stuff a bit more (still needs more tho) Devel Note: * Lots of code cleanups regarding app message handling * Added wxAppWithHelpers.cpp/h files (linux projects need updated but too tired.. >_<) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2411 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
1298a35481
commit
ac1df96678
|
@ -260,7 +260,7 @@ BEGIN_DECLARE_EVENT_TYPES()
|
|||
DECLARE_EVENT_TYPE(wxEVT_MEASURE_ITEM, 436)
|
||||
DECLARE_EVENT_TYPE(wxEVT_COMPARE_ITEM, 437)
|
||||
DECLARE_EVENT_TYPE(wxEVT_INIT_DIALOG, 438)
|
||||
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_IDLE, 439)
|
||||
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEvt_Idle, 439)
|
||||
DECLARE_EVENT_TYPE(wxEVT_UPDATE_UI, 440)
|
||||
DECLARE_EVENT_TYPE(wxEVT_SIZING, 441)
|
||||
DECLARE_EVENT_TYPE(wxEVT_MOVING, 442)
|
||||
|
@ -2127,7 +2127,7 @@ private:
|
|||
|
||||
// Idle event
|
||||
/*
|
||||
wxEVT_IDLE
|
||||
wxEvt_Idle
|
||||
*/
|
||||
|
||||
// Whether to always send idle events to windows, or
|
||||
|
@ -2148,7 +2148,7 @@ class WXDLLIMPEXP_CORE wxIdleEvent : public wxEvent
|
|||
{
|
||||
public:
|
||||
wxIdleEvent()
|
||||
: wxEvent(0, wxEVT_IDLE),
|
||||
: wxEvent(0, wxEvt_Idle),
|
||||
m_requestMore(false)
|
||||
{ }
|
||||
wxIdleEvent(const wxIdleEvent & event)
|
||||
|
@ -3069,7 +3069,7 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
|||
EVT_JOY_ZMOVE(func)
|
||||
|
||||
// Idle event
|
||||
#define EVT_IDLE(func) wx__DECLARE_EVT0(wxEVT_IDLE, wxIdleEventHandler(func))
|
||||
#define EVT_IDLE(func) wx__DECLARE_EVT0(wxEvt_Idle, wxIdleEventHandler(func))
|
||||
|
||||
// Update UI event
|
||||
#define EVT_UPDATE_UI(winid, func) wx__DECLARE_EVT1(wxEVT_UPDATE_UI, winid, wxUpdateUIEventHandler(func))
|
||||
|
|
|
@ -157,7 +157,7 @@ const wxEventType wxEVT_FIRST = 10000;
|
|||
const wxEventType wxEVT_USER_FIRST = wxEVT_FIRST + 2000;
|
||||
|
||||
DEFINE_EVENT_TYPE(wxEVT_NULL)
|
||||
DEFINE_EVENT_TYPE(wxEVT_IDLE)
|
||||
DEFINE_EVENT_TYPE(wxEvt_Idle)
|
||||
DEFINE_EVENT_TYPE(wxEVT_SOCKET)
|
||||
|
||||
#endif // !WXWIN_COMPATIBILITY_EVENT_TYPES
|
||||
|
@ -1248,10 +1248,10 @@ bool wxEvtHandler::TryParent(wxEvent& event)
|
|||
{
|
||||
if ( wxTheApp && (this != wxTheApp) )
|
||||
{
|
||||
// Special case: don't pass wxEVT_IDLE to wxApp, since it'll always
|
||||
// swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be
|
||||
// Special case: don't pass wxEvt_Idle to wxApp, since it'll always
|
||||
// swallow it. wxEvt_Idle is sent explicitly to wxApp so it will be
|
||||
// processed appropriately via SearchEventTable.
|
||||
if ( event.GetEventType() != wxEVT_IDLE )
|
||||
if ( event.GetEventType() != wxEvt_Idle )
|
||||
{
|
||||
if ( wxTheApp->ProcessEvent(event) )
|
||||
return true;
|
||||
|
|
|
@ -247,8 +247,6 @@ public:
|
|||
SysMtgsThread();
|
||||
virtual ~SysMtgsThread() throw();
|
||||
|
||||
static SysMtgsThread& Get();
|
||||
|
||||
// Waits for the GS to empty out the entire ring buffer contents.
|
||||
// Used primarily for plugin startup/shutdown.
|
||||
void WaitGS();
|
||||
|
@ -269,6 +267,8 @@ public:
|
|||
void SetEvent();
|
||||
void PostVsyncEnd();
|
||||
|
||||
bool IsPluginOpened() const { return m_PluginOpened; }
|
||||
|
||||
protected:
|
||||
void OpenPlugin();
|
||||
void ClosePlugin();
|
||||
|
|
|
@ -998,6 +998,7 @@ void SysMtgsThread::WaitForOpen()
|
|||
|
||||
void SysMtgsThread::Freeze( int mode, MTGS_FreezeData& data )
|
||||
{
|
||||
GetPluginManager().Open( PluginId_GS );
|
||||
SendPointerPacket( GS_RINGTYPE_FREEZE, mode, &data );
|
||||
Resume();
|
||||
WaitGS();
|
||||
|
|
|
@ -875,18 +875,23 @@ extern void spu2DMA4Irq();
|
|||
extern void spu2DMA7Irq();
|
||||
extern void spu2Irq();
|
||||
|
||||
static bool OpenPlugin_GS()
|
||||
bool PluginManager::OpenPlugin_CDVD()
|
||||
{
|
||||
return DoCDVDopen();
|
||||
}
|
||||
|
||||
bool PluginManager::OpenPlugin_GS()
|
||||
{
|
||||
GetMTGS().Resume();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool OpenPlugin_PAD()
|
||||
bool PluginManager::OpenPlugin_PAD()
|
||||
{
|
||||
return !PADopen( (void*)&pDsp );
|
||||
}
|
||||
|
||||
static bool OpenPlugin_SPU2()
|
||||
bool PluginManager::OpenPlugin_SPU2()
|
||||
{
|
||||
if( SPU2open((void*)&pDsp) ) return false;
|
||||
|
||||
|
@ -896,7 +901,7 @@ static bool OpenPlugin_SPU2()
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool OpenPlugin_DEV9()
|
||||
bool PluginManager::OpenPlugin_DEV9()
|
||||
{
|
||||
dev9Handler = NULL;
|
||||
|
||||
|
@ -906,7 +911,7 @@ static bool OpenPlugin_DEV9()
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool OpenPlugin_USB()
|
||||
bool PluginManager::OpenPlugin_USB()
|
||||
{
|
||||
usbHandler = NULL;
|
||||
|
||||
|
@ -918,7 +923,7 @@ static bool OpenPlugin_USB()
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool OpenPlugin_FW()
|
||||
bool PluginManager::OpenPlugin_FW()
|
||||
{
|
||||
if( FWopen((void*)&pDsp) ) return false;
|
||||
FWirqCallback( fwIrq );
|
||||
|
@ -936,7 +941,7 @@ void PluginManager::Open( PluginsEnum_t pid )
|
|||
bool result = true;
|
||||
switch( pid )
|
||||
{
|
||||
case PluginId_CDVD: result = DoCDVDopen(); break;
|
||||
case PluginId_CDVD: result = OpenPlugin_CDVD(); break;
|
||||
case PluginId_GS: result = OpenPlugin_GS(); break;
|
||||
case PluginId_PAD: result = OpenPlugin_PAD(); break;
|
||||
case PluginId_SPU2: result = OpenPlugin_SPU2(); break;
|
||||
|
@ -951,21 +956,33 @@ void PluginManager::Open( PluginsEnum_t pid )
|
|||
m_info[pid].IsOpened = true;
|
||||
}
|
||||
|
||||
void PluginManager::Open()
|
||||
bool PluginManager::NeedsOpen() const
|
||||
{
|
||||
// Spam stopper: If all plugins are already opened, then return before writing any logs. >_<
|
||||
|
||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||
if( !m_info[pi->id].IsOpened ) break;
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
if( pi->shortname == NULL ) return;
|
||||
return pi->shortname != NULL;
|
||||
}
|
||||
|
||||
bool PluginManager::NeedsClose() const
|
||||
{
|
||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||
if( m_info[pi->id].IsOpened ) break;
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
return pi->shortname != NULL;
|
||||
}
|
||||
|
||||
void PluginManager::Open()
|
||||
{
|
||||
if( !NeedsOpen() ) return; // Spam stopper: returns before writing any logs. >_<
|
||||
|
||||
Console.WriteLn( Color_StrongBlue, "Opening plugins..." );
|
||||
|
||||
SendSettingsFolder();
|
||||
|
||||
pi = tbl_PluginInfo; do {
|
||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||
Open( pi->id );
|
||||
// If GS doesn't support GSopen2, need to wait until call to GSopen
|
||||
// returns to populate pDsp. If it does, can initialize other plugins
|
||||
|
@ -978,17 +995,21 @@ void PluginManager::Open()
|
|||
Console.WriteLn( Color_StrongBlue, "Plugins opened successfully." );
|
||||
}
|
||||
|
||||
void PluginManager::ClosePlugin_GS()
|
||||
{
|
||||
// force-close PAD before GS, because the PAD depends on the GS window.
|
||||
|
||||
Close( PluginId_PAD );
|
||||
GetMTGS().Suspend();
|
||||
}
|
||||
|
||||
void PluginManager::Close( PluginsEnum_t pid )
|
||||
{
|
||||
if( !m_info[pid].IsOpened ) return;
|
||||
Console.Indent().WriteLn( "Closing %s", tbl_PluginInfo[pid].shortname );
|
||||
|
||||
if( pid == PluginId_GS )
|
||||
{
|
||||
// force-close PAD before GS, because the PAD depends on the GS window.
|
||||
Close( PluginId_PAD );
|
||||
GetMTGS().Suspend();
|
||||
}
|
||||
ClosePlugin_GS();
|
||||
else if( pid == PluginId_CDVD )
|
||||
DoCDVDclose();
|
||||
else
|
||||
|
@ -997,25 +1018,16 @@ void PluginManager::Close( PluginsEnum_t pid )
|
|||
m_info[pid].IsOpened = false;
|
||||
}
|
||||
|
||||
void PluginManager::Close( bool closegs )
|
||||
void PluginManager::Close()
|
||||
{
|
||||
// Spam stopper: If all plugins are already closed, then return before writing any logs. >_<
|
||||
|
||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||
if( m_info[pi->id].IsOpened && (closegs || (pi->id != PluginId_GS)) ) break;
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
if( pi->shortname == NULL ) return;
|
||||
|
||||
DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." );
|
||||
if( !NeedsClose() ) return; // Spam stopper; returns before writing any logs. >_<
|
||||
|
||||
// Close plugins in reverse order of the initialization procedure.
|
||||
|
||||
DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." );
|
||||
|
||||
for( int i=PluginId_Count-1; i>=0; --i )
|
||||
{
|
||||
if( closegs || (tbl_PluginInfo[i].id != PluginId_GS) )
|
||||
Close( tbl_PluginInfo[i].id );
|
||||
}
|
||||
Close( tbl_PluginInfo[i].id );
|
||||
|
||||
DbgCon.WriteLn( Color_StrongBlue, "Plugins closed successfully." );
|
||||
}
|
||||
|
|
|
@ -248,7 +248,9 @@ public:
|
|||
virtual void Open() { }
|
||||
virtual void Open( PluginsEnum_t pid ) { pxFail( "Null PluginManager!" ); }
|
||||
virtual void Close( PluginsEnum_t pid ) {}
|
||||
virtual void Close( bool closegs=true ) {}
|
||||
virtual void Close() {}
|
||||
|
||||
virtual bool IsOpen( PluginsEnum_t pid ) const { return false; }
|
||||
|
||||
virtual void Freeze( PluginsEnum_t pid, SaveStateBase& state ) { pxFail( "Null PluginManager!" ); }
|
||||
virtual bool DoFreeze( PluginsEnum_t pid, int mode, freezeData* data )
|
||||
|
@ -298,20 +300,25 @@ public:
|
|||
PluginManager( const wxString (&folders)[PluginId_Count] );
|
||||
virtual ~PluginManager() throw();
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Open();
|
||||
void Open( PluginsEnum_t pid );
|
||||
void Close( PluginsEnum_t pid );
|
||||
void Close( bool closegs=true );
|
||||
virtual void Init();
|
||||
virtual void Shutdown();
|
||||
virtual void Open();
|
||||
virtual void Open( PluginsEnum_t pid );
|
||||
virtual void Close( PluginsEnum_t pid );
|
||||
virtual void Close();
|
||||
|
||||
void Freeze( PluginsEnum_t pid, SaveStateBase& state );
|
||||
bool DoFreeze( PluginsEnum_t pid, int mode, freezeData* data );
|
||||
virtual bool IsOpen( PluginsEnum_t pid ) const { return m_info[pid].IsOpened; }
|
||||
|
||||
virtual bool NeedsClose() const;
|
||||
virtual bool NeedsOpen() const;
|
||||
|
||||
virtual void Freeze( PluginsEnum_t pid, SaveStateBase& state );
|
||||
virtual bool DoFreeze( PluginsEnum_t pid, int mode, freezeData* data );
|
||||
|
||||
bool KeyEvent( const keyEvent& evt );
|
||||
void Configure( PluginsEnum_t pid );
|
||||
void SetSettingsFolder( const wxString& folder );
|
||||
void SendSettingsFolder();
|
||||
virtual bool KeyEvent( const keyEvent& evt );
|
||||
virtual void Configure( PluginsEnum_t pid );
|
||||
virtual void SetSettingsFolder( const wxString& folder );
|
||||
virtual void SendSettingsFolder();
|
||||
|
||||
const wxString& GetName( PluginsEnum_t pid ) const { return m_info[pid].Name; }
|
||||
const wxString& GetVersion( PluginsEnum_t pid ) const { return m_info[pid].Version; }
|
||||
|
@ -322,6 +329,16 @@ protected:
|
|||
void BindCommon( PluginsEnum_t pid );
|
||||
void BindRequired( PluginsEnum_t pid );
|
||||
void BindOptional( PluginsEnum_t pid );
|
||||
|
||||
virtual bool OpenPlugin_GS();
|
||||
virtual bool OpenPlugin_CDVD();
|
||||
virtual bool OpenPlugin_PAD();
|
||||
virtual bool OpenPlugin_SPU2();
|
||||
virtual bool OpenPlugin_DEV9();
|
||||
virtual bool OpenPlugin_USB();
|
||||
virtual bool OpenPlugin_FW();
|
||||
|
||||
virtual void ClosePlugin_GS();
|
||||
|
||||
friend class SysMtgsThread;
|
||||
};
|
||||
|
|
|
@ -107,11 +107,7 @@ protected:
|
|||
|
||||
void SendFinishEvent( int type )
|
||||
{
|
||||
wxCommandEvent evt( pxEVT_FreezeThreadFinished );
|
||||
evt.SetClientData( this );
|
||||
evt.SetInt( type );
|
||||
evt.SetExtraLong( m_resume_when_done );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( this, pxEvt_FreezeThreadFinished, type, m_resume_when_done );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -105,13 +105,8 @@ extern void NTFS_CompressFile( const wxString& file, bool compressStatus=true );
|
|||
// responded to the prompt.
|
||||
//
|
||||
|
||||
class pxMessageBoxEvent;
|
||||
class pxAssertionEvent;
|
||||
|
||||
namespace Msgbox
|
||||
{
|
||||
extern void OnEvent( pxMessageBoxEvent& evt );
|
||||
|
||||
extern bool Alert( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=wxICON_EXCLAMATION );
|
||||
extern bool OkCancel( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=0 );
|
||||
extern bool YesNo( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=wxICON_QUESTION );
|
||||
|
@ -119,7 +114,3 @@ namespace Msgbox
|
|||
extern int Assertion( const wxString& text, const wxString& stacktrace );
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
DECLARE_EVENT_TYPE( pxEVT_MSGBOX, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_ASSERTION, -1 )
|
||||
END_DECLARE_EVENT_TYPES()
|
||||
|
|
|
@ -97,6 +97,7 @@ bool SysThreadBase::Suspend( bool isBlocking )
|
|||
|
||||
case ExecMode_Pausing:
|
||||
case ExecMode_Paused:
|
||||
if( !isBlocking ) return retval;
|
||||
throw Exception::CancelEvent( "Another thread is pausing the VM state." );
|
||||
|
||||
case ExecMode_Opened:
|
||||
|
|
|
@ -15,32 +15,37 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include "wxAppWithHelpers.h"
|
||||
|
||||
#include <wx/fileconf.h>
|
||||
#include <wx/imaglist.h>
|
||||
#include <wx/apptrait.h>
|
||||
|
||||
#include "IniInterface.h"
|
||||
|
||||
#include "Utilities/HashMap.h"
|
||||
|
||||
#include "AppCommon.h"
|
||||
#include "RecentIsoList.h"
|
||||
|
||||
#include "System.h"
|
||||
#include "System/SysThreads.h"
|
||||
|
||||
#include "Utilities/HashMap.h"
|
||||
|
||||
class Pcsx2App;
|
||||
|
||||
typedef void FnType_OnThreadComplete(const wxCommandEvent& evt);
|
||||
typedef void (Pcsx2App::*FnType_AppMethod)();
|
||||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
DECLARE_EVENT_TYPE( pxEVT_OpenModalDialog, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_ReloadPlugins, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_SysExecute, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_LoadPluginsComplete, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_CoreThreadStatus, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_FreezeThreadFinished, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_Ping, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_LogicalVsync, -1 )
|
||||
/*DECLARE_EVENT_TYPE( pxEVT_ReloadPlugins, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEVT_OpenGsPanel, -1 )*/
|
||||
|
||||
DECLARE_EVENT_TYPE( pxEvt_FreezeThreadFinished, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_CoreThreadStatus, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_LoadPluginsComplete, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_PluginStatus, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_SysExecute, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_OpenModalDialog, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_InvokeMethod, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_LogicalVsync, -1 )
|
||||
END_DECLARE_EVENT_TYPES()
|
||||
|
||||
// This is used when the GS plugin is handling its own window. Messages from the PAD
|
||||
|
@ -297,39 +302,13 @@ struct pxAppResources
|
|||
~pxAppResources() throw() { }
|
||||
};
|
||||
|
||||
struct MsgboxEventResult
|
||||
{
|
||||
Semaphore WaitForMe;
|
||||
int result;
|
||||
|
||||
MsgboxEventResult()
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// AppIniSaver / AppIniLoader
|
||||
// --------------------------------------------------------------------------------------
|
||||
class AppIniSaver : public IniSaver
|
||||
{
|
||||
public:
|
||||
AppIniSaver();
|
||||
virtual ~AppIniSaver() {}
|
||||
};
|
||||
|
||||
class AppIniLoader : public IniLoader
|
||||
{
|
||||
public:
|
||||
AppIniLoader();
|
||||
virtual ~AppIniLoader() {}
|
||||
};
|
||||
|
||||
// =====================================================================================================
|
||||
// Pcsx2App - main wxApp class
|
||||
// =====================================================================================================
|
||||
class Pcsx2App : public wxApp
|
||||
class Pcsx2App : public wxAppWithHelpers
|
||||
{
|
||||
typedef wxAppWithHelpers _parent;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Event Sources!
|
||||
// These need to be at the top of the App class, because a lot of other things depend
|
||||
|
@ -343,11 +322,11 @@ protected:
|
|||
EventSource<AppEventType> m_evtsrc_AppStatus;
|
||||
|
||||
public:
|
||||
CmdEvt_Source& Source_CoreThreadStatus() { return m_evtsrc_CoreThreadStatus; }
|
||||
EventSource<int>& Source_SettingsApplied() { return m_evtsrc_SettingsApplied; }
|
||||
EventSource<AppEventType>& Source_AppStatus() { return m_evtsrc_AppStatus; }
|
||||
EventSource<PluginEventType>& Source_CorePluginStatus() { return m_evtsrc_CorePluginStatus; }
|
||||
EventSource<IniInterface>& Source_SettingsLoadSave() { return m_evtsrc_SettingsLoadSave; }
|
||||
CmdEvt_Source& Source_CoreThreadStatus() { AffinityAssert_AllowFromMain(); return m_evtsrc_CoreThreadStatus; }
|
||||
EventSource<int>& Source_SettingsApplied() { AffinityAssert_AllowFromMain(); return m_evtsrc_SettingsApplied; }
|
||||
EventSource<AppEventType>& Source_AppStatus() { AffinityAssert_AllowFromMain(); return m_evtsrc_AppStatus; }
|
||||
EventSource<PluginEventType>& Source_CorePluginStatus() { AffinityAssert_AllowFromMain(); return m_evtsrc_CorePluginStatus; }
|
||||
EventSource<IniInterface>& Source_SettingsLoadSave() { AffinityAssert_AllowFromMain(); return m_evtsrc_SettingsLoadSave; }
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
@ -370,16 +349,13 @@ protected:
|
|||
GSFrame* m_gsFrame;
|
||||
ConsoleLogFrame* m_ProgramLogBox;
|
||||
|
||||
std::vector<Semaphore*> m_PingWhenIdle;
|
||||
wxKeyEvent m_kevt;
|
||||
|
||||
public:
|
||||
Pcsx2App();
|
||||
virtual ~Pcsx2App();
|
||||
|
||||
void Ping();
|
||||
|
||||
void PostPadKey( wxKeyEvent& evt );
|
||||
void PostPluginStatus( PluginEventType pevt );
|
||||
void PostMenuAction( MenuIdentifiers menu_id ) const;
|
||||
int IssueModalDialog( const wxString& dlgName );
|
||||
|
||||
|
@ -388,6 +364,7 @@ public:
|
|||
void SysExecute();
|
||||
void SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override=wxEmptyString );
|
||||
void SysReset();
|
||||
void ReloadPlugins();
|
||||
|
||||
GSFrame& GetGSFrame() const;
|
||||
GSFrame* GetGSFramePtr() const { return m_gsFrame; }
|
||||
|
@ -396,7 +373,8 @@ public:
|
|||
MainEmuFrame* GetMainFramePtr() const { return m_MainFrame; }
|
||||
bool HasMainFrame() const { return m_MainFrame != NULL; }
|
||||
|
||||
void OpenGsFrame();
|
||||
void OpenGsPanel();
|
||||
void CloseGsPanel();
|
||||
void OnGsFrameClosed();
|
||||
void OnMainFrameClosed();
|
||||
|
||||
|
@ -443,31 +421,30 @@ public:
|
|||
void OnProgramLogClosed();
|
||||
|
||||
protected:
|
||||
bool SelfPostMethod( FnType_AppMethod method );
|
||||
|
||||
void InitDefaultGlobalAccelerators();
|
||||
void BuildCommandHash();
|
||||
void ReadUserModeSettings();
|
||||
bool TryOpenConfigCwd();
|
||||
void CleanupMess();
|
||||
void OpenWizardConsole();
|
||||
void PingDispatch( const char* action );
|
||||
void PadKeyDispatch( const keyEvent& ev );
|
||||
|
||||
void HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event) const;
|
||||
void HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event);
|
||||
|
||||
void OnSysExecute( wxCommandEvent& evt );
|
||||
void OnReloadPlugins( wxCommandEvent& evt );
|
||||
void OnLoadPluginsComplete( wxCommandEvent& evt );
|
||||
void OnPluginStatus( wxCommandEvent& evt );
|
||||
void OnOpenModalDialog( wxCommandEvent& evt );
|
||||
void OnCoreThreadStatus( wxCommandEvent& evt );
|
||||
void OnFreezeThreadFinished( wxCommandEvent& evt );
|
||||
|
||||
void OnMessageBox( pxMessageBoxEvent& evt );
|
||||
void OnEmuKeyDown( wxKeyEvent& evt );
|
||||
void OnLogicalVsync( wxCommandEvent& evt );
|
||||
|
||||
void OnIdleEvent( wxIdleEvent& evt );
|
||||
void OnPingEvent( pxPingEvent& evt );
|
||||
void OnInvokeMethod( pxInvokeMethodEvent& evt );
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Override wx default exception handling behavior
|
||||
|
|
|
@ -30,7 +30,7 @@ class GSFrame;
|
|||
class ConsoleLogFrame;
|
||||
class PipeRedirectionBase;
|
||||
class AppCoreThread;
|
||||
class pxPingEvent;
|
||||
class pxInvokeMethodEvent;
|
||||
|
||||
// wxWidgets forward declarations
|
||||
|
||||
|
@ -50,8 +50,10 @@ enum PluginEventType
|
|||
{
|
||||
PluginsEvt_Loaded,
|
||||
PluginsEvt_Init,
|
||||
PluginsEvt_Open,
|
||||
PluginsEvt_Close,
|
||||
PluginsEvt_Opening, // dispatched prior to plugins being opened
|
||||
PluginsEvt_Opened, // dispatched after plugins are opened
|
||||
PluginsEvt_Closing, // dispatched prior to plugins being closed
|
||||
PluginsEvt_Closed, // dispatched after plugins are closed
|
||||
PluginsEvt_Shutdown,
|
||||
PluginsEvt_Unloaded,
|
||||
};
|
||||
|
|
|
@ -45,10 +45,7 @@ void AppCoreThread::Reset()
|
|||
ScopedBusyCursor::SetDefault( Cursor_KindaBusy );
|
||||
|
||||
_parent::Reset();
|
||||
|
||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||
evt.SetInt( CoreStatus_Reset );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Reset );
|
||||
}
|
||||
|
||||
bool AppCoreThread::Suspend( bool isBlocking )
|
||||
|
@ -92,9 +89,7 @@ void AppCoreThread::Resume()
|
|||
// Resume failed for some reason, so update GUI statuses and post a message to
|
||||
// try again on the resume.
|
||||
|
||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||
evt.SetInt( CoreStatus_Suspended );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Suspended );
|
||||
|
||||
if( (m_ExecMode != ExecMode_Closing) || (m_ExecMode != ExecMode_Pausing) )
|
||||
{
|
||||
|
@ -131,30 +126,19 @@ void AppCoreThread::OnResumeReady()
|
|||
|
||||
AppSaveSettings();
|
||||
|
||||
if( GSopen2 != NULL )
|
||||
{
|
||||
sApp.OpenGsFrame();
|
||||
}
|
||||
|
||||
_parent::OnResumeReady();
|
||||
}
|
||||
|
||||
void AppCoreThread::OnResumeInThread( bool isSuspended )
|
||||
{
|
||||
_parent::OnResumeInThread( isSuspended );
|
||||
|
||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||
evt.SetInt( CoreStatus_Resumed );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Resumed );
|
||||
}
|
||||
|
||||
void AppCoreThread::OnSuspendInThread()
|
||||
{
|
||||
_parent::OnSuspendInThread();
|
||||
|
||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||
evt.SetInt( CoreStatus_Suspended );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Suspended );
|
||||
}
|
||||
|
||||
// Called whenever the thread has terminated, for either regular or irregular reasons.
|
||||
|
@ -163,16 +147,13 @@ void AppCoreThread::OnSuspendInThread()
|
|||
// the new (lack of) thread status, so this posts a message to the App to do so.
|
||||
void AppCoreThread::OnCleanupInThread()
|
||||
{
|
||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||
evt.SetInt( CoreStatus_Stopped );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Stopped );
|
||||
_parent::OnCleanupInThread();
|
||||
}
|
||||
|
||||
void AppCoreThread::PostVsyncToUI()
|
||||
{
|
||||
wxCommandEvent evt( pxEVT_LogicalVsync );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().PostCommand( pxEvt_LogicalVsync );
|
||||
}
|
||||
|
||||
void AppCoreThread::StateCheckInThread()
|
||||
|
|
|
@ -260,21 +260,15 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef void (wxEvtHandler::*pxMessageBoxEventFunction)(pxMessageBoxEvent&);
|
||||
typedef void (wxEvtHandler::*pxPingEventFunction)(pxPingEvent&);
|
||||
typedef void (wxEvtHandler::*pxInvokeMethodEventFunction)(pxInvokeMethodEvent&);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool Pcsx2App::OnInit()
|
||||
{
|
||||
#define pxMessageBoxEventThing(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
|
||||
#define pxMethodEventHandler(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxInvokeMethodEventFunction, &func )
|
||||
|
||||
#define pxPingEventHandler(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxPingEventFunction, &func )
|
||||
|
||||
Connect( pxEVT_MSGBOX, pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
|
||||
Connect( pxEVT_ASSERTION, pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
|
||||
Connect( pxEVT_OpenModalDialog, wxCommandEventHandler( Pcsx2App::OnOpenModalDialog ) );
|
||||
Connect( pxEvt_OpenModalDialog, wxCommandEventHandler( Pcsx2App::OnOpenModalDialog ) );
|
||||
|
||||
pxDoAssert = AppDoAssert;
|
||||
|
||||
|
@ -282,22 +276,23 @@ bool Pcsx2App::OnInit()
|
|||
EnableAllLogging();
|
||||
|
||||
wxInitAllImageHandlers();
|
||||
if( !wxApp::OnInit() ) return false;
|
||||
if( !_parent::OnInit() ) return false;
|
||||
|
||||
m_StdoutRedirHandle = NewPipeRedir(stdout);
|
||||
m_StderrRedirHandle = NewPipeRedir(stderr);
|
||||
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
||||
|
||||
Connect( pxEVT_ReloadPlugins, wxCommandEventHandler (Pcsx2App::OnReloadPlugins) );
|
||||
Connect( pxEVT_SysExecute, wxCommandEventHandler (Pcsx2App::OnSysExecute) );
|
||||
/*Connect( pxEVT_ReloadPlugins, wxCommandEventHandler (Pcsx2App::OnReloadPlugins) );
|
||||
|
||||
Connect( pxEVT_LoadPluginsComplete, wxCommandEventHandler (Pcsx2App::OnLoadPluginsComplete) );
|
||||
Connect( pxEVT_CoreThreadStatus, wxCommandEventHandler (Pcsx2App::OnCoreThreadStatus) );
|
||||
Connect( pxEVT_FreezeThreadFinished, wxCommandEventHandler (Pcsx2App::OnFreezeThreadFinished) );
|
||||
Connect( pxEVT_LogicalVsync, wxCommandEventHandler (Pcsx2App::OnLogicalVsync) );
|
||||
Connect( pxEVT_OpenGsPanel, wxCommandEventHandler (Pcsx2App::OpenGsPanel) );*/
|
||||
|
||||
Connect( pxEVT_Ping, pxPingEventHandler (Pcsx2App::OnPingEvent) );
|
||||
Connect( wxEVT_IDLE, wxIdleEventHandler (Pcsx2App::OnIdleEvent) );
|
||||
Connect( pxEvt_FreezeThreadFinished, wxCommandEventHandler (Pcsx2App::OnFreezeThreadFinished) );
|
||||
Connect( pxEvt_CoreThreadStatus, wxCommandEventHandler (Pcsx2App::OnCoreThreadStatus) );
|
||||
Connect( pxEvt_LoadPluginsComplete, wxCommandEventHandler (Pcsx2App::OnLoadPluginsComplete) );
|
||||
Connect( pxEvt_PluginStatus, wxCommandEventHandler (Pcsx2App::OnPluginStatus) );
|
||||
Connect( pxEvt_SysExecute, wxCommandEventHandler (Pcsx2App::OnSysExecute) );
|
||||
Connect( pxEvt_InvokeMethod, pxMethodEventHandler (Pcsx2App::OnInvokeMethod) );
|
||||
|
||||
Connect( pxID_PadHandler_Keydown, wxEVT_KEY_DOWN, wxKeyEventHandler( Pcsx2App::OnEmuKeyDown ) );
|
||||
|
||||
|
@ -518,16 +513,6 @@ Pcsx2App::Pcsx2App()
|
|||
|
||||
SetAppName( L"pcsx2" );
|
||||
BuildCommandHash();
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// This variable assignment ensures that MSVC links in the TLS setup stubs even in
|
||||
// full optimization builds. Without it, DLLs that use TLS won't work because the
|
||||
// FS segment register won't have been initialized by the main exe, due to tls_insurance
|
||||
// being optimized away >_< --air
|
||||
|
||||
static __threadlocal int tls_insurance = 0;
|
||||
tls_insurance = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
Pcsx2App::~Pcsx2App()
|
||||
|
|
|
@ -32,14 +32,17 @@
|
|||
|
||||
IMPLEMENT_APP(Pcsx2App)
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEVT_OpenModalDialog );
|
||||
DEFINE_EVENT_TYPE( pxEVT_ReloadPlugins );
|
||||
DEFINE_EVENT_TYPE( pxEVT_SysExecute );
|
||||
DEFINE_EVENT_TYPE( pxEVT_LoadPluginsComplete );
|
||||
DEFINE_EVENT_TYPE( pxEVT_CoreThreadStatus );
|
||||
DEFINE_EVENT_TYPE( pxEVT_FreezeThreadFinished );
|
||||
DEFINE_EVENT_TYPE( pxEVT_Ping );
|
||||
DEFINE_EVENT_TYPE( pxEVT_LogicalVsync );
|
||||
/*DEFINE_EVENT_TYPE( pxEVT_ReloadPlugins );
|
||||
DEFINE_EVENT_TYPE( pxEVT_OpenGsPanel );*/
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEvt_FreezeThreadFinished );
|
||||
DEFINE_EVENT_TYPE( pxEvt_CoreThreadStatus );
|
||||
DEFINE_EVENT_TYPE( pxEvt_LoadPluginsComplete );
|
||||
DEFINE_EVENT_TYPE( pxEvt_PluginStatus );
|
||||
DEFINE_EVENT_TYPE( pxEvt_SysExecute );
|
||||
DEFINE_EVENT_TYPE( pxEvt_OpenModalDialog );
|
||||
DEFINE_EVENT_TYPE( pxEvt_InvokeMethod );
|
||||
DEFINE_EVENT_TYPE( pxEvt_LogicalVsync );
|
||||
|
||||
#include "Utilities/EventSource.inl"
|
||||
EventSource_ImplementType( IniInterface );
|
||||
|
@ -85,72 +88,66 @@ void Pcsx2App::PostMenuAction( MenuIdentifiers menu_id ) const
|
|||
m_MainFrame->GetEventHandler()->AddPendingEvent( joe );
|
||||
}
|
||||
|
||||
class pxPingEvent : public wxEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxInvokeMethodEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Unlike pxPingEvent, the Semaphore belonging to this event is typically posted when the
|
||||
// invoked method is completed. If the method can be executed in non-blocking fashion then
|
||||
// it should leave the semaphore postback NULL.
|
||||
//
|
||||
class pxInvokeMethodEvent : public pxPingEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxPingEvent)
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxInvokeMethodEvent)
|
||||
|
||||
protected:
|
||||
Semaphore* m_PostBack;
|
||||
FnType_AppMethod m_Method;
|
||||
|
||||
public:
|
||||
virtual ~pxPingEvent() throw() { }
|
||||
virtual pxPingEvent *Clone() const { return new pxPingEvent(*this); }
|
||||
virtual ~pxInvokeMethodEvent() throw() { }
|
||||
virtual pxInvokeMethodEvent *Clone() const { return new pxInvokeMethodEvent(*this); }
|
||||
|
||||
explicit pxPingEvent( int msgtype, Semaphore* sema=NULL )
|
||||
: wxEvent( 0, msgtype )
|
||||
explicit pxInvokeMethodEvent( int msgtype, FnType_AppMethod method=NULL, Semaphore* sema=NULL )
|
||||
: pxPingEvent( msgtype, sema )
|
||||
{
|
||||
m_PostBack = sema;
|
||||
m_Method = method;
|
||||
}
|
||||
|
||||
explicit pxPingEvent( Semaphore* sema=NULL )
|
||||
: wxEvent( 0, pxEVT_Ping )
|
||||
explicit pxInvokeMethodEvent( FnType_AppMethod method=NULL, Semaphore* sema=NULL )
|
||||
: pxPingEvent( pxEvt_InvokeMethod, sema )
|
||||
{
|
||||
m_PostBack = sema;
|
||||
m_Method = method;
|
||||
}
|
||||
|
||||
explicit pxInvokeMethodEvent( FnType_AppMethod method, Semaphore& sema )
|
||||
: pxPingEvent( pxEvt_InvokeMethod, &sema )
|
||||
{
|
||||
m_Method = method;
|
||||
}
|
||||
|
||||
pxPingEvent( const pxPingEvent& src )
|
||||
: wxEvent( src )
|
||||
pxInvokeMethodEvent( const pxInvokeMethodEvent& src )
|
||||
: pxPingEvent( src )
|
||||
{
|
||||
m_PostBack = src.m_PostBack;
|
||||
m_Method = src.m_Method;
|
||||
}
|
||||
|
||||
void Invoke() const
|
||||
{
|
||||
if( m_Method ) (wxGetApp().*m_Method)();
|
||||
if( m_PostBack ) m_PostBack->Post();
|
||||
}
|
||||
|
||||
Semaphore* GetSemaphore() { return m_PostBack; }
|
||||
void SetMethod( FnType_AppMethod method )
|
||||
{
|
||||
m_Method = method;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxPingEvent, wxEvent )
|
||||
|
||||
void Pcsx2App::OnPingEvent( pxPingEvent& evt )
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxInvokeMethodEvent, pxPingEvent )
|
||||
|
||||
void Pcsx2App::OnInvokeMethod( pxInvokeMethodEvent& evt )
|
||||
{
|
||||
m_PingWhenIdle.push_back( evt.GetSemaphore() );
|
||||
}
|
||||
|
||||
void Pcsx2App::PingDispatch( const char* action )
|
||||
{
|
||||
size_t size = m_PingWhenIdle.size();
|
||||
if( size == 0 ) return;
|
||||
|
||||
DbgCon.WriteLn( Color_Gray, "App Event Ping (%s) -> %u listeners.", action, size );
|
||||
|
||||
for( size_t i=0; i<size; ++i )
|
||||
{
|
||||
if( Semaphore* sema = m_PingWhenIdle[i] ) sema->Post();
|
||||
}
|
||||
|
||||
m_PingWhenIdle.clear();
|
||||
}
|
||||
|
||||
void Pcsx2App::OnIdleEvent( wxIdleEvent& evt )
|
||||
{
|
||||
evt.Skip();
|
||||
PingDispatch( "Idle" );
|
||||
}
|
||||
|
||||
void Pcsx2App::Ping()
|
||||
{
|
||||
Semaphore sema;
|
||||
pxPingEvent evt( &sema );
|
||||
AddPendingEvent( evt );
|
||||
sema.WaitNoCancel();
|
||||
evt.Invoke(); // wow this is easy!
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
|
@ -268,10 +265,7 @@ int Pcsx2App::IssueModalDialog( const wxString& dlgName )
|
|||
if( !wxThread::IsMain() )
|
||||
{
|
||||
MsgboxEventResult result;
|
||||
wxCommandEvent joe( pxEVT_OpenModalDialog );
|
||||
joe.SetString( dlgName );
|
||||
joe.SetClientData( &result );
|
||||
AddPendingEvent( joe );
|
||||
PostCommand( &result, pxEvt_OpenModalDialog, 0, 0, dlgName );
|
||||
result.WaitForMe.WaitNoCancel();
|
||||
return result.result;
|
||||
}
|
||||
|
@ -608,20 +602,55 @@ void AppSaveSettings()
|
|||
wxGetApp().Source_SettingsLoadSave().Dispatch( saver );
|
||||
}
|
||||
|
||||
void Pcsx2App::OpenGsFrame()
|
||||
// This function works something like setjmp/longjmp, in that the return value indicates if the
|
||||
// function actually executed the specified method or not.
|
||||
//
|
||||
// Returns:
|
||||
// FALSE if the method was not posted to the main thread (meaning this IS the main thread!)
|
||||
// TRUE if the method was posted.
|
||||
//
|
||||
bool Pcsx2App::SelfPostMethod( FnType_AppMethod method )
|
||||
{
|
||||
if( wxThread::IsMain() ) return false;
|
||||
|
||||
Semaphore sem;
|
||||
pxInvokeMethodEvent evt( method, sem );
|
||||
AddPendingEvent( evt );
|
||||
sem.Wait();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pcsx2App::OpenGsPanel()
|
||||
{
|
||||
if( SelfPostMethod( &Pcsx2App::OpenGsPanel ) ) return;
|
||||
|
||||
if( m_gsFrame == NULL )
|
||||
{
|
||||
m_gsFrame = new GSFrame( m_MainFrame, L"PCSX2" );
|
||||
m_gsFrame->SetFocus();
|
||||
pDsp = (uptr)m_gsFrame->GetViewport()->GetHandle();
|
||||
}
|
||||
|
||||
pxAssumeDev( !GetPluginManager().IsOpen( PluginId_GS ), "GS Plugin must be closed prior to opening a new Gs Panel!" );
|
||||
|
||||
m_gsFrame->Show();
|
||||
pDsp = (uptr)m_gsFrame->GetViewport()->GetHandle();
|
||||
|
||||
// The "in the main window" quickie hack...
|
||||
//pDsp = (uptr)m_MainFrame->m_background.GetHandle();
|
||||
}
|
||||
|
||||
void Pcsx2App::CloseGsPanel()
|
||||
{
|
||||
if( SelfPostMethod( &Pcsx2App::CloseGsPanel ) ) return;
|
||||
|
||||
if( m_gsFrame != NULL )
|
||||
{
|
||||
if( GSPanel* woot = (GSPanel*)m_gsFrame->FindWindowByName(L"GSPanel") )
|
||||
woot->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void Pcsx2App::OnGsFrameClosed()
|
||||
{
|
||||
CoreThread.Suspend();
|
||||
|
@ -659,10 +688,7 @@ static void _sendmsg_SysExecute()
|
|||
}
|
||||
|
||||
AppSaveSettings();
|
||||
|
||||
wxCommandEvent execevt( pxEVT_SysExecute );
|
||||
execevt.SetInt( _sysexec_cdvdsrc_type );
|
||||
wxGetApp().AddPendingEvent( execevt );
|
||||
wxGetApp().PostCommand( pxEvt_SysExecute, _sysexec_cdvdsrc_type );
|
||||
}
|
||||
|
||||
static void OnSysExecuteAfterPlugins( const wxCommandEvent& loadevt )
|
||||
|
@ -683,6 +709,8 @@ void Pcsx2App::SysExecute()
|
|||
LoadPluginsPassive( OnSysExecuteAfterPlugins );
|
||||
return;
|
||||
}
|
||||
|
||||
DbgCon.WriteLn( Color_Gray, "(SysExecute) Queuing request to re-execute existing VM state." );
|
||||
_sendmsg_SysExecute();
|
||||
}
|
||||
|
||||
|
@ -699,6 +727,8 @@ void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override
|
|||
LoadPluginsPassive( OnSysExecuteAfterPlugins );
|
||||
return;
|
||||
}
|
||||
|
||||
DbgCon.WriteLn( Color_Gray, "(SysExecute) Queuing request for new VM state." );
|
||||
_sendmsg_SysExecute();
|
||||
}
|
||||
|
||||
|
@ -719,6 +749,8 @@ void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
|
|||
// it, because apparently too much stuff is going on and the emulation states are wonky.
|
||||
if( !m_CorePlugins ) return;
|
||||
|
||||
DbgCon.WriteLn( Color_Gray, "(MainThread) SysExecute received." );
|
||||
|
||||
if( evt.GetInt() != -1 ) CoreThread.Reset(); else CoreThread.Suspend();
|
||||
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
|
||||
if( evt.GetInt() != -1 )
|
||||
|
|
|
@ -67,94 +67,6 @@ protected:
|
|||
virtual void OnDoubleClicked( wxCommandEvent& evt );
|
||||
};
|
||||
|
||||
class MsgButtons
|
||||
{
|
||||
protected:
|
||||
BITFIELD32()
|
||||
bool
|
||||
m_OK :1,
|
||||
m_Cancel :1,
|
||||
m_Yes :1,
|
||||
m_No :1,
|
||||
m_AllowToAll:1,
|
||||
m_Apply :1,
|
||||
m_Abort :1,
|
||||
m_Retry :1,
|
||||
m_Ignore :1,
|
||||
m_Reset :1,
|
||||
m_Close :1;
|
||||
BITFIELD_END
|
||||
|
||||
wxString m_CustomLabel;
|
||||
|
||||
public:
|
||||
MsgButtons() : bitset( 0 ) { }
|
||||
|
||||
MsgButtons& OK() { m_OK = true; return *this; }
|
||||
MsgButtons& Cancel() { m_Cancel = true; return *this; }
|
||||
MsgButtons& Apply() { m_Apply = true; return *this; }
|
||||
MsgButtons& Yes() { m_Yes = true; return *this; }
|
||||
MsgButtons& No() { m_No = true; return *this; }
|
||||
MsgButtons& ToAll() { m_AllowToAll = true; return *this; }
|
||||
|
||||
MsgButtons& Abort() { m_Abort = true; return *this; }
|
||||
MsgButtons& Retry() { m_Retry = true; return *this; }
|
||||
MsgButtons& Ignore() { m_Ignore = true; return *this; }
|
||||
MsgButtons& Reset() { m_Reset = true; return *this; }
|
||||
MsgButtons& Close() { m_Close = true; return *this; }
|
||||
|
||||
MsgButtons& Custom( const wxString& label)
|
||||
{
|
||||
m_CustomLabel = label;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgButtons& OKCancel() { m_OK = m_Cancel = true; return *this; }
|
||||
MsgButtons& YesNo() { m_Yes = m_No = true; return *this; }
|
||||
|
||||
bool HasOK() const { return m_OK; }
|
||||
bool HasCancel() const { return m_Cancel; }
|
||||
bool HasApply() const { return m_Apply; }
|
||||
bool HasYes() const { return m_Yes; }
|
||||
bool HasNo() const { return m_No; }
|
||||
bool AllowsToAll() const{ return m_AllowToAll; }
|
||||
|
||||
bool HasAbort() const { return m_Abort; }
|
||||
bool HasRetry() const { return m_Retry; }
|
||||
bool HasIgnore() const { return m_Ignore; }
|
||||
bool HasReset() const { return m_Reset; }
|
||||
bool HasClose() const { return m_Close; }
|
||||
|
||||
bool HasCustom() const { return !m_CustomLabel.IsEmpty(); }
|
||||
const wxString& GetCustomLabel() const { return m_CustomLabel; }
|
||||
|
||||
bool Allows( wxWindowID id ) const;
|
||||
void SetBestFocus( wxWindow* dialog ) const;
|
||||
void SetBestFocus( wxWindow& dialog ) const;
|
||||
|
||||
bool operator ==( const MsgButtons& right ) const
|
||||
{
|
||||
return OpEqu( bitset );
|
||||
}
|
||||
|
||||
bool operator !=( const MsgButtons& right ) const
|
||||
{
|
||||
return !OpEqu( bitset );
|
||||
}
|
||||
};
|
||||
|
||||
class ModalButtonPanel : public wxPanelWithHelpers
|
||||
{
|
||||
public:
|
||||
ModalButtonPanel( wxWindow* window, const MsgButtons& buttons );
|
||||
virtual ~ModalButtonPanel() throw() { }
|
||||
|
||||
virtual void AddActionButton( wxWindowID id );
|
||||
virtual void AddCustomButton( wxWindowID id, const wxString& label );
|
||||
|
||||
virtual void OnActionButtonClicked( wxCommandEvent& evt );
|
||||
};
|
||||
|
||||
namespace Dialogs
|
||||
{
|
||||
class AboutBoxDialog: public wxDialogWithHelpers
|
||||
|
|
|
@ -47,7 +47,7 @@ void GSPanel::InitDefaultAccelerators()
|
|||
|
||||
GSPanel::GSPanel( wxWindow* parent )
|
||||
: wxWindow()
|
||||
, m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener<int> ( this, OnSettingsApplied ) )
|
||||
, m_Listener_SettingsApplied ( wxGetApp().Source_SettingsApplied(), EventListener<int> ( this, OnSettingsApplied ) )
|
||||
, m_HideMouseTimer( this )
|
||||
{
|
||||
m_CursorShown = true;
|
||||
|
@ -66,29 +66,29 @@ GSPanel::GSPanel( wxWindow* parent )
|
|||
m_CursorShown = false;
|
||||
}
|
||||
|
||||
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSPanel::OnCloseWindow) );
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler (GSPanel::OnResize) );
|
||||
Connect( wxEVT_KEY_DOWN, wxKeyEventHandler (GSPanel::OnKeyDown) );
|
||||
Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSPanel::OnCloseWindow));
|
||||
Connect(wxEVT_SIZE, wxSizeEventHandler (GSPanel::OnResize));
|
||||
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (GSPanel::OnKeyDown));
|
||||
|
||||
Connect( wxEVT_SET_FOCUS, wxFocusEventHandler(GSPanel::OnFocus) );
|
||||
Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler(GSPanel::OnFocusLost) );
|
||||
Connect(wxEVT_SET_FOCUS, wxFocusEventHandler (GSPanel::OnFocus));
|
||||
Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler (GSPanel::OnFocusLost));
|
||||
|
||||
Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_MOTION, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_RIGHT_DCLICK, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(GSPanel::OnShowMouse) );
|
||||
Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_UP, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MOTION, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
|
||||
Connect(m_HideMouseTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(GSPanel::OnHideMouseTimeout) );
|
||||
}
|
||||
|
||||
GSPanel::~GSPanel() throw()
|
||||
{
|
||||
CoreThread.Suspend(); // Just in case...!
|
||||
CoreThread.Suspend( false ); // Just in case...!
|
||||
}
|
||||
|
||||
void GSPanel::DoShowMouse()
|
||||
|
@ -246,9 +246,10 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title)
|
|||
label->SetName(L"OutputDisabledLabel");
|
||||
label->SetFont( *new wxFont( 20, wxDEFAULT, wxNORMAL, wxBOLD ) );
|
||||
label->SetForegroundColour( *wxWHITE );
|
||||
label->Show( !EmuConfig.GS.DisableOutput );
|
||||
label->Show( EmuConfig.GS.DisableOutput );
|
||||
|
||||
m_gspanel = new GSPanel( this );
|
||||
m_gspanel = new GSPanel( this ); // TODO : give this an id instead of using FindByName
|
||||
m_gspanel->Show( !EmuConfig.GS.DisableOutput );
|
||||
|
||||
//Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSFrame::OnCloseWindow) );
|
||||
Connect( wxEVT_MOVE, wxMoveEventHandler (GSFrame::OnMove) );
|
||||
|
@ -260,6 +261,24 @@ GSFrame::~GSFrame() throw()
|
|||
{
|
||||
}
|
||||
|
||||
// overrides base Show behavior.
|
||||
bool GSFrame::Show( bool shown )
|
||||
{
|
||||
if( shown )
|
||||
{
|
||||
if( FindWindowByName(L"GSPanel") == NULL )
|
||||
{
|
||||
m_gspanel = new GSPanel( this );
|
||||
m_gspanel->Show( !EmuConfig.GS.DisableOutput );
|
||||
}
|
||||
|
||||
m_gspanel->DoResize();
|
||||
m_gspanel->SetFocus();
|
||||
}
|
||||
|
||||
return _parent::Show( shown );
|
||||
}
|
||||
|
||||
void __evt_fastcall GSFrame::OnSettingsApplied( void* obj, int& evt )
|
||||
{
|
||||
if( obj == NULL ) return;
|
||||
|
@ -280,7 +299,7 @@ void GSFrame::DoSettingsApplied()
|
|||
|
||||
wxWindow* GSFrame::GetViewport()
|
||||
{
|
||||
return m_gspanel;
|
||||
return FindWindowByName(L"GSPanel");
|
||||
}
|
||||
|
||||
void GSFrame::OnActivate( wxActivateEvent& evt )
|
||||
|
|
|
@ -78,7 +78,7 @@ IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config )
|
|||
}
|
||||
|
||||
IniLoader::IniLoader() : IniInterface() {}
|
||||
IniLoader::~IniLoader() {}
|
||||
IniLoader::~IniLoader() throw() {}
|
||||
|
||||
|
||||
void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue )
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
class IniLoader : public IniInterface
|
||||
{
|
||||
public:
|
||||
virtual ~IniLoader();
|
||||
virtual ~IniLoader() throw();
|
||||
explicit IniLoader();
|
||||
explicit IniLoader( wxConfigBase& config );
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ protected:
|
|||
// --------------------------------------------------------------------------------------
|
||||
class GSFrame : public wxFrame
|
||||
{
|
||||
typedef wxFrame _parent;
|
||||
|
||||
protected:
|
||||
EventListenerBinding<int> m_Listener_SettingsApplied;
|
||||
GSPanel* m_gspanel;
|
||||
|
@ -78,6 +80,8 @@ public:
|
|||
|
||||
wxWindow* GetViewport();
|
||||
|
||||
bool Show( bool shown=true );
|
||||
|
||||
protected:
|
||||
void OnMove( wxMoveEvent& evt );
|
||||
void OnResize( wxSizeEvent& evt );
|
||||
|
|
|
@ -240,16 +240,16 @@ void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event)
|
|||
{
|
||||
if( !SysHasValidState() ) return;
|
||||
|
||||
if( !CoreThread.Suspend() )
|
||||
{
|
||||
sApp.SysExecute();
|
||||
}
|
||||
|
||||
// Disable the menu item. The state of the menu is indeterminate until the core thread
|
||||
// has responded (it updates status after the plugins are loaded and emulation has
|
||||
// engaged successfully).
|
||||
|
||||
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, false );
|
||||
|
||||
if( !CoreThread.Suspend() )
|
||||
{
|
||||
sApp.SysExecute();
|
||||
}
|
||||
}
|
||||
|
||||
void MainEmuFrame::Menu_SysReset_Click(wxCommandEvent &event)
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
#include "App.h"
|
||||
#include "Dialogs/ModalPopups.h"
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
|
||||
DEFINE_EVENT_TYPE( pxEVT_ASSERTION );
|
||||
|
||||
using namespace Threading;
|
||||
using namespace pxSizerFlags;
|
||||
|
||||
|
@ -43,206 +40,152 @@ static int pxMessageDialog( const wxString& caption, const wxString& content, co
|
|||
return pxIssueConfirmation( dialog, buttons );
|
||||
}
|
||||
|
||||
class BaseMessageBoxEvent : public wxEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent)
|
||||
|
||||
protected:
|
||||
MsgboxEventResult* m_Instdata;
|
||||
wxString m_Content;
|
||||
|
||||
public:
|
||||
explicit BaseMessageBoxEvent( int msgtype=pxEVT_MSGBOX, const wxString& content=wxEmptyString )
|
||||
: wxEvent( 0, msgtype )
|
||||
, m_Content( content )
|
||||
{
|
||||
m_Instdata = NULL;
|
||||
}
|
||||
|
||||
virtual ~BaseMessageBoxEvent() throw() { }
|
||||
virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); }
|
||||
|
||||
BaseMessageBoxEvent( MsgboxEventResult& instdata, const wxString& content )
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( &instdata )
|
||||
, m_Content( content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent( const wxString& content )
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( NULL )
|
||||
, m_Content( content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent( const BaseMessageBoxEvent& event )
|
||||
: wxEvent( event )
|
||||
, m_Instdata( event.m_Instdata )
|
||||
, m_Content( event.m_Content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent& SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
m_Instdata = &instdata;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
virtual void IssueDialog()
|
||||
{
|
||||
AffinityAssert_AllowFromMain();
|
||||
|
||||
int result = _DoDialog();
|
||||
|
||||
if( m_Instdata != NULL )
|
||||
{
|
||||
m_Instdata->result = result;
|
||||
m_Instdata->WaitForMe.Post();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const
|
||||
{
|
||||
pxFailDev( "Abstract Base MessageBox Event." );
|
||||
return wxID_CANCEL;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxMessageBoxEvent
|
||||
// BaseMessageBoxEvent Implementation
|
||||
// --------------------------------------------------------------------------------------
|
||||
// This event type is used to transfer message boxes to the main UI thread, and return the
|
||||
// result of the box. It's the only way a message box can be issued from non-main threads
|
||||
// with complete safety in wx2.8.
|
||||
//
|
||||
// For simplicity sake this message box only supports two basic designs. The main design
|
||||
// is a generic message box with confirmation buttons of your choosing. Additionally you
|
||||
// can specify a "scrollableContent" text string, which is added into a read-only richtext
|
||||
// control similar to the console logs and such.
|
||||
//
|
||||
// Future consideration: If wxWidgets 3.0 has improved thread safety, then it should probably
|
||||
// be reasonable for it to work with a more flexable model where the dialog can be created
|
||||
// on a child thread, passed to the main thread, where ShowModal() is run (keeping the nested
|
||||
// message pumps on the main thread where they belong). But so far this is not possible,
|
||||
// because of various subtle issues in wx2.8 design.
|
||||
//
|
||||
class pxMessageBoxEvent : public BaseMessageBoxEvent
|
||||
{
|
||||
typedef BaseMessageBoxEvent _parent;
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||
|
||||
protected:
|
||||
wxString m_Title;
|
||||
MsgButtons m_Buttons;
|
||||
|
||||
public:
|
||||
pxMessageBoxEvent( int msgtype=pxEVT_MSGBOX )
|
||||
: BaseMessageBoxEvent( msgtype )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~pxMessageBoxEvent() throw() { }
|
||||
virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||
|
||||
pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, const MsgButtons& buttons )
|
||||
: BaseMessageBoxEvent( instdata, content )
|
||||
, m_Title( title )
|
||||
, m_Buttons( buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons )
|
||||
: BaseMessageBoxEvent( content )
|
||||
, m_Title( title )
|
||||
, m_Buttons( buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( const pxMessageBoxEvent& event )
|
||||
: BaseMessageBoxEvent( event )
|
||||
, m_Title( event.m_Title )
|
||||
, m_Buttons( event.m_Buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent& SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
_parent::SetInstData( instdata );
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const
|
||||
{
|
||||
return pxMessageDialog( m_Content, m_Title, m_Buttons );
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxAssertionEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxAssertionEvent : public BaseMessageBoxEvent
|
||||
{
|
||||
typedef BaseMessageBoxEvent _parent;
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN( pxAssertionEvent )
|
||||
|
||||
protected:
|
||||
wxString m_Stacktrace;
|
||||
|
||||
public:
|
||||
pxAssertionEvent()
|
||||
: BaseMessageBoxEvent( pxEVT_ASSERTION )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~pxAssertionEvent() throw() { }
|
||||
|
||||
virtual pxAssertionEvent *Clone() const { return new pxAssertionEvent(*this); }
|
||||
|
||||
pxAssertionEvent( MsgboxEventResult& instdata, const wxString& content, const wxString& trace )
|
||||
: BaseMessageBoxEvent( pxEVT_ASSERTION )
|
||||
, m_Stacktrace( trace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent( const wxString& content, const wxString& trace )
|
||||
: BaseMessageBoxEvent( pxEVT_ASSERTION, content )
|
||||
, m_Stacktrace( trace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent( const pxAssertionEvent& event )
|
||||
: BaseMessageBoxEvent( event )
|
||||
, m_Stacktrace( event.m_Stacktrace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent& SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
_parent::SetInstData( instdata );
|
||||
return *this;
|
||||
}
|
||||
|
||||
pxAssertionEvent& SetStacktrace( const wxString& trace )
|
||||
{
|
||||
m_Stacktrace = trace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const
|
||||
{
|
||||
return Dialogs::AssertionDialog( m_Content, m_Stacktrace ).ShowModal();
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( BaseMessageBoxEvent, wxEvent )
|
||||
|
||||
BaseMessageBoxEvent::BaseMessageBoxEvent( int msgtype, const wxString& content )
|
||||
: wxEvent( 0, msgtype )
|
||||
, m_Content( content )
|
||||
{
|
||||
m_Instdata = NULL;
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent::BaseMessageBoxEvent( MsgboxEventResult& instdata, const wxString& content )
|
||||
: wxEvent( 0, pxEvt_MessageBox )
|
||||
, m_Instdata( &instdata )
|
||||
, m_Content( content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent::BaseMessageBoxEvent( const wxString& content )
|
||||
: wxEvent( 0, pxEvt_MessageBox )
|
||||
, m_Instdata( NULL )
|
||||
, m_Content( content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent::BaseMessageBoxEvent( const BaseMessageBoxEvent& event )
|
||||
: wxEvent( event )
|
||||
, m_Instdata( event.m_Instdata )
|
||||
, m_Content( event.m_Content )
|
||||
{
|
||||
}
|
||||
|
||||
BaseMessageBoxEvent& BaseMessageBoxEvent::SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
m_Instdata = &instdata;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
void BaseMessageBoxEvent::IssueDialog()
|
||||
{
|
||||
AffinityAssert_AllowFromMain();
|
||||
|
||||
int result = _DoDialog();
|
||||
|
||||
if( m_Instdata != NULL )
|
||||
{
|
||||
m_Instdata->result = result;
|
||||
m_Instdata->WaitForMe.Post();
|
||||
}
|
||||
}
|
||||
|
||||
int BaseMessageBoxEvent::_DoDialog() const
|
||||
{
|
||||
pxFailDev( "Abstract Base MessageBox Event." );
|
||||
return wxID_CANCEL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxMessageBoxEvent Implementation
|
||||
// --------------------------------------------------------------------------------------
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, BaseMessageBoxEvent )
|
||||
|
||||
pxMessageBoxEvent::pxMessageBoxEvent( int msgtype )
|
||||
: BaseMessageBoxEvent( msgtype )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent::pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, const MsgButtons& buttons )
|
||||
: BaseMessageBoxEvent( instdata, content )
|
||||
, m_Title( title )
|
||||
, m_Buttons( buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent::pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons )
|
||||
: BaseMessageBoxEvent( content )
|
||||
, m_Title( title )
|
||||
, m_Buttons( buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent::pxMessageBoxEvent( const pxMessageBoxEvent& event )
|
||||
: BaseMessageBoxEvent( event )
|
||||
, m_Title( event.m_Title )
|
||||
, m_Buttons( event.m_Buttons )
|
||||
{
|
||||
}
|
||||
|
||||
pxMessageBoxEvent& pxMessageBoxEvent::SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
_parent::SetInstData( instdata );
|
||||
return *this;
|
||||
}
|
||||
|
||||
int pxMessageBoxEvent::_DoDialog() const
|
||||
{
|
||||
return pxMessageDialog( m_Content, m_Title, m_Buttons );
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxAssertionEvent Implementation
|
||||
// --------------------------------------------------------------------------------------
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxAssertionEvent, BaseMessageBoxEvent )
|
||||
|
||||
pxAssertionEvent::pxAssertionEvent()
|
||||
: BaseMessageBoxEvent( pxEvt_Assertion )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent::pxAssertionEvent( MsgboxEventResult& instdata, const wxString& content, const wxString& trace )
|
||||
: BaseMessageBoxEvent( pxEvt_Assertion )
|
||||
, m_Stacktrace( trace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent::pxAssertionEvent( const wxString& content, const wxString& trace )
|
||||
: BaseMessageBoxEvent( pxEvt_Assertion, content )
|
||||
, m_Stacktrace( trace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent::pxAssertionEvent( const pxAssertionEvent& event )
|
||||
: BaseMessageBoxEvent( event )
|
||||
, m_Stacktrace( event.m_Stacktrace )
|
||||
{
|
||||
}
|
||||
|
||||
pxAssertionEvent& pxAssertionEvent::SetInstData( MsgboxEventResult& instdata )
|
||||
{
|
||||
_parent::SetInstData( instdata );
|
||||
return *this;
|
||||
}
|
||||
|
||||
pxAssertionEvent& pxAssertionEvent::SetStacktrace( const wxString& trace )
|
||||
{
|
||||
m_Stacktrace = trace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int pxAssertionEvent::_DoDialog() const
|
||||
{
|
||||
return Dialogs::AssertionDialog( m_Content, m_Stacktrace ).ShowModal();
|
||||
}
|
||||
|
||||
namespace Msgbox
|
||||
{
|
||||
static int ThreadedMessageBox( BaseMessageBoxEvent& evt )
|
||||
|
@ -325,8 +268,3 @@ namespace Msgbox
|
|||
return ThreadedMessageBox( tevt );
|
||||
}
|
||||
}
|
||||
|
||||
void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
|
||||
{
|
||||
evt.IssueDialog();
|
||||
}
|
||||
|
|
|
@ -50,51 +50,73 @@ public:
|
|||
|
||||
virtual ~AppPluginManager() throw()
|
||||
{
|
||||
PluginEventType pevt = PluginsEvt_Unloaded;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
sApp.PostPluginStatus( PluginsEvt_Unloaded );
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
SetSettingsFolder( GetSettingsFolder().ToString() );
|
||||
|
||||
_parent::Init();
|
||||
|
||||
PluginEventType pevt = PluginsEvt_Init;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
sApp.PostPluginStatus( PluginsEvt_Init );
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
_parent::Shutdown();
|
||||
|
||||
PluginEventType pevt = PluginsEvt_Shutdown;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
sApp.PostPluginStatus( PluginsEvt_Shutdown );
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if( !NeedsClose() ) return;
|
||||
|
||||
sApp.PostPluginStatus( PluginsEvt_Closing );
|
||||
_parent::Close();
|
||||
|
||||
PluginEventType pevt = PluginsEvt_Close;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
sApp.PostPluginStatus( PluginsEvt_Closed );
|
||||
}
|
||||
|
||||
void Open()
|
||||
{
|
||||
SetSettingsFolder( GetSettingsFolder().ToString() );
|
||||
|
||||
_parent::Open();
|
||||
if( !NeedsOpen() ) return;
|
||||
|
||||
PluginEventType pevt = PluginsEvt_Open;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
sApp.PostPluginStatus( PluginsEvt_Opening );
|
||||
_parent::Open();
|
||||
sApp.PostPluginStatus( PluginsEvt_Opened );
|
||||
}
|
||||
|
||||
bool OpenPlugin_GS()
|
||||
{
|
||||
if( GSopen2 != NULL )
|
||||
{
|
||||
sApp.OpenGsPanel();
|
||||
}
|
||||
|
||||
return _parent::OpenPlugin_GS();
|
||||
}
|
||||
|
||||
void ClosePlugin_GS()
|
||||
{
|
||||
_parent::ClosePlugin_GS();
|
||||
sApp.CloseGsPanel();
|
||||
}
|
||||
|
||||
|
||||
/*void Open( PluginsEnum_t pid )
|
||||
{
|
||||
_parent::Open( pid );
|
||||
}
|
||||
|
||||
void Close( PluginsEnum_t pid )
|
||||
{
|
||||
}*/
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// LoadPluginsTask
|
||||
// --------------------------------------------------------------------------------------
|
||||
// On completion the thread sends a pxEVT_LoadPluginsComplete message, which contains a
|
||||
// On completion the thread sends a pxEvt_LoadPluginsComplete message, which contains a
|
||||
// handle to this thread object. If the load is successful, the Result var is set to
|
||||
// non-NULL. If NULL, an error occurred and the thread loads the exception into either
|
||||
// Ex_PluginError or Ex_RuntimeError.
|
||||
|
@ -140,10 +162,7 @@ void LoadPluginsTask::ExecuteTaskInThread()
|
|||
|
||||
void LoadPluginsTask::OnCleanupInThread()
|
||||
{
|
||||
wxCommandEvent evt( pxEVT_LoadPluginsComplete );
|
||||
evt.SetClientData( this );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
|
||||
wxGetApp().PostCommand( this, pxEvt_LoadPluginsComplete );
|
||||
_parent::OnCleanupInThread();
|
||||
}
|
||||
|
||||
|
@ -225,8 +244,10 @@ void ConvertPluginFilenames( wxString (&passins)[PluginId_Count] )
|
|||
// boolean lock modified from the main thread only...
|
||||
static bool plugin_load_lock = false;
|
||||
|
||||
void Pcsx2App::OnReloadPlugins( wxCommandEvent& evt )
|
||||
void Pcsx2App::ReloadPlugins()
|
||||
{
|
||||
if( SelfPostMethod( &Pcsx2App::ReloadPlugins ) ) return;
|
||||
|
||||
if( plugin_load_lock ) return;
|
||||
CoreThread.Cancel();
|
||||
m_CorePlugins = NULL;
|
||||
|
@ -268,9 +289,24 @@ void Pcsx2App::OnLoadPluginsComplete( wxCommandEvent& evt )
|
|||
|
||||
if( fn_tmp != NULL ) fn_tmp( evt );
|
||||
|
||||
PluginEventType pevt = PluginsEvt_Loaded;
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
Source_CorePluginStatus().Dispatch( pevt );
|
||||
PostPluginStatus( PluginsEvt_Loaded );
|
||||
}
|
||||
|
||||
void Pcsx2App::PostPluginStatus( PluginEventType pevt )
|
||||
{
|
||||
if( !wxThread::IsMain() )
|
||||
{
|
||||
PostCommand( pxEvt_PluginStatus, pevt );
|
||||
}
|
||||
else
|
||||
{
|
||||
sApp.Source_CorePluginStatus().Dispatch( pevt );
|
||||
}
|
||||
}
|
||||
|
||||
void Pcsx2App::OnPluginStatus( wxCommandEvent& evt )
|
||||
{
|
||||
PostPluginStatus( (PluginEventType)evt.GetInt() );
|
||||
}
|
||||
|
||||
// Posts a message to the App to reload plugins. Plugins are loaded via a background thread
|
||||
|
@ -282,15 +318,14 @@ void LoadPluginsPassive( FnType_OnThreadComplete* onComplete )
|
|||
// Plugins already loaded?
|
||||
if( wxGetApp().m_CorePlugins )
|
||||
{
|
||||
if( onComplete ) onComplete( wxCommandEvent( pxEVT_LoadPluginsComplete ) );
|
||||
if( onComplete ) onComplete( wxCommandEvent( pxEvt_LoadPluginsComplete ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( onComplete )
|
||||
Callback_PluginsLoadComplete = onComplete;
|
||||
|
||||
wxCommandEvent evt( pxEVT_ReloadPlugins );
|
||||
wxGetApp().AddPendingEvent( evt );
|
||||
wxGetApp().ReloadPlugins();
|
||||
}
|
||||
|
||||
// Performs a blocking load of plugins. If the emulation thread is active, it is shut down
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "wxAppWithHelpers.h"
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEvt_Ping );
|
||||
DEFINE_EVENT_TYPE( pxEvt_MessageBox );
|
||||
DEFINE_EVENT_TYPE( pxEvt_Assertion );
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxPingEvent Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxPingEvent, wxEvent )
|
||||
|
||||
pxPingEvent::pxPingEvent( int msgtype, Semaphore* sema )
|
||||
: wxEvent( 0, msgtype )
|
||||
{
|
||||
m_PostBack = sema;
|
||||
}
|
||||
|
||||
pxPingEvent::pxPingEvent( Semaphore* sema )
|
||||
: wxEvent( 0, pxEvt_Ping )
|
||||
{
|
||||
m_PostBack = sema;
|
||||
}
|
||||
|
||||
pxPingEvent::pxPingEvent( const pxPingEvent& src )
|
||||
: wxEvent( src )
|
||||
{
|
||||
m_PostBack = src.m_PostBack;
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::OnPingEvent( pxPingEvent& evt )
|
||||
{
|
||||
// Ping events are dispatched during the idle event handler, which ensures
|
||||
// the ping is posted only after all other pending messages behind the ping
|
||||
// are also processed.
|
||||
|
||||
m_PingWhenIdle.push_back( evt.GetSemaphore() );
|
||||
m_PingTimer.Start( 200, true );
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::PingDispatch( const char* action )
|
||||
{
|
||||
size_t size = m_PingWhenIdle.size();
|
||||
if( size == 0 ) return;
|
||||
|
||||
DbgCon.WriteLn( Color_Gray, "App Event Ping (%s) -> %u listeners.", action, size );
|
||||
|
||||
for( size_t i=0; i<size; ++i )
|
||||
{
|
||||
if( Semaphore* sema = m_PingWhenIdle[i] ) sema->Post();
|
||||
}
|
||||
|
||||
m_PingWhenIdle.clear();
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::OnIdleEvent( wxIdleEvent& evt )
|
||||
{
|
||||
evt.Skip();
|
||||
m_PingTimer.Stop();
|
||||
PingDispatch( "Idle" );
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::OnPingTimeout( wxTimerEvent& evt )
|
||||
{
|
||||
PingDispatch( "Timeout" );
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::Ping()
|
||||
{
|
||||
DbgCon.WriteLn( Color_Gray, L"App Event Ping Requested from %s thread.", pxGetCurrentThreadName().c_str() );
|
||||
|
||||
Semaphore sema;
|
||||
pxPingEvent evt( &sema );
|
||||
AddPendingEvent( evt );
|
||||
sema.WaitNoCancel();
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::PostCommand( void* clientData, int evtType, int intParam, long longParam, const wxString& stringParam )
|
||||
{
|
||||
wxCommandEvent evt( evtType );
|
||||
evt.SetClientData( clientData );
|
||||
evt.SetInt( intParam );
|
||||
evt.SetExtraLong( longParam );
|
||||
evt.SetString( stringParam );
|
||||
AddPendingEvent( evt );
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::PostCommand( int evtType, int intParam, long longParam, const wxString& stringParam )
|
||||
{
|
||||
PostCommand( NULL, evtType, intParam, longParam, stringParam );
|
||||
}
|
||||
|
||||
|
||||
typedef void (wxEvtHandler::*pxMessageBoxEventFunction)(pxMessageBoxEvent&);
|
||||
typedef void (wxEvtHandler::*pxPingEventFunction)(pxPingEvent&);
|
||||
|
||||
bool wxAppWithHelpers::OnInit()
|
||||
{
|
||||
#define pxMessageBoxEventThing(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
|
||||
|
||||
#define pxPingEventHandler(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxPingEventFunction, &func )
|
||||
|
||||
Connect( pxEvt_MessageBox, pxMessageBoxEventThing (wxAppWithHelpers::OnMessageBox) );
|
||||
Connect( pxEvt_Assertion, pxMessageBoxEventThing (wxAppWithHelpers::OnMessageBox) );
|
||||
Connect( pxEvt_Ping, pxPingEventHandler (wxAppWithHelpers::OnPingEvent) );
|
||||
Connect( wxEvt_Idle, wxIdleEventHandler (wxAppWithHelpers::OnIdleEvent) );
|
||||
|
||||
Connect( m_PingTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(wxAppWithHelpers::OnPingTimeout) );
|
||||
|
||||
return _parent::OnInit();
|
||||
}
|
||||
|
||||
void wxAppWithHelpers::OnMessageBox( pxMessageBoxEvent& evt )
|
||||
{
|
||||
evt.IssueDialog();
|
||||
}
|
||||
|
||||
wxAppWithHelpers::wxAppWithHelpers()
|
||||
: m_PingTimer( this )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// This variable assignment ensures that MSVC links in the TLS setup stubs even in
|
||||
// full optimization builds. Without it, DLLs that use TLS won't work because the
|
||||
// FS segment register won't have been initialized by the main exe, due to tls_insurance
|
||||
// being optimized away >_< --air
|
||||
|
||||
static __threadlocal int tls_insurance = 0;
|
||||
tls_insurance = 1;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IniInterface.h"
|
||||
#include "Utilities/Threading.h"
|
||||
#include "Utilities/wxGuiTools.h"
|
||||
|
||||
using namespace Threading;
|
||||
|
||||
class pxPingEvent;
|
||||
class pxMessageBoxEvent;
|
||||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
DECLARE_EVENT_TYPE( pxEvt_Ping, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_MessageBox, -1 )
|
||||
DECLARE_EVENT_TYPE( pxEvt_Assertion, -1 )
|
||||
END_DECLARE_EVENT_TYPES()
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// AppIniSaver / AppIniLoader
|
||||
// --------------------------------------------------------------------------------------
|
||||
class AppIniSaver : public IniSaver
|
||||
{
|
||||
public:
|
||||
AppIniSaver();
|
||||
virtual ~AppIniSaver() throw() {}
|
||||
};
|
||||
|
||||
class AppIniLoader : public IniLoader
|
||||
{
|
||||
public:
|
||||
AppIniLoader();
|
||||
virtual ~AppIniLoader() throw() {}
|
||||
};
|
||||
|
||||
struct MsgboxEventResult
|
||||
{
|
||||
Semaphore WaitForMe;
|
||||
int result;
|
||||
|
||||
MsgboxEventResult()
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// MsgButtons
|
||||
// --------------------------------------------------------------------------------------
|
||||
class MsgButtons
|
||||
{
|
||||
protected:
|
||||
BITFIELD32()
|
||||
bool
|
||||
m_OK :1,
|
||||
m_Cancel :1,
|
||||
m_Yes :1,
|
||||
m_No :1,
|
||||
m_AllowToAll:1,
|
||||
m_Apply :1,
|
||||
m_Abort :1,
|
||||
m_Retry :1,
|
||||
m_Ignore :1,
|
||||
m_Reset :1,
|
||||
m_Close :1;
|
||||
BITFIELD_END
|
||||
|
||||
wxString m_CustomLabel;
|
||||
|
||||
public:
|
||||
MsgButtons() : bitset( 0 ) { }
|
||||
|
||||
MsgButtons& OK() { m_OK = true; return *this; }
|
||||
MsgButtons& Cancel() { m_Cancel = true; return *this; }
|
||||
MsgButtons& Apply() { m_Apply = true; return *this; }
|
||||
MsgButtons& Yes() { m_Yes = true; return *this; }
|
||||
MsgButtons& No() { m_No = true; return *this; }
|
||||
MsgButtons& ToAll() { m_AllowToAll = true; return *this; }
|
||||
|
||||
MsgButtons& Abort() { m_Abort = true; return *this; }
|
||||
MsgButtons& Retry() { m_Retry = true; return *this; }
|
||||
MsgButtons& Ignore() { m_Ignore = true; return *this; }
|
||||
MsgButtons& Reset() { m_Reset = true; return *this; }
|
||||
MsgButtons& Close() { m_Close = true; return *this; }
|
||||
|
||||
MsgButtons& Custom( const wxString& label)
|
||||
{
|
||||
m_CustomLabel = label;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MsgButtons& OKCancel() { m_OK = m_Cancel = true; return *this; }
|
||||
MsgButtons& YesNo() { m_Yes = m_No = true; return *this; }
|
||||
|
||||
bool HasOK() const { return m_OK; }
|
||||
bool HasCancel() const { return m_Cancel; }
|
||||
bool HasApply() const { return m_Apply; }
|
||||
bool HasYes() const { return m_Yes; }
|
||||
bool HasNo() const { return m_No; }
|
||||
bool AllowsToAll() const{ return m_AllowToAll; }
|
||||
|
||||
bool HasAbort() const { return m_Abort; }
|
||||
bool HasRetry() const { return m_Retry; }
|
||||
bool HasIgnore() const { return m_Ignore; }
|
||||
bool HasReset() const { return m_Reset; }
|
||||
bool HasClose() const { return m_Close; }
|
||||
|
||||
bool HasCustom() const { return !m_CustomLabel.IsEmpty(); }
|
||||
const wxString& GetCustomLabel() const { return m_CustomLabel; }
|
||||
|
||||
bool Allows( wxWindowID id ) const;
|
||||
void SetBestFocus( wxWindow* dialog ) const;
|
||||
void SetBestFocus( wxWindow& dialog ) const;
|
||||
|
||||
bool operator ==( const MsgButtons& right ) const
|
||||
{
|
||||
return OpEqu( bitset );
|
||||
}
|
||||
|
||||
bool operator !=( const MsgButtons& right ) const
|
||||
{
|
||||
return !OpEqu( bitset );
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ModalButtonPanel
|
||||
// --------------------------------------------------------------------------------------
|
||||
class ModalButtonPanel : public wxPanelWithHelpers
|
||||
{
|
||||
public:
|
||||
ModalButtonPanel( wxWindow* window, const MsgButtons& buttons );
|
||||
virtual ~ModalButtonPanel() throw() { }
|
||||
|
||||
virtual void AddActionButton( wxWindowID id );
|
||||
virtual void AddCustomButton( wxWindowID id, const wxString& label );
|
||||
|
||||
virtual void OnActionButtonClicked( wxCommandEvent& evt );
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseMessageBoxEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class BaseMessageBoxEvent : public wxEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent)
|
||||
|
||||
protected:
|
||||
MsgboxEventResult* m_Instdata;
|
||||
wxString m_Content;
|
||||
|
||||
public:
|
||||
virtual ~BaseMessageBoxEvent() throw() { }
|
||||
virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); }
|
||||
|
||||
explicit BaseMessageBoxEvent( int msgtype=pxEvt_MessageBox, const wxString& content=wxEmptyString );
|
||||
BaseMessageBoxEvent( MsgboxEventResult& instdata, const wxString& content );
|
||||
BaseMessageBoxEvent( const wxString& content );
|
||||
BaseMessageBoxEvent( const BaseMessageBoxEvent& event );
|
||||
|
||||
BaseMessageBoxEvent& SetInstData( MsgboxEventResult& instdata );
|
||||
|
||||
virtual void IssueDialog();
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxMessageBoxEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
// This event type is used to transfer message boxes to the main UI thread, and return the
|
||||
// result of the box. It's the only way a message box can be issued from non-main threads
|
||||
// with complete safety in wx2.8.
|
||||
//
|
||||
// For simplicity sake this message box only supports two basic designs. The main design
|
||||
// is a generic message box with confirmation buttons of your choosing. Additionally you
|
||||
// can specify a "scrollableContent" text string, which is added into a read-only richtext
|
||||
// control similar to the console logs and such.
|
||||
//
|
||||
// Future consideration: If wxWidgets 3.0 has improved thread safety, then it should probably
|
||||
// be reasonable for it to work with a more flexable model where the dialog can be created
|
||||
// on a child thread, passed to the main thread, where ShowModal() is run (keeping the nested
|
||||
// message pumps on the main thread where they belong). But so far this is not possible,
|
||||
// because of various subtle issues in wx2.8 design.
|
||||
//
|
||||
class pxMessageBoxEvent : public BaseMessageBoxEvent
|
||||
{
|
||||
typedef BaseMessageBoxEvent _parent;
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||
|
||||
protected:
|
||||
wxString m_Title;
|
||||
MsgButtons m_Buttons;
|
||||
|
||||
public:
|
||||
virtual ~pxMessageBoxEvent() throw() { }
|
||||
virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||
|
||||
explicit pxMessageBoxEvent( int msgtype=pxEvt_MessageBox );
|
||||
|
||||
pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, const MsgButtons& buttons );
|
||||
pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons );
|
||||
pxMessageBoxEvent( const pxMessageBoxEvent& event );
|
||||
|
||||
pxMessageBoxEvent& SetInstData( MsgboxEventResult& instdata );
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxAssertionEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxAssertionEvent : public BaseMessageBoxEvent
|
||||
{
|
||||
typedef BaseMessageBoxEvent _parent;
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN( pxAssertionEvent )
|
||||
|
||||
protected:
|
||||
wxString m_Stacktrace;
|
||||
|
||||
public:
|
||||
pxAssertionEvent();
|
||||
pxAssertionEvent( MsgboxEventResult& instdata, const wxString& content, const wxString& trace );
|
||||
pxAssertionEvent( const wxString& content, const wxString& trace );
|
||||
pxAssertionEvent( const pxAssertionEvent& event );
|
||||
|
||||
pxAssertionEvent& SetInstData( MsgboxEventResult& instdata );
|
||||
pxAssertionEvent& SetStacktrace( const wxString& trace );
|
||||
|
||||
protected:
|
||||
virtual int _DoDialog() const;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxPingEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxPingEvent : public wxEvent
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxPingEvent)
|
||||
|
||||
protected:
|
||||
Semaphore* m_PostBack;
|
||||
|
||||
public:
|
||||
virtual ~pxPingEvent() throw() { }
|
||||
virtual pxPingEvent *Clone() const { return new pxPingEvent(*this); }
|
||||
|
||||
explicit pxPingEvent( int msgtype, Semaphore* sema=NULL );
|
||||
explicit pxPingEvent( Semaphore* sema=NULL );
|
||||
pxPingEvent( const pxPingEvent& src );
|
||||
|
||||
Semaphore* GetSemaphore() { return m_PostBack; }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// wxAppWithHelpers
|
||||
// --------------------------------------------------------------------------------------
|
||||
class wxAppWithHelpers : public wxApp
|
||||
{
|
||||
typedef wxApp _parent;
|
||||
|
||||
protected:
|
||||
std::vector<Semaphore*> m_PingWhenIdle;
|
||||
wxTimer m_PingTimer;
|
||||
|
||||
public:
|
||||
wxAppWithHelpers();
|
||||
virtual ~wxAppWithHelpers() {}
|
||||
|
||||
void PostCommand( void* clientData, int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
||||
void PostCommand( int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
||||
|
||||
void Ping();
|
||||
void PingDispatch( const char* action );
|
||||
|
||||
bool OnInit();
|
||||
//int OnExit();
|
||||
|
||||
protected:
|
||||
void OnIdleEvent( wxIdleEvent& evt );
|
||||
void OnPingEvent( pxPingEvent& evt );
|
||||
void OnPingTimeout( wxTimerEvent& evt );
|
||||
void OnMessageBox( pxMessageBoxEvent& evt );
|
||||
};
|
|
@ -1904,6 +1904,10 @@
|
|||
RelativePath="..\..\gui\Saveslots.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\wxAppWithHelpers.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Dialogs"
|
||||
>
|
||||
|
@ -2571,6 +2575,10 @@
|
|||
RelativePath="..\..\gui\RecentIsoList.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\wxAppWithHelpers.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Win32"
|
||||
|
|
Loading…
Reference in New Issue