From 97d52323d1f37616a446eb877eb919ef7073a27c Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 1 Dec 2009 15:33:56 +0000 Subject: [PATCH] Implements support for Alt-Enter fullscreen switching, DX9 only! DX10 is still broken, will stay that way until some clever person figures out how to make it work. I've make some comment guidelines in source (see MTGS.cpp). ... also, it's possible DX10 fullscreen will work if bound to, say, Shift-F9 (ie, something beside alt-enter, which DX10 decides to wrangle full unrelenting control of, without our explicit consent, and needs some 20 lines of random COM chaos to disable). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2282 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/MTGS.cpp | 20 ++++++++++++ pcsx2/gui/App.h | 6 ++++ pcsx2/gui/AppCoreThread.cpp | 5 +++ pcsx2/gui/AppMain.cpp | 10 ++++-- pcsx2/gui/FrameForGS.cpp | 62 +++++++++++++++++++----------------- pcsx2/gui/GlobalCommands.cpp | 19 +++++++++++ pcsx2/gui/MainFrame.h | 10 +++--- pcsx2/gui/pxLogTextCtrl.cpp | 12 ++++--- 8 files changed, 103 insertions(+), 41 deletions(-) diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 02c2c3f544..73dbc4323e 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -204,6 +204,26 @@ void SysMtgsThread::OpenPlugin() throw Exception::PluginOpenError( PluginId_GS ); } +// This is the preferred place to implement DXGI fullscreen overrides, using LoadLibrary. +// But I hate COM, I don't know to make this work, and I don't have DX10, so I give up +// and enjoy my working DX9 alt-enter instead. Someone else can fix this mess. --air + +// Also: Prolly needs some DX10 header includes? Which ones? Too many, I gave up. + +#if 0 // defined(__WXMSW__) && defined(_MSC_VER) + wxDynamicLibrary dynlib( L"dxgi.dll" ); + SomeFuncTypeIDunno isThisEvenTheRightFunctionNameIDunno = dynlib.GetSymbol("CreateDXGIFactory"); + if( isThisEvenTheRightFunctionNameIDunno ) + { + // Is this how LoadLibrary for COM works? I dunno. I dont care. + + IDXGIFactory* pFactory; + hr = isThisEvenTheRightFunctionNameIDunno(__uuidof(IDXGIFactory), (void**)(&pFactory) ); + pFactory->MakeWindowAssociation((HWND)&pDsp, DXGI_MWA_NO_WINDOW_CHANGES); + pFactory->Release(); + } +#endif + m_PluginOpened = true; m_sem_OpenDone.Post(); diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 05ce3453bf..6f8740620b 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -414,6 +414,9 @@ public: void SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override=wxEmptyString ); void SysReset(); + GSFrame& GetGSFrame() const; + GSFrame* GetGSFramePtr() const { return m_gsFrame; } + MainEmuFrame& GetMainFrame() const; MainEmuFrame* GetMainFramePtr() const { return m_MainFrame; } bool HasMainFrame() const { return m_MainFrame != NULL; } @@ -574,6 +577,9 @@ DECLARE_APP(Pcsx2App) #define sMainFrame \ if( MainEmuFrame* __frame_ = GetMainFramePtr() ) (*__frame_) +#define sGSFrame \ + if( GSFrame* __gsframe_ = wxGetApp().GetGSFramePtr() ) (*__gsframe_) + // Use this within the scope of a wxWindow (wxDialog or wxFrame). If the window has a valid menu // bar, the command will run, otherwise it will be silently ignored. :) #define sMenuBar \ diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 0d70f05ae4..0590e67dd9 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -187,8 +187,13 @@ void AppCoreThread::StateCheckInThread() { case WXK_SHIFT: m_kevt.m_shiftDown = isDown; return; case WXK_CONTROL: m_kevt.m_controlDown = isDown; return; + + case WXK_ALT: // ALT/MENU are usually the same key? I'm confused. case WXK_MENU: m_kevt.m_altDown = isDown; return; } + + if( vkey != WXK_ALT ) + Console.Warning( "It's not Alt!" ); m_kevt.m_keyCode = vkey; wxGetApp().PostPadKey( m_kevt ); diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index c082abb7f2..4f3526ec88 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -96,7 +96,7 @@ void Pcsx2App::PostPadKey( wxKeyEvent& evt ) } else { - evt.SetId( m_gsFrame->GetId() ); + evt.SetId( m_gsFrame->GetViewport()->GetId() ); m_gsFrame->AddPendingEvent( evt ); } } @@ -391,6 +391,12 @@ MainEmuFrame& Pcsx2App::GetMainFrame() const return *m_MainFrame; } +GSFrame& Pcsx2App::GetGSFrame() const +{ + pxAssert( m_gsFrame != NULL ); + return *m_gsFrame; +} + void AppApplySettings( const AppConfig* oldconf ) { AllowFromMainThreadOnly(); @@ -467,7 +473,7 @@ void Pcsx2App::OpenGsFrame() m_gsFrame = new GSFrame( m_MainFrame, L"PCSX2" ); m_gsFrame->SetFocus(); - pDsp = (uptr)m_gsFrame->GetWindow()->GetHandle(); + pDsp = (uptr)m_gsFrame->GetViewport()->GetHandle(); m_gsFrame->Show(); // The "in the main window" quickie hack... diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 7cf8ba7919..912144ff15 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -20,7 +20,7 @@ #include "wx/utils.h" -void GSFrame::InitDefaultAccelerators() +void GSPanel::InitDefaultAccelerators() { typedef KeyAcceleratorCode AAC; @@ -37,9 +37,11 @@ void GSFrame::InitDefaultAccelerators() m_Accels.Map( AAC( WXK_F8 ), "Sys_TakeSnapshot" ); m_Accels.Map( AAC( WXK_F9 ), "Sys_RenderswitchToggle" ); - m_Accels.Map( AAC( WXK_F10 ), "Sys_LoggingToggle" ); + //m_Accels.Map( AAC( WXK_F10 ), "Sys_LoggingToggle" ); m_Accels.Map( AAC( WXK_F11 ), "Sys_FreezeGS" ); m_Accels.Map( AAC( WXK_F12 ), "Sys_RecordingToggle" ); + + m_Accels.Map( AAC( WXK_RETURN ).Alt(), "FullscreenToggle" ); } GSPanel::GSPanel( wxWindow* parent ) @@ -53,6 +55,8 @@ GSPanel::GSPanel( wxWindow* parent ) if ( !wxWindow::Create(parent, wxID_ANY) ) throw Exception::RuntimeError( "GSPanel constructor esplode!!" ); + InitDefaultAccelerators(); + if( g_Conf->GSWindow.AlwaysHideMouse ) { SetCursor( wxCursor(wxCURSOR_BLANK) ); @@ -61,6 +65,7 @@ GSPanel::GSPanel( wxWindow* parent ) Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSPanel::OnCloseWindow) ); Connect( wxEVT_SIZE, wxSizeEventHandler (GSPanel::OnResize) ); + Connect( wxEVT_KEY_DOWN, wxKeyEventHandler (GSPanel::OnKeyDown) ); Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GSPanel::OnShowMouse) ); Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(GSPanel::OnShowMouse) ); @@ -143,6 +148,30 @@ void GSPanel::OnHideMouseTimeout( wxTimerEvent& evt ) m_CursorShown = false; } +void GSPanel::OnKeyDown( wxKeyEvent& evt ) +{ + // HACK: Legacy PAD plugins expect PCSX2 to ignore keyboard messages on the GS Window while + // the PAD plugin is open, so ignore here (PCSX2 will direct messages routed from PAD directly + // to the APP level message handler, which in turn routes them right back here -- yes it's + // silly, but oh well). + + if( (PADopen != NULL) && CoreThread.IsOpen() ) return; + + const GlobalCommandDescriptor* cmd = NULL; + m_Accels.TryGetValue( KeyAcceleratorCode( evt ).val32, cmd ); + if( cmd == NULL ) + { + evt.Skip(); // Let the global APP handle it if it wants + return; + } + + if( cmd != NULL ) + { + DbgCon.WriteLn( "(gsFrame) Invoking command: %s", cmd->Id ); + cmd->Invoke(); + } +} + void __evt_fastcall GSPanel::OnSettingsApplied( void* obj, int& evt ) { @@ -162,8 +191,6 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title) { SetIcons( wxGetApp().GetIconBundle() ); - InitDefaultAccelerators(); - SetClientSize( g_Conf->GSWindow.WindowSize ); m_gspanel = new GSPanel( this ); @@ -171,7 +198,6 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title) //Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSFrame::OnCloseWindow) ); Connect( wxEVT_MOVE, wxMoveEventHandler (GSFrame::OnMove) ); Connect( wxEVT_SIZE, wxSizeEventHandler (GSFrame::OnResize) ); - Connect( wxEVT_KEY_DOWN, wxKeyEventHandler (GSFrame::OnKeyDown) ); } GSFrame::~GSFrame() throw() @@ -179,7 +205,7 @@ GSFrame::~GSFrame() throw() CoreThread.Suspend(); // Just in case...! } -wxWindow* GSFrame::GetWindow() +wxWindow* GSFrame::GetViewport() { return m_gspanel; } @@ -206,27 +232,3 @@ void GSFrame::OnResize( wxSizeEvent& evt ) // if we skip, the panel is auto-sized to fit our window anyway, which we do not want! //evt.Skip(); } - -void GSFrame::OnKeyDown( wxKeyEvent& evt ) -{ - // HACK: Legacy PAD plugins expect PCSX2 to ignore keyboard messages on the GS Window while - // the PAD plugin is open, so ignore here (PCSX2 will direct messages routed from PAD directly - // to the APP level message handler, which in turn routes them right back here -- yes it's - // silly, but oh well). - - if( (PADopen != NULL) && CoreThread.IsOpen() ) return; - - const GlobalCommandDescriptor* cmd = NULL; - m_Accels.TryGetValue( KeyAcceleratorCode( evt ).val32, cmd ); - if( cmd == NULL ) - { - evt.Skip(); // Let the global APP handle it if it wants - return; - } - - if( cmd != NULL ) - { - DbgCon.WriteLn( "(gsFrame) Invoking command: %s", cmd->Id ); - cmd->Invoke(); - } -} diff --git a/pcsx2/gui/GlobalCommands.cpp b/pcsx2/gui/GlobalCommands.cpp index 2fe67c10b5..0505228c8c 100644 --- a/pcsx2/gui/GlobalCommands.cpp +++ b/pcsx2/gui/GlobalCommands.cpp @@ -153,6 +153,14 @@ namespace Implementations Console.Warning("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc); #endif } + + static bool isFullscreen = false; + + void FullscreenToggle() + { + isFullscreen = !isFullscreen; + sGSFrame.ShowFullScreen( isFullscreen ); + } } // -------------------------------------------------------------------------------------- @@ -242,6 +250,11 @@ static const GlobalCommandDescriptor CommandDeclarations[] = NULL, }, + { "FullscreenToggle", + Implementations::FullscreenToggle, + NULL, + NULL, + }, // Command Declarations terminator: // (must always be last in list!!) @@ -305,6 +318,10 @@ void Pcsx2App::InitDefaultGlobalAccelerators() GlobalAccels.Map( AAC( WXK_TAB ), "Framelimiter_TurboToggle" ); GlobalAccels.Map( AAC( WXK_TAB ).Shift(), "Framelimiter_MasterToggle" ); + // Hack! The following bindings are temporary hacks which are needed because of issues + // with PAD plugin interfacing (the local window-based accelerators in GSPanel are + // currently ignored). + GlobalAccels.Map( AAC( WXK_ESCAPE ), "Sys_Suspend"); GlobalAccels.Map( AAC( WXK_F8 ), "Sys_TakeSnapshot"); GlobalAccels.Map( AAC( WXK_F9 ), "Sys_RenderswitchToggle"); @@ -312,4 +329,6 @@ void Pcsx2App::InitDefaultGlobalAccelerators() GlobalAccels.Map( AAC( WXK_F10 ), "Sys_LoggingToggle"); GlobalAccels.Map( AAC( WXK_F11 ), "Sys_FreezeGS"); GlobalAccels.Map( AAC( WXK_F12 ), "Sys_RecordingToggle"); + + GlobalAccels.Map( AAC( WXK_RETURN ).Alt(), "FullscreenToggle" ); } diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h index 457005211d..d4476ba8e1 100644 --- a/pcsx2/gui/MainFrame.h +++ b/pcsx2/gui/MainFrame.h @@ -27,6 +27,7 @@ class GSPanel : public wxWindow { protected: + AcceleratorDictionary m_Accels; EventListenerBinding m_Listener_SettingsApplied; wxTimer m_HideMouseTimer; bool m_CursorShown; @@ -41,10 +42,13 @@ public: protected: static void __evt_fastcall OnSettingsApplied( void* obj, int& evt ); + void InitDefaultAccelerators(); + void OnCloseWindow( wxCloseEvent& evt ); void OnResize(wxSizeEvent& event); void OnShowMouse( wxMouseEvent& evt ); void OnHideMouseTimeout( wxTimerEvent& evt ); + void OnKeyDown( wxKeyEvent& evt ); }; // -------------------------------------------------------------------------------------- @@ -53,21 +57,17 @@ protected: class GSFrame : public wxFrame { protected: - AcceleratorDictionary m_Accels; - GSPanel* m_gspanel; public: GSFrame(wxWindow* parent, const wxString& title); virtual ~GSFrame() throw(); - wxWindow* GetWindow(); + wxWindow* GetViewport(); protected: - void InitDefaultAccelerators(); void OnMove( wxMoveEvent& evt ); void OnResize( wxSizeEvent& evt ); - void OnKeyDown( wxKeyEvent& evt ); }; struct PluginMenuAddition diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp index 5f03784ad4..27d8037579 100644 --- a/pcsx2/gui/pxLogTextCtrl.cpp +++ b/pcsx2/gui/pxLogTextCtrl.cpp @@ -131,12 +131,16 @@ void pxLogTextCtrl::ConcludeIssue( int lines ) // 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 += lines; + //if( m_win32_StupidRefreshTricks > m_win32_LinesPerScroll ) { + wxTextPos showpos = XYToPosition( 1, GetNumberOfLines()-m_win32_LinesPerScroll ); + if( showpos > 0 ) + ShowPosition( showpos ); + m_win32_StupidRefreshTricks = 0; - ::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); + //::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL); } #endif + }