diff --git a/pcsx2/Linux/pcsx2.cbp b/pcsx2/Linux/pcsx2.cbp index 4363bf97ff..61a3c509b5 100644 --- a/pcsx2/Linux/pcsx2.cbp +++ b/pcsx2/Linux/pcsx2.cbp @@ -364,7 +364,8 @@ - + + @@ -456,8 +457,10 @@ + - + + diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp index 0151f8eb17..3a45a0556c 100644 --- a/pcsx2/gui/ConsoleLogger.cpp +++ b/pcsx2/gui/ConsoleLogger.cpp @@ -23,7 +23,7 @@ #include #ifdef __WXMSW__ -# include // needed for OutputDebugStirng +# include // needed for OutputDebugString #endif BEGIN_DECLARE_EVENT_TYPES() @@ -39,7 +39,7 @@ DEFINE_EVENT_TYPE(wxEVT_SetTitleText) DEFINE_EVENT_TYPE(wxEVT_DockConsole) DEFINE_EVENT_TYPE(wxEVT_FlushQueue) -// C++ requires abstract destructors to exist, even thought hey're abstract. +// C++ requires abstract destructors to exist, even though they're abstract. PipeRedirectionBase::~PipeRedirectionBase() throw() {} // ---------------------------------------------------------------------------- @@ -236,101 +236,6 @@ enum MenuIDs_t MenuID_FontSize_Huge, }; -void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt ) -{ -#ifdef __WXMSW__ - if( obj == NULL ) return; - pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj; - - // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents - // are always displayed as the last line of the log window). Unfortunately this also - // makes logging very slow, so we only send the message for status changes, so that the - // log aligns itself nicely when we pause emulation or when errors occur. - - ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); - mframe->m_win32_StupidRefreshTricks = 0; -#endif -} - -void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt ) -{ -#ifdef __WXMSW__ - if( obj == NULL ) return; - pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj; - - // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents - // are always displayed as the last line of the log window). Unfortunately this also - // makes logging very slow, so we only send the message for status changes, so that the - // log aligns itself nicely when we pause emulation or when errors occur. - - ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); - mframe->m_win32_StupidRefreshTricks = 0; -#endif -} - -pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent ) - : wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, - wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2 - ) - - , m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) ) - , m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener ( this, OnCorePluginStatusChanged ) ) -{ -#ifdef __WXMSW__ - m_win32_StupidRefreshTricks = 0; - m_win32_LinesPerScroll = 10; -#endif - m_FreezeWrites = false; - - Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) ); - Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) ); - - Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) ); -} - - -void pxLogTextCtrl::OnResize( wxSizeEvent& evt ) -{ -#ifdef __WXMSW__ - // Windows has retarded console window update patterns. This helps smarten them up. - int ctrly = GetSize().y; - int fonty; - GetTextExtent( L"blaH yeah", NULL, &fonty ); - m_win32_LinesPerScroll = (int)((ctrly * 0.72) / fonty); -#endif - - evt.Skip(); -} - -void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt) -{ - //Console.Warning( "Thumb Tracking!!!" ); - m_FreezeWrites = true; - evt.Skip(); -} - -void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt) -{ - //Console.Warning( "Thumb Releasing!!!" ); - m_FreezeWrites = false; - evt.Skip(); -} - -void pxLogTextCtrl::DoFlushUpdate() -{ -#ifdef __WXMSW__ - // EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts - // clearing old history: - ::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff); - - if( ++m_win32_StupidRefreshTricks > m_win32_LinesPerScroll ) - { - m_win32_StupidRefreshTricks = 0; - ::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); - } -#endif -} - // ------------------------------------------------------------------------ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, AppConfig::ConsoleLogOptions& options ) : wxFrame(parent, wxID_ANY, title) @@ -672,7 +577,7 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt ) ScopedLock locker( m_QueueLock ); m_pendingFlushMsg = false; - if( m_TextCtrl.HasWriteLock() ) return; + //if( m_TextCtrl.HasWriteLock() ) return; if( m_CurQueuePos != 0 ) { @@ -691,8 +596,6 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt ) } DoFlushQueue(); - m_TextCtrl.DoFlushUpdate(); - //m_TextCtrl.Thaw(); } @@ -758,9 +661,7 @@ void ConsoleLogFrame::DoFlushQueue() m_TextCtrl.WriteText( &m_QueueBuffer[m_QueueColorSection[i].startpoint] ); } - // Some reports on Windows7 have corrupted cursor when using insertPoint (or - // +1 / -1 ). This works better for some reason: - m_TextCtrl.SetInsertionPointEnd(); //( insertPoint ); + m_TextCtrl.ConcludeIssue( m_pendingFlushes ); m_QueueColorSection.Clear(); m_CurQueuePos = 0; @@ -930,188 +831,3 @@ void Pcsx2App::DisableWindowLogging() const Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Buffered ); Threading::Sleep( 5 ); } - -DEFINE_EVENT_TYPE( pxEVT_MSGBOX ); -DEFINE_EVENT_TYPE( pxEVT_CallStackBox ); - -using namespace Threading; - -// Thread Safety: Must be called from the GUI thread ONLY. -static int pxMessageDialog( const wxString& content, const wxString& caption, long flags ) -{ - if( IsDevBuild && !wxThread::IsMain() ) - throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." ); - - // fixme: If the emulator is currently active and is running in fullscreen mode, then we - // need to either: - // 1) Exit fullscreen mode before issuing the popup. - // 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it. - // - // And in either case the emulation should be paused/suspended for the user. - - return wxMessageDialog( NULL, content, caption, flags ).ShowModal(); -} - -// Thread Safety: Must be called from the GUI thread ONLY. -// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and -// uses fixed-width (modern) fonts. -static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags ) -{ - if( IsDevBuild && !wxThread::IsMain() ) - throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." ); - - return wxMessageDialog( NULL, content, caption, flags ).ShowModal(); -} - -class pxMessageBoxEvent : public wxEvent -{ -protected: - MsgboxEventResult& m_Instdata; - wxString m_Title; - wxString m_Content; - long m_Flags; - -public: - pxMessageBoxEvent() - : wxEvent( 0, pxEVT_MSGBOX ) - , m_Instdata( *(MsgboxEventResult*)NULL ) - , m_Title() - , m_Content() - { - m_Flags = 0; - } - - pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags ) - : wxEvent( 0, pxEVT_MSGBOX ) - , m_Instdata( instdata ) - , m_Title( title ) - , m_Content( content ) - { - m_Flags = flags; - } - - pxMessageBoxEvent( const pxMessageBoxEvent& event ) - : wxEvent( event ) - , m_Instdata( event.m_Instdata ) - , m_Title( event.m_Title ) - , m_Content( event.m_Content ) - { - m_Flags = event.m_Flags; - } - - // Thread Safety: Must be called from the GUI thread ONLY. - void DoTheDialog() - { - int result; - - if( m_id == pxEVT_MSGBOX ) - result = pxMessageDialog( m_Content, m_Title, m_Flags ); - else - result = pxCallstackDialog( m_Content, m_Title, m_Flags ); - m_Instdata.result = result; - m_Instdata.WaitForMe.Post(); - } - - virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); } - -private: - DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent) -}; - -IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent ) - -namespace Msgbox -{ - // parameters: - // flags - messagebox type flags, such as wxOK, wxCANCEL, etc. - // - static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX ) - { - // must pass the message to the main gui thread, and then stall this thread, to avoid - // threaded chaos where our thread keeps running while the popup is awaiting input. - - MsgboxEventResult instdat; - pxMessageBoxEvent tevt( instdat, title, content, flags ); - wxGetApp().AddPendingEvent( tevt ); - instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars. - return instdat.result; - } - - void OnEvent( pxMessageBoxEvent& evt ) - { - evt.DoTheDialog(); - } - - // Pops up an alert Dialog Box with a singular "OK" button. - // Always returns false. - bool Alert( const wxString& text, const wxString& caption, int icon ) - { - icon |= wxOK; - if( wxThread::IsMain() ) - pxMessageDialog( text, caption, icon ); - else - ThreadedMessageBox( text, caption, icon ); - return false; - } - - // Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry, - // true if OK, false if cancel. - bool OkCancel( const wxString& text, const wxString& caption, int icon ) - { - icon |= wxOK | wxCANCEL; - if( wxThread::IsMain() ) - { - return wxID_OK == pxMessageDialog( text, caption, icon ); - } - else - { - return wxID_OK == ThreadedMessageBox( text, caption, icon ); - } - } - - bool YesNo( const wxString& text, const wxString& caption, int icon ) - { - icon |= wxYES_NO; - if( wxThread::IsMain() ) - { - return wxID_YES == pxMessageDialog( text, caption, icon ); - } - else - { - return wxID_YES == ThreadedMessageBox( text, caption, icon ); - } - } - - // [TODO] : This should probably be a fancier looking dialog box with the stacktrace - // displayed inside a wxTextCtrl. - static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons ) - { - buttons |= wxICON_STOP; - - wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt ); - - if( wxThread::IsMain() ) - { - return pxCallstackDialog( text, caption, buttons ); - } - else - { - return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox ); - } - } - - int Assertion( const wxString& text, const wxString& stacktrace ) - { - return CallStack( text, stacktrace, - L"\nDo you want to stop the program?" - L"\nOr press [Cancel] to suppress further assertions.", - L"PCSX2 Assertion Failure", - wxYES_NO | wxCANCEL - ); - } - - void Except( const Exception::BaseException& src ) - { - CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK ); - } -} diff --git a/pcsx2/gui/ConsoleLogger.h b/pcsx2/gui/ConsoleLogger.h index 3fbe7a98fc..0597e34134 100644 --- a/pcsx2/gui/ConsoleLogger.h +++ b/pcsx2/gui/ConsoleLogger.h @@ -97,6 +97,7 @@ protected: #ifdef __WXMSW__ int m_win32_StupidRefreshTricks; + int m_win32_LinesPerPage; int m_win32_LinesPerScroll; #endif bool m_FreezeWrites; @@ -105,7 +106,9 @@ public: pxLogTextCtrl(wxWindow* parent); bool HasWriteLock() const { return m_FreezeWrites; } - void DoFlushUpdate(); + void ConcludeIssue( int lines ); + + virtual void WriteText(const wxString& text); protected: virtual void OnThumbTrack(wxScrollWinEvent& event); @@ -114,7 +117,6 @@ protected: static void __evt_fastcall OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt ); static void __evt_fastcall OnCorePluginStatusChanged( void* obj, PluginEventType& evt ); - }; // -------------------------------------------------------------------------------------- diff --git a/pcsx2/gui/MessageBoxes.cpp b/pcsx2/gui/MessageBoxes.cpp new file mode 100644 index 0000000000..40d78b4e25 --- /dev/null +++ b/pcsx2/gui/MessageBoxes.cpp @@ -0,0 +1,205 @@ +/* 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 . + */ + +#include "PrecompiledHeader.h" +#include "App.h" + +DEFINE_EVENT_TYPE( pxEVT_MSGBOX ); +DEFINE_EVENT_TYPE( pxEVT_CallStackBox ); + +using namespace Threading; + +// Thread Safety: Must be called from the GUI thread ONLY. +static int pxMessageDialog( const wxString& content, const wxString& caption, long flags ) +{ + if( IsDevBuild && !wxThread::IsMain() ) + throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." ); + + // fixme: If the emulator is currently active and is running in fullscreen mode, then we + // need to either: + // 1) Exit fullscreen mode before issuing the popup. + // 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it. + // + // And in either case the emulation should be paused/suspended for the user. + + return wxMessageDialog( NULL, content, caption, flags ).ShowModal(); +} + +// Thread Safety: Must be called from the GUI thread ONLY. +// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and +// uses fixed-width (modern) fonts. +static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags ) +{ + if( IsDevBuild && !wxThread::IsMain() ) + throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." ); + + return wxMessageDialog( NULL, content, caption, flags ).ShowModal(); +} + +// -------------------------------------------------------------------------------------- +// pxMessageBoxEvent +// -------------------------------------------------------------------------------------- +class pxMessageBoxEvent : public wxEvent +{ +protected: + MsgboxEventResult& m_Instdata; + wxString m_Title; + wxString m_Content; + long m_Flags; + +public: + pxMessageBoxEvent() + : wxEvent( 0, pxEVT_MSGBOX ) + , m_Instdata( *(MsgboxEventResult*)NULL ) + , m_Title() + , m_Content() + { + m_Flags = 0; + } + + pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags ) + : wxEvent( 0, pxEVT_MSGBOX ) + , m_Instdata( instdata ) + , m_Title( title ) + , m_Content( content ) + { + m_Flags = flags; + } + + pxMessageBoxEvent( const pxMessageBoxEvent& event ) + : wxEvent( event ) + , m_Instdata( event.m_Instdata ) + , m_Title( event.m_Title ) + , m_Content( event.m_Content ) + { + m_Flags = event.m_Flags; + } + + // Thread Safety: Must be called from the GUI thread ONLY. + void DoTheDialog() + { + int result; + + if( m_id == pxEVT_MSGBOX ) + result = pxMessageDialog( m_Content, m_Title, m_Flags ); + else + result = pxCallstackDialog( m_Content, m_Title, m_Flags ); + m_Instdata.result = result; + m_Instdata.WaitForMe.Post(); + } + + virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); } + +private: + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent) +}; + +IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent ) + +namespace Msgbox +{ + // parameters: + // flags - messagebox type flags, such as wxOK, wxCANCEL, etc. + // + static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX ) + { + // must pass the message to the main gui thread, and then stall this thread, to avoid + // threaded chaos where our thread keeps running while the popup is awaiting input. + + MsgboxEventResult instdat; + pxMessageBoxEvent tevt( instdat, title, content, flags ); + wxGetApp().AddPendingEvent( tevt ); + instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars. + return instdat.result; + } + + void OnEvent( pxMessageBoxEvent& evt ) + { + evt.DoTheDialog(); + } + + // Pops up an alert Dialog Box with a singular "OK" button. + // Always returns false. + bool Alert( const wxString& text, const wxString& caption, int icon ) + { + icon |= wxOK; + if( wxThread::IsMain() ) + pxMessageDialog( text, caption, icon ); + else + ThreadedMessageBox( text, caption, icon ); + return false; + } + + // Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry, + // true if OK, false if cancel. + bool OkCancel( const wxString& text, const wxString& caption, int icon ) + { + icon |= wxOK | wxCANCEL; + if( wxThread::IsMain() ) + { + return wxID_OK == pxMessageDialog( text, caption, icon ); + } + else + { + return wxID_OK == ThreadedMessageBox( text, caption, icon ); + } + } + + bool YesNo( const wxString& text, const wxString& caption, int icon ) + { + icon |= wxYES_NO; + if( wxThread::IsMain() ) + { + return wxID_YES == pxMessageDialog( text, caption, icon ); + } + else + { + return wxID_YES == ThreadedMessageBox( text, caption, icon ); + } + } + + // [TODO] : This should probably be a fancier looking dialog box with the stacktrace + // displayed inside a wxTextCtrl. + static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons ) + { + buttons |= wxICON_STOP; + + wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt ); + + if( wxThread::IsMain() ) + { + return pxCallstackDialog( text, caption, buttons ); + } + else + { + return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox ); + } + } + + int Assertion( const wxString& text, const wxString& stacktrace ) + { + return CallStack( text, stacktrace, + L"\nDo you want to stop the program?" + L"\nOr press [Cancel] to suppress further assertions.", + L"PCSX2 Assertion Failure", + wxYES_NO | wxCANCEL + ); + } + + void Except( const Exception::BaseException& src ) + { + CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK ); + } +} diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp new file mode 100644 index 0000000000..6f5519b4dd --- /dev/null +++ b/pcsx2/gui/pxLogTextCtrl.cpp @@ -0,0 +1,140 @@ +/* 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 . + */ + +#include "PrecompiledHeader.h" +#include "App.h" +#include "ConsoleLogger.h" + +#ifdef __WXMSW__ +# include // needed for windows-specific rich text messages to make scrolling not lame +#endif + +void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt ) +{ +#ifdef __WXMSW__ + if( obj == NULL ) return; + pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj; + + // See ConcludeIssue for details on WM_VSCROLL + + if( mframe->HasWriteLock() ) return; + ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); + mframe->m_win32_StupidRefreshTricks = 0; +#endif +} + +void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt ) +{ +#ifdef __WXMSW__ + if( obj == NULL ) return; + pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj; + + // See ConcludeIssue for details on WM_VSCROLL + + if( mframe->HasWriteLock() ) return; + ::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); + mframe->m_win32_StupidRefreshTricks = 0; +#endif +} + +pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent ) + : wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2 + ) + + , m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) ) + , m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener ( this, OnCorePluginStatusChanged ) ) +{ +#ifdef __WXMSW__ + m_win32_StupidRefreshTricks = 0; + m_win32_LinesPerScroll = 10; +#endif + m_FreezeWrites = false; + + Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) ); + Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) ); + + Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) ); +} + +void pxLogTextCtrl::WriteText(const wxString& text) +{ + // Don't need the update message -- saves some overhead. + DoWriteText( text, SetValue_SelectionOnly ); +} + +void pxLogTextCtrl::OnResize( wxSizeEvent& evt ) +{ +#ifdef __WXMSW__ + // Windows has retarded console window update patterns. This helps smarten them up. + int ctrly = GetSize().y; + int fonty; + GetTextExtent( L"blaH yeah", NULL, &fonty ); + m_win32_LinesPerPage = (ctrly / fonty) + 1; + m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.72; +#endif + + evt.Skip(); +} + +bool m_IsPaused = false; + +void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt) +{ + //Console.Warning( "Thumb Tracking!!!" ); + m_FreezeWrites = true; + if( !m_IsPaused ) + m_IsPaused = CoreThread.Pause(); + + evt.Skip(); +} + +void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt) +{ + //Console.Warning( "Thumb Releasing!!!" ); + m_FreezeWrites = false; + if( m_IsPaused ) + { + CoreThread.Resume(); + m_IsPaused = false; + } + evt.Skip(); +} + +void pxLogTextCtrl::ConcludeIssue( int lines ) +{ + if( HasWriteLock() ) return; + SetInsertionPointEnd(); + +#ifdef __WXMSW__ + + // EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts + // clearing old history: + ::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff); + + // WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents + // are always displayed as the last line of the log window). Unfortunately this also + // makes logging very slow, so we only send the message for status changes, so that the + // log aligns itself nicely when we pause emulation or when errors occur. + + m_win32_StupidRefreshTricks += lines; + m_win32_StupidRefreshTricks %= m_win32_LinesPerPage; + if( m_win32_StupidRefreshTricks > m_win32_LinesPerScroll ) + { + m_win32_StupidRefreshTricks = 0; + ::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); + } +#endif +} diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index b2fb84439b..9569efc296 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -1808,10 +1808,18 @@ RelativePath="..\..\gui\MemoryCardFile.cpp" > + + + + @@ -1879,41 +1887,7 @@ - - - - - - - - - - - - + + + + + + + + + + +