2015-05-24 04:55:12 +00:00
|
|
|
// Copyright 2008 Dolphin Emulator Project
|
2015-05-17 23:08:10 +00:00
|
|
|
// Licensed under GPLv2+
|
2013-04-18 03:43:35 +00:00
|
|
|
// Refer to the license.txt file included.
|
2008-12-08 05:30:24 +00:00
|
|
|
|
2016-07-08 14:35:03 +00:00
|
|
|
#include <atomic>
|
2014-02-22 22:36:30 +00:00
|
|
|
#include <cstddef>
|
2014-06-24 20:41:12 +00:00
|
|
|
#include <fstream>
|
2014-02-22 22:36:30 +00:00
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2016-07-08 14:35:03 +00:00
|
|
|
#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
|
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
2016-06-24 08:43:46 +00:00
|
|
|
#include <wx/aui/auibook.h>
|
|
|
|
#include <wx/aui/framemanager.h>
|
2014-06-21 00:59:07 +00:00
|
|
|
#include <wx/filename.h>
|
2014-02-22 22:36:30 +00:00
|
|
|
#include <wx/frame.h>
|
|
|
|
#include <wx/icon.h>
|
|
|
|
#include <wx/listbase.h>
|
|
|
|
#include <wx/menu.h>
|
|
|
|
#include <wx/msgdlg.h>
|
|
|
|
#include <wx/panel.h>
|
|
|
|
#include <wx/sizer.h>
|
|
|
|
#include <wx/statusbr.h>
|
|
|
|
#include <wx/textctrl.h>
|
|
|
|
#include <wx/thread.h>
|
2014-02-17 10:18:15 +00:00
|
|
|
|
2014-12-29 10:00:03 +00:00
|
|
|
#include "AudioCommon/AudioCommon.h"
|
|
|
|
|
2014-09-08 01:06:58 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "Common/FileUtil.h"
|
2016-07-08 14:35:03 +00:00
|
|
|
#include "Common/Flag.h"
|
2014-06-05 23:29:54 +00:00
|
|
|
#include "Common/Logging/ConsoleListener.h"
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "Common/Thread.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
|
|
|
|
#include "Core/ConfigManager.h"
|
|
|
|
#include "Core/Core.h"
|
2014-06-21 00:59:07 +00:00
|
|
|
#include "Core/HW/DVDInterface.h"
|
2015-02-04 07:05:22 +00:00
|
|
|
#include "Core/HW/GCKeyboard.h"
|
|
|
|
#include "Core/HW/GCPad.h"
|
2015-02-04 07:48:19 +00:00
|
|
|
#include "Core/HW/Wiimote.h"
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "Core/HotkeyManager.h"
|
2016-08-23 14:19:30 +00:00
|
|
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
|
|
|
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "Core/Movie.h"
|
|
|
|
#include "Core/State.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
#include "DolphinWX/Debugger/CodeWindow.h"
|
2014-02-19 01:56:29 +00:00
|
|
|
#include "DolphinWX/Frame.h"
|
|
|
|
#include "DolphinWX/GameListCtrl.h"
|
|
|
|
#include "DolphinWX/Globals.h"
|
2014-02-22 22:36:30 +00:00
|
|
|
#include "DolphinWX/LogWindow.h"
|
2014-07-08 14:49:33 +00:00
|
|
|
#include "DolphinWX/Main.h"
|
2014-02-22 22:36:30 +00:00
|
|
|
#include "DolphinWX/TASInputDlg.h"
|
|
|
|
#include "DolphinWX/WxUtils.h"
|
|
|
|
|
|
|
|
#include "InputCommon/GCPadStatus.h"
|
2014-02-19 01:56:29 +00:00
|
|
|
|
2014-09-04 22:42:40 +00:00
|
|
|
#include "VideoCommon/OnScreenDisplay.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoCommon/RenderBase.h"
|
|
|
|
#include "VideoCommon/VertexShaderManager.h"
|
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2008-12-08 05:30:24 +00:00
|
|
|
|
2014-11-01 14:33:02 +00:00
|
|
|
#if defined(HAVE_X11) && HAVE_X11
|
|
|
|
// X11Utils nastiness that's only used here
|
2016-06-24 08:43:46 +00:00
|
|
|
namespace X11Utils
|
|
|
|
{
|
|
|
|
Window XWindowFromHandle(void* Handle)
|
2014-11-01 14:33:02 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
return GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(Handle)));
|
2014-11-01 14:33:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
Display* XDisplayFromHandle(void* Handle)
|
2014-11-01 14:33:02 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(GTK_WIDGET(Handle)));
|
2014-11-01 14:33:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-04-15 03:25:35 +00:00
|
|
|
CRenderFrame::CRenderFrame(wxFrame* parent, wxWindowID id, const wxString& title,
|
2016-06-24 08:43:46 +00:00
|
|
|
const wxPoint& pos, const wxSize& size, long style)
|
|
|
|
: wxFrame(parent, id, title, pos, size, style)
|
2010-04-15 03:25:35 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// Give it an icon
|
2016-10-03 07:19:56 +00:00
|
|
|
SetIcons(WxUtils::GetDolphinIconBundle());
|
2013-09-27 12:38:12 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
DragAcceptFiles(true);
|
|
|
|
Bind(wxEVT_DROP_FILES, &CRenderFrame::OnDropFiles, this);
|
2013-09-27 12:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRenderFrame::OnDropFiles(wxDropFilesEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (event.GetNumberOfFiles() != 1)
|
|
|
|
return;
|
|
|
|
if (File::IsDirectory(WxStrToStr(event.GetFiles()[0])))
|
|
|
|
return;
|
|
|
|
|
|
|
|
wxFileName file = event.GetFiles()[0];
|
|
|
|
const std::string filepath = WxStrToStr(file.GetFullPath());
|
|
|
|
|
|
|
|
if (file.GetExt() == "dtm")
|
|
|
|
{
|
|
|
|
if (Core::IsRunning())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!Movie::IsReadOnly())
|
|
|
|
{
|
|
|
|
// let's make the read-only flag consistent at the start of a movie.
|
|
|
|
Movie::SetReadOnly(true);
|
|
|
|
main_frame->GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Check(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Movie::PlayInput(filepath))
|
|
|
|
main_frame->BootGame("");
|
|
|
|
}
|
|
|
|
else if (!Core::IsRunning())
|
|
|
|
{
|
|
|
|
main_frame->BootGame(filepath);
|
|
|
|
}
|
|
|
|
else if (IsValidSavestateDropped(filepath) && Core::IsRunning())
|
|
|
|
{
|
|
|
|
State::LoadAs(filepath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-07-05 16:20:24 +00:00
|
|
|
DVDInterface::ChangeDiscAsHost(filepath);
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
2010-04-15 03:25:35 +00:00
|
|
|
}
|
|
|
|
|
2014-06-24 20:41:12 +00:00
|
|
|
bool CRenderFrame::IsValidSavestateDropped(const std::string& filepath)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
const int game_id_length = 6;
|
|
|
|
std::ifstream file(filepath, std::ios::in | std::ios::binary);
|
2014-06-24 20:41:12 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (!file)
|
|
|
|
return false;
|
2014-06-24 20:41:12 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
std::string internal_game_id(game_id_length, ' ');
|
|
|
|
file.read(&internal_game_id[0], game_id_length);
|
2014-06-24 20:41:12 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
return internal_game_id == SConfig::GetInstance().GetUniqueID();
|
2014-06-24 20:41:12 +00:00
|
|
|
}
|
|
|
|
|
2010-04-15 03:25:35 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
WXLRESULT CRenderFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
switch (nMsg)
|
|
|
|
{
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case SC_SCREENSAVE:
|
|
|
|
case SC_MONITORPOWER:
|
|
|
|
if (Core::GetState() == Core::CORE_RUN && SConfig::GetInstance().bDisableScreenSaver)
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_USER:
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case WM_USER_STOP:
|
|
|
|
main_frame->DoStop();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_USER_SETCURSOR:
|
|
|
|
if (SConfig::GetInstance().bHideCursor && main_frame->RendererHasFocus() &&
|
|
|
|
Core::GetState() == Core::CORE_RUN)
|
|
|
|
SetCursor(wxCURSOR_BLANK);
|
|
|
|
else
|
|
|
|
SetCursor(wxNullCursor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
// Let Core finish initializing before accepting any WM_CLOSE messages
|
|
|
|
if (!Core::IsRunning())
|
|
|
|
break;
|
|
|
|
// Use default action otherwise
|
|
|
|
|
|
|
|
default:
|
|
|
|
// By default let wxWidgets do what it normally does with this event
|
|
|
|
return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
|
|
|
|
}
|
|
|
|
return 0;
|
2010-04-15 03:25:35 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-08-03 21:36:54 +00:00
|
|
|
bool CRenderFrame::ShowFullScreen(bool show, long style)
|
|
|
|
{
|
2014-10-09 09:30:26 +00:00
|
|
|
#if defined WIN32
|
2016-06-24 08:43:46 +00:00
|
|
|
if (show && !g_Config.bBorderlessFullscreen)
|
|
|
|
{
|
|
|
|
// OpenGL requires the pop-up style to activate exclusive mode.
|
|
|
|
SetWindowStyle((GetWindowStyle() & ~wxDEFAULT_FRAME_STYLE) | wxPOPUP_WINDOW);
|
|
|
|
|
|
|
|
// Some backends don't support exclusive fullscreen, so we
|
|
|
|
// can't tell exactly when exclusive mode is activated.
|
|
|
|
if (!g_Config.backend_info.bSupportsExclusiveFullscreen)
|
|
|
|
OSD::AddMessage("Entered exclusive fullscreen.");
|
|
|
|
}
|
2014-10-09 09:30:26 +00:00
|
|
|
#endif
|
2014-08-03 21:36:54 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
bool result = wxTopLevelWindow::ShowFullScreen(show, style);
|
2014-08-03 21:36:54 +00:00
|
|
|
|
2014-10-09 09:30:26 +00:00
|
|
|
#if defined WIN32
|
2016-06-24 08:43:46 +00:00
|
|
|
if (!show)
|
|
|
|
{
|
|
|
|
// Restore the default style.
|
|
|
|
SetWindowStyle((GetWindowStyle() & ~wxPOPUP_WINDOW) | wxDEFAULT_FRAME_STYLE);
|
|
|
|
}
|
2014-10-09 09:30:26 +00:00
|
|
|
#endif
|
2014-08-03 21:36:54 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
return result;
|
2014-08-03 21:36:54 +00:00
|
|
|
}
|
|
|
|
|
2014-11-06 03:19:52 +00:00
|
|
|
wxDEFINE_EVENT(wxEVT_HOST_COMMAND, wxCommandEvent);
|
2016-04-22 10:42:16 +00:00
|
|
|
wxDEFINE_EVENT(DOLPHIN_EVT_LOCAL_INI_CHANGED, wxCommandEvent);
|
2008-12-08 05:30:24 +00:00
|
|
|
|
2016-10-14 18:52:18 +00:00
|
|
|
// Event tables
|
2010-04-15 03:25:35 +00:00
|
|
|
BEGIN_EVENT_TABLE(CFrame, CRenderFrame)
|
2009-09-03 05:24:30 +00:00
|
|
|
|
2016-10-14 18:52:18 +00:00
|
|
|
// Debugger pane context menu
|
2014-12-21 01:36:26 +00:00
|
|
|
EVT_MENU_RANGE(IDM_FLOAT_LOG_WINDOW, IDM_FLOAT_CODE_WINDOW, CFrame::OnFloatWindow)
|
2009-09-05 04:50:45 +00:00
|
|
|
|
2016-10-14 18:52:18 +00:00
|
|
|
// Game list context menu
|
2014-12-21 01:36:26 +00:00
|
|
|
EVT_MENU(IDM_LIST_INSTALL_WAD, CFrame::OnInstallWAD)
|
2009-01-04 21:53:41 +00:00
|
|
|
|
2009-09-03 05:24:30 +00:00
|
|
|
// Other
|
2009-12-30 09:00:43 +00:00
|
|
|
EVT_ACTIVATE(CFrame::OnActive)
|
2009-09-03 05:24:30 +00:00
|
|
|
EVT_CLOSE(CFrame::OnClose)
|
2008-12-12 03:38:50 +00:00
|
|
|
EVT_SIZE(CFrame::OnResize)
|
2010-01-18 18:01:03 +00:00
|
|
|
EVT_MOVE(CFrame::OnMove)
|
2008-12-08 05:30:24 +00:00
|
|
|
EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage)
|
2009-08-25 01:50:27 +00:00
|
|
|
|
2009-08-30 19:44:42 +00:00
|
|
|
EVT_AUI_PANE_CLOSE(CFrame::OnPaneClose)
|
2009-08-26 09:19:15 +00:00
|
|
|
|
2009-09-03 05:24:30 +00:00
|
|
|
// Post events to child panels
|
2010-07-27 02:39:12 +00:00
|
|
|
EVT_MENU_RANGE(IDM_INTERPRETER, IDM_ADDRBOX, CFrame::PostEvent)
|
2009-09-03 05:24:30 +00:00
|
|
|
|
2008-12-08 05:30:24 +00:00
|
|
|
END_EVENT_TABLE()
|
2009-01-05 04:08:18 +00:00
|
|
|
|
2009-09-03 07:56:35 +00:00
|
|
|
// ---------------
|
2009-09-01 12:44:02 +00:00
|
|
|
// Creation and close, quit functions
|
2009-09-01 13:06:37 +00:00
|
|
|
|
2015-02-04 07:05:22 +00:00
|
|
|
bool CFrame::InitControllers()
|
2015-01-27 01:24:47 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (!g_controller_interface.IsInit())
|
|
|
|
{
|
2015-01-27 01:24:47 +00:00
|
|
|
#if defined(HAVE_X11) && HAVE_X11
|
2016-10-11 19:54:35 +00:00
|
|
|
void* win = reinterpret_cast<void*>(X11Utils::XWindowFromHandle(GetHandle()));
|
2015-01-27 01:24:47 +00:00
|
|
|
#else
|
2016-10-11 19:54:35 +00:00
|
|
|
void* win = reinterpret_cast<void*>(GetHandle());
|
2015-01-27 01:24:47 +00:00
|
|
|
#endif
|
2016-10-11 19:54:35 +00:00
|
|
|
g_controller_interface.Initialize(win);
|
|
|
|
Pad::Initialize();
|
|
|
|
Keyboard::Initialize();
|
|
|
|
Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
|
|
|
HotkeyManagerEmu::Initialize();
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2015-01-27 01:24:47 +00:00
|
|
|
}
|
|
|
|
|
2016-07-08 14:35:03 +00:00
|
|
|
static Common::Flag s_shutdown_signal_received;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
static BOOL WINAPI s_ctrl_handler(DWORD fdwCtrlType)
|
|
|
|
{
|
|
|
|
switch (fdwCtrlType)
|
|
|
|
{
|
|
|
|
case CTRL_C_EVENT:
|
|
|
|
case CTRL_BREAK_EVENT:
|
|
|
|
case CTRL_CLOSE_EVENT:
|
|
|
|
case CTRL_LOGOFF_EVENT:
|
|
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
|
|
SetConsoleCtrlHandler(s_ctrl_handler, FALSE);
|
|
|
|
s_shutdown_signal_received.Set();
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, wxRect geometry,
|
|
|
|
bool use_debugger, bool batch_mode, bool show_log_window, long style)
|
|
|
|
: CRenderFrame(parent, id, title, wxDefaultPosition, wxSize(800, 600), style),
|
|
|
|
UseDebugger(use_debugger), m_bBatchMode(batch_mode),
|
|
|
|
m_toolbar_bitmap_size(FromDIP(wxSize(32, 32)))
|
2008-12-08 05:30:24 +00:00
|
|
|
{
|
2016-10-14 18:52:18 +00:00
|
|
|
BindMenuBarEvents();
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
for (int i = 0; i <= IDM_CODE_WINDOW - IDM_LOG_WINDOW; i++)
|
|
|
|
bFloatWindow[i] = false;
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
if (show_log_window)
|
2016-06-24 08:43:46 +00:00
|
|
|
SConfig::GetInstance().m_InterfaceLogWindow = true;
|
|
|
|
|
|
|
|
// Debugger class
|
|
|
|
if (UseDebugger)
|
|
|
|
{
|
|
|
|
g_pCodeWindow = new CCodeWindow(SConfig::GetInstance(), this, IDM_CODE_WINDOW);
|
|
|
|
LoadIniPerspectives();
|
|
|
|
g_pCodeWindow->Load();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create toolbar bitmaps
|
|
|
|
InitBitmaps();
|
|
|
|
|
|
|
|
// Give it a status bar
|
|
|
|
SetStatusBar(CreateStatusBar(2, wxST_SIZEGRIP, ID_STATUSBAR));
|
|
|
|
if (!SConfig::GetInstance().m_InterfaceStatusbar)
|
|
|
|
GetStatusBar()->Hide();
|
|
|
|
|
|
|
|
// Give it a menu bar
|
2016-10-14 18:52:18 +00:00
|
|
|
SetMenuBar(CreateMenuBar());
|
2016-06-24 08:43:46 +00:00
|
|
|
// Create a menubar to service requests while the real menubar is hidden from the screen
|
2016-10-10 20:41:58 +00:00
|
|
|
m_menubar_shadow = CreateMenuBar();
|
2016-06-24 08:43:46 +00:00
|
|
|
|
|
|
|
// ---------------
|
|
|
|
// Main panel
|
|
|
|
// This panel is the parent for rendering and it holds the gamelistctrl
|
|
|
|
m_Panel = new wxPanel(this, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0);
|
|
|
|
|
|
|
|
m_GameListCtrl = new CGameListCtrl(m_Panel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
|
|
|
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT);
|
|
|
|
m_GameListCtrl->Bind(wxEVT_LIST_ITEM_ACTIVATED, &CFrame::OnGameListCtrlItemActivated, this);
|
|
|
|
|
|
|
|
wxBoxSizer* sizerPanel = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
sizerPanel->Add(m_GameListCtrl, 1, wxEXPAND | wxALL);
|
|
|
|
m_Panel->SetSizer(sizerPanel);
|
|
|
|
// ---------------
|
|
|
|
|
|
|
|
// Manager
|
|
|
|
m_Mgr = new wxAuiManager(this, wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE);
|
|
|
|
|
|
|
|
m_Mgr->AddPane(m_Panel, wxAuiPaneInfo()
|
|
|
|
.Name("Pane 0")
|
|
|
|
.Caption("Pane 0")
|
|
|
|
.PaneBorder(false)
|
|
|
|
.CaptionVisible(false)
|
|
|
|
.Layer(0)
|
|
|
|
.Center()
|
|
|
|
.Show());
|
|
|
|
if (!g_pCodeWindow)
|
|
|
|
m_Mgr->AddPane(CreateEmptyNotebook(), wxAuiPaneInfo()
|
|
|
|
.Name("Pane 1")
|
|
|
|
.Caption(_("Logging"))
|
|
|
|
.CaptionVisible(true)
|
|
|
|
.Layer(0)
|
|
|
|
.FloatingSize(wxSize(600, 350))
|
|
|
|
.CloseButton(true)
|
|
|
|
.Hide());
|
|
|
|
AuiFullscreen = m_Mgr->SavePerspective();
|
|
|
|
|
|
|
|
// Create toolbar
|
|
|
|
RecreateToolbar();
|
|
|
|
if (!SConfig::GetInstance().m_InterfaceToolbar)
|
|
|
|
DoToggleToolbar(false);
|
|
|
|
|
|
|
|
m_LogWindow = new CLogWindow(this, IDM_LOG_WINDOW);
|
|
|
|
m_LogWindow->Hide();
|
|
|
|
m_LogWindow->Disable();
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; ++i)
|
|
|
|
g_TASInputDlg[i] = new TASInputDlg(this);
|
|
|
|
|
|
|
|
Movie::SetGCInputManip(GCTASManipFunction);
|
|
|
|
Movie::SetWiiInputManip(WiiTASManipFunction);
|
|
|
|
|
|
|
|
State::SetOnAfterLoadCallback(OnAfterLoadCallback);
|
|
|
|
Core::SetOnStoppedCallback(OnStoppedCallback);
|
|
|
|
|
|
|
|
// Setup perspectives
|
|
|
|
if (g_pCodeWindow)
|
|
|
|
{
|
|
|
|
// Load perspective
|
|
|
|
DoLoadPerspective();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (SConfig::GetInstance().m_InterfaceLogWindow)
|
|
|
|
ToggleLogWindow(true);
|
|
|
|
if (SConfig::GetInstance().m_InterfaceLogConfigWindow)
|
|
|
|
ToggleLogConfigWindow(true);
|
|
|
|
}
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
// Setup the window size.
|
|
|
|
// This has to be done here instead of in Main because the Show() happens here.
|
|
|
|
SetMinSize(FromDIP(wxSize(400, 300)));
|
|
|
|
WxUtils::SetWindowSizeAndFitToScreen(this, geometry.GetPosition(), geometry.GetSize(),
|
|
|
|
FromDIP(wxSize(800, 600)));
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
// Start debugging maximized (Must be after the window has been positioned)
|
|
|
|
if (UseDebugger)
|
|
|
|
Maximize(true);
|
2016-06-24 08:43:46 +00:00
|
|
|
|
|
|
|
// Commit
|
|
|
|
m_Mgr->Update();
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
// The window must be shown for m_XRRConfig to be created (wxGTK will not allocate X11
|
|
|
|
// resources until the window is shown for the first time).
|
|
|
|
Show();
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
SetToolTip("");
|
|
|
|
GetToolTip()->SetAutoPop(25000);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
|
|
|
m_XRRConfig = new X11Utils::XRRConfiguration(X11Utils::XDisplayFromHandle(GetHandle()),
|
|
|
|
X11Utils::XWindowFromHandle(GetHandle()));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// -------------------------
|
|
|
|
// Connect event handlers
|
|
|
|
|
|
|
|
m_Mgr->Bind(wxEVT_AUI_RENDER, &CFrame::OnManagerResize, this);
|
|
|
|
// ----------
|
|
|
|
|
|
|
|
// Update controls
|
|
|
|
UpdateGUI();
|
|
|
|
if (g_pCodeWindow)
|
|
|
|
g_pCodeWindow->UpdateButtonStates();
|
|
|
|
|
|
|
|
// check if game is running
|
|
|
|
InitControllers();
|
|
|
|
|
|
|
|
m_poll_hotkey_timer.SetOwner(this);
|
2016-07-08 14:35:03 +00:00
|
|
|
Bind(wxEVT_TIMER, &CFrame::PollHotkeys, this, m_poll_hotkey_timer.GetId());
|
2016-06-24 08:43:46 +00:00
|
|
|
m_poll_hotkey_timer.Start(1000 / 60, wxTIMER_CONTINUOUS);
|
2016-07-08 14:35:03 +00:00
|
|
|
|
|
|
|
// Shut down cleanly on SIGINT, SIGTERM (Unix) and on various signals on Windows
|
|
|
|
m_handle_signal_timer.SetOwner(this);
|
|
|
|
Bind(wxEVT_TIMER, &CFrame::HandleSignal, this, m_handle_signal_timer.GetId());
|
|
|
|
m_handle_signal_timer.Start(100, wxTIMER_CONTINUOUS);
|
|
|
|
|
|
|
|
#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
|
|
|
|
struct sigaction sa;
|
2016-07-09 15:38:27 +00:00
|
|
|
sa.sa_handler = [](int unused) {
|
|
|
|
char message[] = "A signal was received. A second signal will force Dolphin to stop.\n";
|
|
|
|
write(STDERR_FILENO, message, sizeof(message));
|
|
|
|
s_shutdown_signal_received.Set();
|
|
|
|
};
|
2016-07-08 14:35:03 +00:00
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = SA_RESETHAND;
|
|
|
|
sigaction(SIGINT, &sa, nullptr);
|
|
|
|
sigaction(SIGTERM, &sa, nullptr);
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
SetConsoleCtrlHandler(s_ctrl_handler, TRUE);
|
|
|
|
#endif
|
2008-12-08 05:30:24 +00:00
|
|
|
}
|
2009-01-04 21:53:41 +00:00
|
|
|
// Destructor
|
|
|
|
CFrame::~CFrame()
|
2008-12-08 05:30:24 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
Wiimote::Shutdown();
|
|
|
|
Keyboard::Shutdown();
|
|
|
|
Pad::Shutdown();
|
|
|
|
HotkeyManagerEmu::Shutdown();
|
2016-10-11 19:54:35 +00:00
|
|
|
g_controller_interface.Shutdown();
|
2015-01-27 01:24:47 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
drives.clear();
|
2009-09-01 12:44:02 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
|
|
|
delete m_XRRConfig;
|
|
|
|
#endif
|
2013-09-10 08:04:29 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
ClosePages();
|
2013-09-10 08:04:29 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
delete m_Mgr;
|
2014-09-06 05:15:10 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
// This object is owned by us, not wxw
|
|
|
|
m_menubar_shadow->Destroy();
|
|
|
|
m_menubar_shadow = nullptr;
|
2008-12-08 05:30:24 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 01:33:10 +00:00
|
|
|
bool CFrame::RendererIsFullscreen()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
bool fullscreen = false;
|
2013-03-31 16:08:29 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
|
|
|
|
{
|
|
|
|
fullscreen = m_RenderFrame->IsFullScreen();
|
|
|
|
}
|
2013-03-31 16:08:29 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
return fullscreen;
|
2010-04-12 01:33:10 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
void CFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
2009-01-05 04:08:18 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
Close(true);
|
2009-01-05 04:08:18 +00:00
|
|
|
}
|
|
|
|
|
2009-09-03 07:56:35 +00:00
|
|
|
// --------
|
2009-09-01 15:16:44 +00:00
|
|
|
// Events
|
2009-12-30 09:00:43 +00:00
|
|
|
void CFrame::OnActive(wxActivateEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
|
|
|
|
{
|
|
|
|
if (event.GetActive() && event.GetEventObject() == m_RenderFrame)
|
|
|
|
{
|
|
|
|
if (SConfig::GetInstance().bRenderToMain)
|
|
|
|
m_RenderParent->SetFocus();
|
|
|
|
|
|
|
|
if (SConfig::GetInstance().bHideCursor && Core::GetState() == Core::CORE_RUN)
|
|
|
|
m_RenderParent->SetCursor(wxCURSOR_BLANK);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
m_RenderParent->SetCursor(wxNullCursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
event.Skip();
|
2009-12-30 09:00:43 +00:00
|
|
|
}
|
2009-09-01 15:16:44 +00:00
|
|
|
|
2009-01-05 04:08:18 +00:00
|
|
|
void CFrame::OnClose(wxCloseEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// Before closing the window we need to shut down the emulation core.
|
|
|
|
// We'll try to close this window again once that is done.
|
|
|
|
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
|
|
|
{
|
|
|
|
DoStop();
|
|
|
|
if (event.CanVeto())
|
|
|
|
{
|
|
|
|
event.Veto();
|
|
|
|
}
|
|
|
|
// Tell OnStopped to resubmit the Close event
|
2016-10-04 20:54:55 +00:00
|
|
|
m_bClosing = true;
|
2016-06-24 08:43:46 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop Dolphin from saving the minimized Xpos and Ypos
|
|
|
|
if (main_frame->IsIconized())
|
|
|
|
main_frame->Iconize(false);
|
|
|
|
|
|
|
|
// Don't forget the skip or the window won't be destroyed
|
|
|
|
event.Skip();
|
|
|
|
|
|
|
|
// Save GUI settings
|
|
|
|
if (g_pCodeWindow)
|
|
|
|
{
|
|
|
|
SaveIniPerspectives();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-03 07:29:50 +00:00
|
|
|
m_LogWindow->SaveSettings();
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
2016-10-03 07:29:50 +00:00
|
|
|
if (m_LogWindow)
|
|
|
|
m_LogWindow->RemoveAllListeners();
|
2016-06-24 08:43:46 +00:00
|
|
|
|
|
|
|
// Uninit
|
|
|
|
m_Mgr->UnInit();
|
2009-01-05 04:08:18 +00:00
|
|
|
}
|
2009-08-26 09:19:15 +00:00
|
|
|
|
2009-09-01 15:16:44 +00:00
|
|
|
// Post events
|
2009-09-01 07:32:07 +00:00
|
|
|
|
2009-09-01 15:16:44 +00:00
|
|
|
// Warning: This may cause an endless loop if the event is propagated back to its parent
|
|
|
|
void CFrame::PostEvent(wxCommandEvent& event)
|
2009-08-27 07:33:07 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (g_pCodeWindow && event.GetId() >= IDM_INTERPRETER && event.GetId() <= IDM_ADDRBOX)
|
|
|
|
{
|
|
|
|
event.StopPropagation();
|
|
|
|
g_pCodeWindow->GetEventHandler()->AddPendingEvent(event);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event.Skip();
|
|
|
|
}
|
2009-08-31 05:56:30 +00:00
|
|
|
}
|
|
|
|
|
2010-01-18 18:01:03 +00:00
|
|
|
void CFrame::OnMove(wxMoveEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
event.Skip();
|
|
|
|
|
|
|
|
if (!IsMaximized() && !(SConfig::GetInstance().bRenderToMain && RendererIsFullscreen()))
|
|
|
|
{
|
|
|
|
SConfig::GetInstance().iPosX = GetPosition().x;
|
|
|
|
SConfig::GetInstance().iPosY = GetPosition().y;
|
|
|
|
}
|
2010-01-18 18:01:03 +00:00
|
|
|
}
|
2010-03-08 23:29:16 +00:00
|
|
|
|
2009-09-07 12:40:43 +00:00
|
|
|
void CFrame::OnResize(wxSizeEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
event.Skip();
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
if (!IsMaximized() && !IsIconized() &&
|
|
|
|
!(SConfig::GetInstance().bRenderToMain && RendererIsFullscreen()) &&
|
2016-06-24 08:43:46 +00:00
|
|
|
!(Core::GetState() != Core::CORE_UNINITIALIZED && SConfig::GetInstance().bRenderToMain &&
|
|
|
|
SConfig::GetInstance().bRenderWindowAutoSize))
|
|
|
|
{
|
|
|
|
SConfig::GetInstance().iWidth = GetSize().GetWidth();
|
|
|
|
SConfig::GetInstance().iHeight = GetSize().GetHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the logger pane is a sane size
|
|
|
|
if (!g_pCodeWindow && m_LogWindow && m_Mgr->GetPane("Pane 1").IsShown() &&
|
|
|
|
!m_Mgr->GetPane("Pane 1").IsFloating() &&
|
|
|
|
(m_LogWindow->x > GetClientRect().GetWidth() || m_LogWindow->y > GetClientRect().GetHeight()))
|
|
|
|
ShowResizePane();
|
2009-09-07 12:40:43 +00:00
|
|
|
}
|
2009-08-31 05:56:30 +00:00
|
|
|
|
2009-09-01 12:44:02 +00:00
|
|
|
// Host messages
|
2009-09-01 13:06:37 +00:00
|
|
|
|
2008-12-14 17:37:59 +00:00
|
|
|
#ifdef _WIN32
|
2009-07-02 21:17:36 +00:00
|
|
|
WXLRESULT CFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (WM_SYSCOMMAND == nMsg && (SC_SCREENSAVE == wParam || SC_MONITORPOWER == wParam))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (nMsg == WM_QUERYENDSESSION)
|
|
|
|
{
|
|
|
|
// Indicate that the application will be able to close
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (nMsg == WM_ENDSESSION)
|
|
|
|
{
|
|
|
|
// Actually trigger the close now
|
|
|
|
Close(true);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
|
|
|
|
}
|
2009-07-02 21:17:36 +00:00
|
|
|
}
|
2009-01-04 21:53:41 +00:00
|
|
|
#endif
|
2008-12-08 05:30:24 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
void CFrame::UpdateTitle(const std::string& str)
|
2014-08-19 14:17:33 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (SConfig::GetInstance().bRenderToMain && SConfig::GetInstance().m_InterfaceStatusbar)
|
|
|
|
{
|
|
|
|
GetStatusBar()->SetStatusText(str, 0);
|
|
|
|
m_RenderFrame->SetTitle(scm_rev_str);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string titleStr = StringFromFormat("%s | %s", scm_rev_str.c_str(), str.c_str());
|
|
|
|
m_RenderFrame->SetTitle(titleStr);
|
|
|
|
}
|
2014-08-19 14:17:33 +00:00
|
|
|
}
|
|
|
|
|
2008-12-08 05:30:24 +00:00
|
|
|
void CFrame::OnHostMessage(wxCommandEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
switch (event.GetId())
|
|
|
|
{
|
2016-10-03 07:29:50 +00:00
|
|
|
case IDM_UPDATE_DISASM_DIALOG: // For breakpoints causing pausing
|
|
|
|
if (!g_pCodeWindow || Core::GetState() != Core::CORE_PAUSE)
|
|
|
|
return;
|
|
|
|
// fallthrough
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
case IDM_UPDATE_GUI:
|
|
|
|
UpdateGUI();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_UPDATE_STATUS_BAR:
|
|
|
|
if (GetStatusBar() != nullptr)
|
|
|
|
GetStatusBar()->SetStatusText(event.GetString(), event.GetInt());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_UPDATE_TITLE:
|
|
|
|
UpdateTitle(WxStrToStr(event.GetString()));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_WINDOW_SIZE_REQUEST:
|
|
|
|
{
|
|
|
|
std::pair<int, int>* win_size = (std::pair<int, int>*)(event.GetClientData());
|
|
|
|
OnRenderWindowSizeRequest(win_size->first, win_size->second);
|
|
|
|
delete win_size;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_FULLSCREEN_REQUEST:
|
|
|
|
{
|
|
|
|
bool enable_fullscreen = event.GetInt() == 0 ? false : true;
|
|
|
|
ToggleDisplayMode(enable_fullscreen);
|
|
|
|
if (m_RenderFrame != nullptr)
|
|
|
|
m_RenderFrame->ShowFullScreen(enable_fullscreen);
|
|
|
|
|
|
|
|
// If the stop dialog initiated this fullscreen switch then we need
|
|
|
|
// to pause the emulator after we've completed the switch.
|
|
|
|
// TODO: Allow the renderer to switch fullscreen modes while paused.
|
|
|
|
if (m_confirmStop)
|
|
|
|
Core::SetState(Core::CORE_PAUSE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_USER_CREATE:
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
m_RenderParent->SetCursor(wxCURSOR_BLANK);
|
|
|
|
break;
|
2012-05-02 19:40:40 +00:00
|
|
|
|
2012-12-17 03:32:14 +00:00
|
|
|
#ifdef __WXGTK__
|
2016-06-24 08:43:46 +00:00
|
|
|
case IDM_PANIC:
|
|
|
|
{
|
|
|
|
wxString caption = event.GetString().BeforeFirst(':');
|
|
|
|
wxString text = event.GetString().AfterFirst(':');
|
|
|
|
bPanicResult = (wxYES == wxMessageBox(text, caption, event.GetInt() ? wxYES_NO : wxOK,
|
|
|
|
wxWindow::FindFocus()));
|
|
|
|
panic_event.Set();
|
|
|
|
}
|
|
|
|
break;
|
2010-11-11 00:55:06 +00:00
|
|
|
#endif
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
case WM_USER_STOP:
|
|
|
|
DoStop();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_STOPPED:
|
|
|
|
OnStopped();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_FORCE_CONNECT_WIIMOTE1:
|
|
|
|
case IDM_FORCE_CONNECT_WIIMOTE2:
|
|
|
|
case IDM_FORCE_CONNECT_WIIMOTE3:
|
|
|
|
case IDM_FORCE_CONNECT_WIIMOTE4:
|
|
|
|
case IDM_FORCE_CONNECT_BALANCEBOARD:
|
|
|
|
ConnectWiimote(event.GetId() - IDM_FORCE_CONNECT_WIIMOTE1, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDM_FORCE_DISCONNECT_WIIMOTE1:
|
|
|
|
case IDM_FORCE_DISCONNECT_WIIMOTE2:
|
|
|
|
case IDM_FORCE_DISCONNECT_WIIMOTE3:
|
|
|
|
case IDM_FORCE_DISCONNECT_WIIMOTE4:
|
|
|
|
case IDM_FORCE_DISCONNECT_BALANCEBOARD:
|
|
|
|
ConnectWiimote(event.GetId() - IDM_FORCE_DISCONNECT_WIIMOTE1, false);
|
|
|
|
break;
|
|
|
|
}
|
2009-09-07 12:40:43 +00:00
|
|
|
}
|
|
|
|
|
2011-01-25 03:30:12 +00:00
|
|
|
void CFrame::OnRenderWindowSizeRequest(int width, int height)
|
2011-01-07 04:57:59 +00:00
|
|
|
{
|
2016-10-03 07:29:50 +00:00
|
|
|
if (!SConfig::GetInstance().bRenderWindowAutoSize || !Core::IsRunning() ||
|
2016-06-24 08:43:46 +00:00
|
|
|
RendererIsFullscreen() || m_RenderFrame->IsMaximized())
|
|
|
|
return;
|
|
|
|
|
2016-10-03 07:29:50 +00:00
|
|
|
wxSize requested_size(width, height);
|
|
|
|
// Convert to window pixels, since the size is from the backend it will be in framebuffer px.
|
|
|
|
requested_size *= 1.0 / m_RenderFrame->GetContentScaleFactor();
|
|
|
|
wxSize old_size;
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2016-10-03 07:29:50 +00:00
|
|
|
if (!SConfig::GetInstance().bRenderToMain)
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
2016-10-03 07:29:50 +00:00
|
|
|
old_size = m_RenderFrame->GetClientSize();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Resize for the render panel only, this implicitly retains space for everything else
|
|
|
|
// (i.e. log panel, toolbar, statusbar, etc) without needing to compute for them.
|
|
|
|
old_size = m_RenderParent->GetSize();
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
|
2016-10-03 07:29:50 +00:00
|
|
|
wxSize diff = requested_size - old_size;
|
|
|
|
if (diff != wxSize())
|
|
|
|
m_RenderFrame->SetSize(m_RenderFrame->GetSize() + diff);
|
2011-01-07 04:57:59 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 01:33:10 +00:00
|
|
|
bool CFrame::RendererHasFocus()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (m_RenderParent == nullptr)
|
|
|
|
return false;
|
2014-07-16 14:21:22 +00:00
|
|
|
#ifdef _WIN32
|
2016-06-24 08:43:46 +00:00
|
|
|
HWND window = GetForegroundWindow();
|
|
|
|
if (window == nullptr)
|
|
|
|
return false;
|
2014-06-15 11:13:37 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (m_RenderFrame->GetHWND() == window)
|
|
|
|
return true;
|
2014-07-16 14:21:22 +00:00
|
|
|
#else
|
2016-06-24 08:43:46 +00:00
|
|
|
wxWindow* window = wxWindow::FindFocus();
|
|
|
|
if (window == nullptr)
|
|
|
|
return false;
|
|
|
|
// Why these different cases?
|
|
|
|
if (m_RenderParent == window || m_RenderParent == window->GetParent() ||
|
|
|
|
m_RenderParent->GetParent() == window->GetParent())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2014-07-16 14:21:22 +00:00
|
|
|
#endif
|
2016-06-24 08:43:46 +00:00
|
|
|
return false;
|
2010-04-12 01:33:10 +00:00
|
|
|
}
|
|
|
|
|
2014-07-16 14:24:40 +00:00
|
|
|
bool CFrame::UIHasFocus()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// UIHasFocus should return true any time any one of our UI
|
|
|
|
// windows has the focus, including any dialogs or other windows.
|
|
|
|
//
|
|
|
|
// wxWindow::FindFocus() returns the current wxWindow which has
|
|
|
|
// focus. If it's not one of our windows, then it will return
|
|
|
|
// null.
|
|
|
|
|
|
|
|
wxWindow* focusWindow = wxWindow::FindFocus();
|
|
|
|
return (focusWindow != nullptr);
|
2014-07-16 14:24:40 +00:00
|
|
|
}
|
|
|
|
|
2015-03-13 20:47:06 +00:00
|
|
|
void CFrame::OnGameListCtrlItemActivated(wxListEvent& WXUNUSED(event))
|
2009-01-07 09:06:42 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// Show all platforms and regions if...
|
|
|
|
// 1. All platforms are set to hide
|
|
|
|
// 2. All Regions are set to hide
|
|
|
|
// Otherwise call BootGame to either...
|
|
|
|
// 1. Boot the selected iso
|
|
|
|
// 2. Boot the default or last loaded iso.
|
|
|
|
// 3. Call BrowseForDirectory if the gamelist is empty
|
|
|
|
if (!m_GameListCtrl->GetISO(0) && CGameListCtrl::IsHidingItems())
|
|
|
|
{
|
|
|
|
SConfig::GetInstance().m_ListGC = SConfig::GetInstance().m_ListWii =
|
|
|
|
SConfig::GetInstance().m_ListWad = SConfig::GetInstance().m_ListElfDol =
|
|
|
|
SConfig::GetInstance().m_ListJap = SConfig::GetInstance().m_ListUsa =
|
|
|
|
SConfig::GetInstance().m_ListPal = SConfig::GetInstance().m_ListAustralia =
|
|
|
|
SConfig::GetInstance().m_ListFrance = SConfig::GetInstance().m_ListGermany =
|
|
|
|
SConfig::GetInstance().m_ListItaly = SConfig::GetInstance().m_ListKorea =
|
|
|
|
SConfig::GetInstance().m_ListNetherlands =
|
|
|
|
SConfig::GetInstance().m_ListRussia =
|
|
|
|
SConfig::GetInstance().m_ListSpain =
|
|
|
|
SConfig::GetInstance().m_ListTaiwan =
|
|
|
|
SConfig::GetInstance().m_ListWorld =
|
|
|
|
SConfig::GetInstance().m_ListUnknown = true;
|
|
|
|
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_GC)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_WII)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_WAD)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_JAP)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_USA)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_PAL)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_AUSTRALIA)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_FRANCE)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_GERMANY)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_ITALY)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_KOREA)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_NETHERLANDS)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_RUSSIA)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_SPAIN)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_TAIWAN)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_WORLD)->Check(true);
|
|
|
|
GetMenuBar()->FindItem(IDM_LIST_UNKNOWN)->Check(true);
|
|
|
|
|
2016-08-14 19:54:01 +00:00
|
|
|
UpdateGameList();
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
else if (!m_GameListCtrl->GetISO(0))
|
|
|
|
{
|
|
|
|
m_GameListCtrl->BrowseForDirectory();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Game started by double click
|
|
|
|
BootGame("");
|
|
|
|
}
|
2009-01-07 09:06:42 +00:00
|
|
|
}
|
2009-01-28 16:51:05 +00:00
|
|
|
|
2015-05-26 19:04:16 +00:00
|
|
|
static bool IsHotkey(int id, bool held = false)
|
2010-04-12 01:33:10 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
return HotkeyManagerEmu::IsPressed(id, held);
|
2010-04-12 01:33:10 +00:00
|
|
|
}
|
|
|
|
|
2016-10-18 22:09:24 +00:00
|
|
|
static int GetMenuIDFromHotkey(unsigned int key)
|
2011-02-14 01:18:01 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case HK_OPEN:
|
|
|
|
return wxID_OPEN;
|
|
|
|
case HK_CHANGE_DISC:
|
|
|
|
return IDM_CHANGE_DISC;
|
|
|
|
case HK_REFRESH_LIST:
|
|
|
|
return wxID_REFRESH;
|
|
|
|
case HK_PLAY_PAUSE:
|
|
|
|
return IDM_PLAY;
|
|
|
|
case HK_STOP:
|
|
|
|
return IDM_STOP;
|
|
|
|
case HK_RESET:
|
|
|
|
return IDM_RESET;
|
|
|
|
case HK_FRAME_ADVANCE:
|
|
|
|
return IDM_FRAMESTEP;
|
|
|
|
case HK_START_RECORDING:
|
|
|
|
return IDM_RECORD;
|
|
|
|
case HK_PLAY_RECORDING:
|
|
|
|
return IDM_PLAY_RECORD;
|
|
|
|
case HK_EXPORT_RECORDING:
|
|
|
|
return IDM_RECORD_EXPORT;
|
|
|
|
case HK_READ_ONLY_MODE:
|
|
|
|
return IDM_RECORD_READ_ONLY;
|
|
|
|
case HK_FULLSCREEN:
|
|
|
|
return IDM_TOGGLE_FULLSCREEN;
|
|
|
|
case HK_SCREENSHOT:
|
|
|
|
return IDM_SCREENSHOT;
|
|
|
|
case HK_EXIT:
|
|
|
|
return wxID_EXIT;
|
|
|
|
|
|
|
|
case HK_WIIMOTE1_CONNECT:
|
|
|
|
return IDM_CONNECT_WIIMOTE1;
|
|
|
|
case HK_WIIMOTE2_CONNECT:
|
|
|
|
return IDM_CONNECT_WIIMOTE2;
|
|
|
|
case HK_WIIMOTE3_CONNECT:
|
|
|
|
return IDM_CONNECT_WIIMOTE3;
|
|
|
|
case HK_WIIMOTE4_CONNECT:
|
|
|
|
return IDM_CONNECT_WIIMOTE4;
|
|
|
|
case HK_BALANCEBOARD_CONNECT:
|
|
|
|
return IDM_CONNECT_BALANCEBOARD;
|
|
|
|
|
|
|
|
case HK_LOAD_STATE_SLOT_1:
|
|
|
|
return IDM_LOAD_SLOT_1;
|
|
|
|
case HK_LOAD_STATE_SLOT_2:
|
|
|
|
return IDM_LOAD_SLOT_2;
|
|
|
|
case HK_LOAD_STATE_SLOT_3:
|
|
|
|
return IDM_LOAD_SLOT_3;
|
|
|
|
case HK_LOAD_STATE_SLOT_4:
|
|
|
|
return IDM_LOAD_SLOT_4;
|
|
|
|
case HK_LOAD_STATE_SLOT_5:
|
|
|
|
return IDM_LOAD_SLOT_5;
|
|
|
|
case HK_LOAD_STATE_SLOT_6:
|
|
|
|
return IDM_LOAD_SLOT_6;
|
|
|
|
case HK_LOAD_STATE_SLOT_7:
|
|
|
|
return IDM_LOAD_SLOT_7;
|
|
|
|
case HK_LOAD_STATE_SLOT_8:
|
|
|
|
return IDM_LOAD_SLOT_8;
|
|
|
|
case HK_LOAD_STATE_SLOT_9:
|
|
|
|
return IDM_LOAD_SLOT_9;
|
|
|
|
case HK_LOAD_STATE_SLOT_10:
|
|
|
|
return IDM_LOAD_SLOT_10;
|
|
|
|
|
|
|
|
case HK_SAVE_STATE_SLOT_1:
|
|
|
|
return IDM_SAVE_SLOT_1;
|
|
|
|
case HK_SAVE_STATE_SLOT_2:
|
|
|
|
return IDM_SAVE_SLOT_2;
|
|
|
|
case HK_SAVE_STATE_SLOT_3:
|
|
|
|
return IDM_SAVE_SLOT_3;
|
|
|
|
case HK_SAVE_STATE_SLOT_4:
|
|
|
|
return IDM_SAVE_SLOT_4;
|
|
|
|
case HK_SAVE_STATE_SLOT_5:
|
|
|
|
return IDM_SAVE_SLOT_5;
|
|
|
|
case HK_SAVE_STATE_SLOT_6:
|
|
|
|
return IDM_SAVE_SLOT_6;
|
|
|
|
case HK_SAVE_STATE_SLOT_7:
|
|
|
|
return IDM_SAVE_SLOT_7;
|
|
|
|
case HK_SAVE_STATE_SLOT_8:
|
|
|
|
return IDM_SAVE_SLOT_8;
|
|
|
|
case HK_SAVE_STATE_SLOT_9:
|
|
|
|
return IDM_SAVE_SLOT_9;
|
|
|
|
case HK_SAVE_STATE_SLOT_10:
|
|
|
|
return IDM_SAVE_SLOT_10;
|
|
|
|
|
|
|
|
case HK_LOAD_LAST_STATE_1:
|
|
|
|
return IDM_LOAD_LAST_1;
|
|
|
|
case HK_LOAD_LAST_STATE_2:
|
|
|
|
return IDM_LOAD_LAST_2;
|
|
|
|
case HK_LOAD_LAST_STATE_3:
|
|
|
|
return IDM_LOAD_LAST_3;
|
|
|
|
case HK_LOAD_LAST_STATE_4:
|
|
|
|
return IDM_LOAD_LAST_4;
|
|
|
|
case HK_LOAD_LAST_STATE_5:
|
|
|
|
return IDM_LOAD_LAST_5;
|
|
|
|
case HK_LOAD_LAST_STATE_6:
|
|
|
|
return IDM_LOAD_LAST_6;
|
|
|
|
case HK_LOAD_LAST_STATE_7:
|
|
|
|
return IDM_LOAD_LAST_7;
|
|
|
|
case HK_LOAD_LAST_STATE_8:
|
|
|
|
return IDM_LOAD_LAST_8;
|
|
|
|
case HK_LOAD_LAST_STATE_9:
|
|
|
|
return IDM_LOAD_LAST_9;
|
|
|
|
case HK_LOAD_LAST_STATE_10:
|
|
|
|
return IDM_LOAD_LAST_10;
|
|
|
|
|
|
|
|
case HK_SAVE_FIRST_STATE:
|
|
|
|
return IDM_SAVE_FIRST_STATE;
|
|
|
|
case HK_UNDO_LOAD_STATE:
|
|
|
|
return IDM_UNDO_LOAD_STATE;
|
|
|
|
case HK_UNDO_SAVE_STATE:
|
|
|
|
return IDM_UNDO_SAVE_STATE;
|
|
|
|
case HK_LOAD_STATE_FILE:
|
|
|
|
return IDM_LOAD_STATE_FILE;
|
|
|
|
case HK_SAVE_STATE_FILE:
|
|
|
|
return IDM_SAVE_STATE_FILE;
|
|
|
|
|
|
|
|
case HK_SELECT_STATE_SLOT_1:
|
|
|
|
return IDM_SELECT_SLOT_1;
|
|
|
|
case HK_SELECT_STATE_SLOT_2:
|
|
|
|
return IDM_SELECT_SLOT_2;
|
|
|
|
case HK_SELECT_STATE_SLOT_3:
|
|
|
|
return IDM_SELECT_SLOT_3;
|
|
|
|
case HK_SELECT_STATE_SLOT_4:
|
|
|
|
return IDM_SELECT_SLOT_4;
|
|
|
|
case HK_SELECT_STATE_SLOT_5:
|
|
|
|
return IDM_SELECT_SLOT_5;
|
|
|
|
case HK_SELECT_STATE_SLOT_6:
|
|
|
|
return IDM_SELECT_SLOT_6;
|
|
|
|
case HK_SELECT_STATE_SLOT_7:
|
|
|
|
return IDM_SELECT_SLOT_7;
|
|
|
|
case HK_SELECT_STATE_SLOT_8:
|
|
|
|
return IDM_SELECT_SLOT_8;
|
|
|
|
case HK_SELECT_STATE_SLOT_9:
|
|
|
|
return IDM_SELECT_SLOT_9;
|
|
|
|
case HK_SELECT_STATE_SLOT_10:
|
|
|
|
return IDM_SELECT_SLOT_10;
|
|
|
|
case HK_SAVE_STATE_SLOT_SELECTED:
|
|
|
|
return IDM_SAVE_SELECTED_SLOT;
|
|
|
|
case HK_LOAD_STATE_SLOT_SELECTED:
|
|
|
|
return IDM_LOAD_SELECTED_SLOT;
|
|
|
|
|
|
|
|
case HK_FREELOOK_DECREASE_SPEED:
|
|
|
|
return IDM_FREELOOK_DECREASE_SPEED;
|
|
|
|
case HK_FREELOOK_INCREASE_SPEED:
|
|
|
|
return IDM_FREELOOK_INCREASE_SPEED;
|
|
|
|
case HK_FREELOOK_RESET_SPEED:
|
|
|
|
return IDM_FREELOOK_RESET_SPEED;
|
|
|
|
case HK_FREELOOK_LEFT:
|
|
|
|
return IDM_FREELOOK_LEFT;
|
|
|
|
case HK_FREELOOK_RIGHT:
|
|
|
|
return IDM_FREELOOK_RIGHT;
|
|
|
|
case HK_FREELOOK_UP:
|
|
|
|
return IDM_FREELOOK_UP;
|
|
|
|
case HK_FREELOOK_DOWN:
|
|
|
|
return IDM_FREELOOK_DOWN;
|
|
|
|
case HK_FREELOOK_ZOOM_IN:
|
|
|
|
return IDM_FREELOOK_ZOOM_IN;
|
|
|
|
case HK_FREELOOK_ZOOM_OUT:
|
|
|
|
return IDM_FREELOOK_ZOOM_OUT;
|
|
|
|
case HK_FREELOOK_RESET:
|
|
|
|
return IDM_FREELOOK_RESET;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2011-02-14 01:18:01 +00:00
|
|
|
}
|
|
|
|
|
2011-12-18 09:15:59 +00:00
|
|
|
void OnAfterLoadCallback()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// warning: this gets called from the CPU thread, so we should only queue things to do on the
|
|
|
|
// proper thread
|
|
|
|
if (main_frame)
|
|
|
|
{
|
|
|
|
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATE_GUI);
|
|
|
|
main_frame->GetEventHandler()->AddPendingEvent(event);
|
|
|
|
}
|
2011-12-18 09:15:59 +00:00
|
|
|
}
|
|
|
|
|
2014-06-20 00:43:57 +00:00
|
|
|
void OnStoppedCallback()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// warning: this gets called from the EmuThread, so we should only queue things to do on the
|
|
|
|
// proper thread
|
|
|
|
if (main_frame)
|
|
|
|
{
|
|
|
|
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_STOPPED);
|
|
|
|
main_frame->GetEventHandler()->AddPendingEvent(event);
|
|
|
|
}
|
2014-06-20 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
2014-09-15 03:42:32 +00:00
|
|
|
void GCTASManipFunction(GCPadStatus* PadStatus, int controllerID)
|
2011-06-24 06:50:50 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (main_frame)
|
|
|
|
main_frame->g_TASInputDlg[controllerID]->GetValues(PadStatus);
|
2014-09-15 03:42:32 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
void WiiTASManipFunction(u8* data, WiimoteEmu::ReportFeatures rptf, int controllerID, int ext,
|
|
|
|
const wiimote_key key)
|
2014-09-15 03:42:32 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (main_frame)
|
|
|
|
{
|
|
|
|
main_frame->g_TASInputDlg[controllerID + 4]->GetValues(data, rptf, ext, key);
|
|
|
|
}
|
2011-06-24 06:50:50 +00:00
|
|
|
}
|
|
|
|
|
2015-07-20 08:04:18 +00:00
|
|
|
void CFrame::OnKeyDown(wxKeyEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// On OS X, we claim all keyboard events while
|
|
|
|
// emulation is running to avoid wxWidgets sounding
|
|
|
|
// the system beep for unhandled key events when
|
|
|
|
// receiving pad/Wiimote keypresses which take an
|
|
|
|
// entirely different path through the HID subsystem.
|
2015-07-20 08:04:18 +00:00
|
|
|
#ifndef __APPLE__
|
2016-06-24 08:43:46 +00:00
|
|
|
// On other platforms, we leave the key event alone
|
|
|
|
// so it can be passed on to the windowing system.
|
|
|
|
event.Skip();
|
2015-07-20 08:04:18 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-12-21 23:58:25 +00:00
|
|
|
void CFrame::OnMouse(wxMouseEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// next handlers are all for FreeLook, so we don't need to check them if disabled
|
|
|
|
if (!g_Config.bFreeLook)
|
|
|
|
{
|
|
|
|
event.Skip();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free look variables
|
|
|
|
static bool mouseLookEnabled = false;
|
|
|
|
static bool mouseMoveEnabled = false;
|
|
|
|
static float lastMouse[2];
|
|
|
|
|
|
|
|
if (event.MiddleDown())
|
|
|
|
{
|
|
|
|
lastMouse[0] = event.GetX();
|
|
|
|
lastMouse[1] = event.GetY();
|
|
|
|
mouseMoveEnabled = true;
|
|
|
|
}
|
|
|
|
else if (event.RightDown())
|
|
|
|
{
|
|
|
|
lastMouse[0] = event.GetX();
|
|
|
|
lastMouse[1] = event.GetY();
|
|
|
|
mouseLookEnabled = true;
|
|
|
|
}
|
|
|
|
else if (event.MiddleUp())
|
|
|
|
{
|
|
|
|
mouseMoveEnabled = false;
|
|
|
|
}
|
|
|
|
else if (event.RightUp())
|
|
|
|
{
|
|
|
|
mouseLookEnabled = false;
|
|
|
|
}
|
|
|
|
// no button, so it's a move event
|
|
|
|
else if (event.GetButton() == wxMOUSE_BTN_NONE)
|
|
|
|
{
|
|
|
|
if (mouseLookEnabled)
|
|
|
|
{
|
|
|
|
VertexShaderManager::RotateView((event.GetX() - lastMouse[0]) / 200.0f,
|
|
|
|
(event.GetY() - lastMouse[1]) / 200.0f);
|
|
|
|
lastMouse[0] = event.GetX();
|
|
|
|
lastMouse[1] = event.GetY();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mouseMoveEnabled)
|
|
|
|
{
|
|
|
|
VertexShaderManager::TranslateView((event.GetX() - lastMouse[0]) / 50.0f,
|
|
|
|
(event.GetY() - lastMouse[1]) / 50.0f);
|
|
|
|
lastMouse[0] = event.GetX();
|
|
|
|
lastMouse[1] = event.GetY();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
event.Skip();
|
2010-12-21 23:58:25 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 04:31:13 +00:00
|
|
|
void CFrame::OnFocusChange(wxFocusEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (SConfig::GetInstance().m_PauseOnFocusLost && Core::IsRunningAndStarted())
|
|
|
|
{
|
|
|
|
if (RendererHasFocus())
|
|
|
|
{
|
|
|
|
if (Core::GetState() == Core::CORE_PAUSE)
|
|
|
|
{
|
|
|
|
Core::SetState(Core::CORE_RUN);
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
m_RenderParent->SetCursor(wxCURSOR_BLANK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Core::GetState() == Core::CORE_RUN)
|
|
|
|
{
|
|
|
|
Core::SetState(Core::CORE_PAUSE);
|
|
|
|
if (SConfig::GetInstance().bHideCursor)
|
|
|
|
m_RenderParent->SetCursor(wxNullCursor);
|
|
|
|
Core::UpdateTitle();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UpdateGUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
event.Skip();
|
2015-03-17 04:31:13 +00:00
|
|
|
}
|
|
|
|
|
2014-07-26 10:43:49 +00:00
|
|
|
void CFrame::DoFullscreen(bool enable_fullscreen)
|
2009-09-01 15:16:44 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (g_Config.bExclusiveMode && Core::GetState() == Core::CORE_PAUSE)
|
|
|
|
{
|
|
|
|
// A responsive renderer is required for exclusive fullscreen, but the
|
|
|
|
// renderer can only respond in the running state. Therefore we ignore
|
|
|
|
// fullscreen switches if we are in exclusive fullscreen, but the
|
|
|
|
// renderer is not running.
|
|
|
|
// TODO: Allow the renderer to switch fullscreen modes while paused.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ToggleDisplayMode(enable_fullscreen);
|
2010-04-22 04:28:34 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (enable_fullscreen)
|
|
|
|
{
|
|
|
|
m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL);
|
|
|
|
}
|
|
|
|
else if (!g_Config.bExclusiveMode)
|
|
|
|
{
|
|
|
|
// Exiting exclusive fullscreen should be done from a Renderer callback.
|
|
|
|
// Therefore we don't exit fullscreen from here if we are in exclusive mode.
|
|
|
|
m_RenderFrame->ShowFullScreen(false, wxFULLSCREEN_ALL);
|
|
|
|
}
|
2013-03-31 16:08:29 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (SConfig::GetInstance().bRenderToMain)
|
|
|
|
{
|
|
|
|
if (enable_fullscreen)
|
|
|
|
{
|
|
|
|
// Save the current mode before going to fullscreen
|
|
|
|
AuiCurrent = m_Mgr->SavePerspective();
|
|
|
|
m_Mgr->LoadPerspective(AuiFullscreen, true);
|
|
|
|
|
|
|
|
// Hide toolbar
|
|
|
|
DoToggleToolbar(false);
|
|
|
|
|
|
|
|
// Hide menubar (by having wxwidgets delete it)
|
|
|
|
SetMenuBar(nullptr);
|
|
|
|
|
|
|
|
// Hide the statusbar if enabled
|
|
|
|
if (GetStatusBar()->IsShown())
|
|
|
|
{
|
|
|
|
GetStatusBar()->Hide();
|
|
|
|
this->SendSizeEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Restore saved perspective
|
|
|
|
m_Mgr->LoadPerspective(AuiCurrent, true);
|
|
|
|
|
|
|
|
// Restore toolbar to the status it was at before going fullscreen.
|
|
|
|
DoToggleToolbar(SConfig::GetInstance().m_InterfaceToolbar);
|
|
|
|
|
|
|
|
// Recreate the menubar if needed.
|
|
|
|
if (wxFrame::GetMenuBar() == nullptr)
|
|
|
|
{
|
2016-10-10 20:41:58 +00:00
|
|
|
SetMenuBar(CreateMenuBar());
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Show statusbar if enabled
|
|
|
|
if (SConfig::GetInstance().m_InterfaceStatusbar)
|
|
|
|
{
|
|
|
|
GetStatusBar()->Show();
|
|
|
|
this->SendSizeEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_RenderFrame->Raise();
|
|
|
|
}
|
|
|
|
|
|
|
|
g_Config.bFullscreen = enable_fullscreen;
|
2009-09-05 04:50:45 +00:00
|
|
|
}
|
2011-02-13 22:36:12 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
const CGameListCtrl* CFrame::GetGameListCtrl() const
|
2011-02-13 22:36:12 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
return m_GameListCtrl;
|
2011-02-13 22:36:12 +00:00
|
|
|
}
|
2015-01-27 01:24:47 +00:00
|
|
|
|
|
|
|
void CFrame::PollHotkeys(wxTimerEvent& event)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
if (!HotkeyManagerEmu::IsEnabled())
|
|
|
|
return;
|
2015-02-28 20:43:34 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (Core::GetState() == Core::CORE_UNINITIALIZED || Core::GetState() == Core::CORE_PAUSE)
|
|
|
|
g_controller_interface.UpdateInput();
|
2015-01-27 01:24:47 +00:00
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (Core::GetState() != Core::CORE_STOPPING)
|
|
|
|
{
|
|
|
|
HotkeyManagerEmu::GetStatus();
|
|
|
|
ParseHotkeys();
|
|
|
|
}
|
2015-01-27 01:24:47 +00:00
|
|
|
}
|
|
|
|
|
2015-05-26 19:04:16 +00:00
|
|
|
void CFrame::ParseHotkeys()
|
2015-01-27 01:24:47 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
for (int i = 0; i < NUM_HOTKEYS; i++)
|
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case HK_OPEN:
|
|
|
|
case HK_CHANGE_DISC:
|
|
|
|
case HK_REFRESH_LIST:
|
|
|
|
case HK_RESET:
|
|
|
|
case HK_START_RECORDING:
|
|
|
|
case HK_PLAY_RECORDING:
|
|
|
|
case HK_EXPORT_RECORDING:
|
|
|
|
case HK_READ_ONLY_MODE:
|
|
|
|
|
|
|
|
case HK_LOAD_STATE_FILE:
|
|
|
|
case HK_SAVE_STATE_FILE:
|
|
|
|
case HK_LOAD_STATE_SLOT_SELECTED:
|
|
|
|
|
|
|
|
if (IsHotkey(i))
|
|
|
|
{
|
2016-10-18 22:09:24 +00:00
|
|
|
const int id = GetMenuIDFromHotkey(i);
|
|
|
|
if (id >= 0)
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
2016-10-18 22:09:24 +00:00
|
|
|
wxCommandEvent evt(wxEVT_MENU, id);
|
|
|
|
wxMenuItem* item = GetMenuBar()->FindItem(id);
|
2016-06-24 08:43:46 +00:00
|
|
|
if (item && item->IsCheckable())
|
|
|
|
{
|
|
|
|
item->wxMenuItemBase::Toggle();
|
|
|
|
evt.SetInt(item->IsChecked());
|
|
|
|
}
|
|
|
|
GetEventHandler()->AddPendingEvent(evt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Core::IsRunningAndStarted())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Toggle fullscreen
|
|
|
|
if (IsHotkey(HK_FULLSCREEN))
|
|
|
|
DoFullscreen(!RendererIsFullscreen());
|
|
|
|
// Pause and Unpause
|
|
|
|
if (IsHotkey(HK_PLAY_PAUSE))
|
|
|
|
DoPause();
|
|
|
|
// Frame advance
|
|
|
|
HandleFrameSkipHotkeys();
|
|
|
|
// Stop
|
|
|
|
if (IsHotkey(HK_STOP))
|
|
|
|
DoStop();
|
|
|
|
// Screenshot hotkey
|
|
|
|
if (IsHotkey(HK_SCREENSHOT))
|
|
|
|
Core::SaveScreenShot();
|
|
|
|
if (IsHotkey(HK_EXIT))
|
|
|
|
wxPostEvent(this, wxCommandEvent(wxEVT_MENU, wxID_EXIT));
|
|
|
|
if (IsHotkey(HK_VOLUME_DOWN))
|
|
|
|
AudioCommon::DecreaseVolume(3);
|
|
|
|
if (IsHotkey(HK_VOLUME_UP))
|
|
|
|
AudioCommon::IncreaseVolume(3);
|
|
|
|
if (IsHotkey(HK_VOLUME_TOGGLE_MUTE))
|
|
|
|
AudioCommon::ToggleMuteVolume();
|
|
|
|
|
2016-08-23 14:19:30 +00:00
|
|
|
if (SConfig::GetInstance().m_bt_passthrough_enabled)
|
|
|
|
{
|
|
|
|
auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305");
|
|
|
|
if (device != nullptr)
|
|
|
|
std::static_pointer_cast<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(device)
|
|
|
|
->UpdateSyncButtonState(IsHotkey(HK_TRIGGER_SYNC_BUTTON, true));
|
|
|
|
}
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
// Wiimote connect and disconnect hotkeys
|
|
|
|
int WiimoteId = -1;
|
|
|
|
if (IsHotkey(HK_WIIMOTE1_CONNECT))
|
|
|
|
WiimoteId = 0;
|
|
|
|
if (IsHotkey(HK_WIIMOTE2_CONNECT))
|
|
|
|
WiimoteId = 1;
|
|
|
|
if (IsHotkey(HK_WIIMOTE3_CONNECT))
|
|
|
|
WiimoteId = 2;
|
|
|
|
if (IsHotkey(HK_WIIMOTE4_CONNECT))
|
|
|
|
WiimoteId = 3;
|
|
|
|
if (IsHotkey(HK_BALANCEBOARD_CONNECT))
|
|
|
|
WiimoteId = 4;
|
|
|
|
|
|
|
|
// Actually perform the Wiimote connection or disconnection
|
|
|
|
if (WiimoteId >= 0 && SConfig::GetInstance().bWii)
|
|
|
|
{
|
|
|
|
wxCommandEvent evt;
|
|
|
|
evt.SetId(IDM_CONNECT_WIIMOTE1 + WiimoteId);
|
|
|
|
OnConnectWiimote(evt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsHotkey(HK_INCREASE_IR))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 1;
|
2016-06-24 08:43:46 +00:00
|
|
|
++g_Config.iEFBScale;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_DECREASE_IR))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 1;
|
2016-06-24 08:43:46 +00:00
|
|
|
if (--g_Config.iEFBScale < SCALE_AUTO)
|
|
|
|
g_Config.iEFBScale = SCALE_AUTO;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_CROP))
|
|
|
|
{
|
|
|
|
g_Config.bCrop = !g_Config.bCrop;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_AR))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 2;
|
2016-06-24 08:43:46 +00:00
|
|
|
// Toggle aspect ratio
|
|
|
|
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_EFBCOPIES))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 3;
|
2016-06-24 08:43:46 +00:00
|
|
|
// Toggle EFB copies between EFB2RAM and EFB2Texture
|
|
|
|
g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_FOG))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 4;
|
2016-06-24 08:43:46 +00:00
|
|
|
g_Config.bDisableFog = !g_Config.bDisableFog;
|
|
|
|
}
|
2016-08-20 04:14:56 +00:00
|
|
|
if (IsHotkey(HK_TOGGLE_TEXTURES))
|
|
|
|
g_Config.bHiresTextures = !g_Config.bHiresTextures;
|
2016-06-24 08:43:46 +00:00
|
|
|
Core::SetIsThrottlerTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true));
|
|
|
|
if (IsHotkey(HK_DECREASE_EMULATION_SPEED))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 5;
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (SConfig::GetInstance().m_EmulationSpeed <= 0.0f)
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
|
|
|
|
else if (SConfig::GetInstance().m_EmulationSpeed >= 0.2f)
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed -= 0.1f;
|
|
|
|
else
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed = 0.1f;
|
|
|
|
|
|
|
|
if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f &&
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed <= 1.05f)
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_INCREASE_EMULATION_SPEED))
|
|
|
|
{
|
2016-10-15 10:36:11 +00:00
|
|
|
OSDChoice = 5;
|
|
|
|
|
2016-06-24 08:43:46 +00:00
|
|
|
if (SConfig::GetInstance().m_EmulationSpeed > 0.0f)
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed += 0.1f;
|
|
|
|
|
|
|
|
if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f &&
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed <= 1.05f)
|
|
|
|
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED))
|
|
|
|
{
|
2016-08-04 17:41:28 +00:00
|
|
|
State::Save(m_saveSlot);
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
if (IsHotkey(HK_LOAD_STATE_SLOT_SELECTED))
|
|
|
|
{
|
2016-08-04 17:41:28 +00:00
|
|
|
State::Load(m_saveSlot);
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IsHotkey(HK_TOGGLE_STEREO_SBS))
|
|
|
|
{
|
|
|
|
if (g_Config.iStereoMode != STEREO_SBS)
|
|
|
|
{
|
|
|
|
// Current implementation of anaglyph stereoscopy uses a
|
|
|
|
// post-processing shader. Thus the shader needs to be to be
|
|
|
|
// turned off when selecting other stereoscopy modes.
|
|
|
|
if (g_Config.sPostProcessingShader == "dubois")
|
|
|
|
{
|
|
|
|
g_Config.sPostProcessingShader = "";
|
|
|
|
}
|
|
|
|
g_Config.iStereoMode = STEREO_SBS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Config.iStereoMode = STEREO_OFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_STEREO_TAB))
|
|
|
|
{
|
|
|
|
if (g_Config.iStereoMode != STEREO_TAB)
|
|
|
|
{
|
|
|
|
if (g_Config.sPostProcessingShader == "dubois")
|
|
|
|
{
|
|
|
|
g_Config.sPostProcessingShader = "";
|
|
|
|
}
|
|
|
|
g_Config.iStereoMode = STEREO_TAB;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Config.iStereoMode = STEREO_OFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_STEREO_ANAGLYPH))
|
|
|
|
{
|
|
|
|
if (g_Config.iStereoMode != STEREO_ANAGLYPH)
|
|
|
|
{
|
|
|
|
// Setting the anaglyph mode also requires a specific
|
|
|
|
// post-processing shader to be activated.
|
|
|
|
g_Config.iStereoMode = STEREO_ANAGLYPH;
|
|
|
|
g_Config.sPostProcessingShader = "dubois";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Config.iStereoMode = STEREO_OFF;
|
|
|
|
g_Config.sPostProcessingShader = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_TOGGLE_STEREO_3DVISION))
|
|
|
|
{
|
|
|
|
if (g_Config.iStereoMode != STEREO_3DVISION)
|
|
|
|
{
|
|
|
|
if (g_Config.sPostProcessingShader == "dubois")
|
|
|
|
{
|
|
|
|
g_Config.sPostProcessingShader = "";
|
|
|
|
}
|
|
|
|
g_Config.iStereoMode = STEREO_3DVISION;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Config.iStereoMode = STEREO_OFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsHotkey(HK_DECREASE_DEPTH, true))
|
|
|
|
{
|
|
|
|
if (--g_Config.iStereoDepth < 0)
|
|
|
|
g_Config.iStereoDepth = 0;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_INCREASE_DEPTH, true))
|
|
|
|
{
|
|
|
|
if (++g_Config.iStereoDepth > 100)
|
|
|
|
g_Config.iStereoDepth = 100;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_DECREASE_CONVERGENCE, true))
|
|
|
|
{
|
|
|
|
g_Config.iStereoConvergence -= 5;
|
|
|
|
if (g_Config.iStereoConvergence < 0)
|
|
|
|
g_Config.iStereoConvergence = 0;
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_INCREASE_CONVERGENCE, true))
|
|
|
|
{
|
|
|
|
g_Config.iStereoConvergence += 5;
|
|
|
|
if (g_Config.iStereoConvergence > 500)
|
|
|
|
g_Config.iStereoConvergence = 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
static float debugSpeed = 1.0f;
|
|
|
|
if (IsHotkey(HK_FREELOOK_DECREASE_SPEED, true))
|
|
|
|
debugSpeed /= 1.1f;
|
|
|
|
if (IsHotkey(HK_FREELOOK_INCREASE_SPEED, true))
|
|
|
|
debugSpeed *= 1.1f;
|
|
|
|
if (IsHotkey(HK_FREELOOK_RESET_SPEED, true))
|
|
|
|
debugSpeed = 1.0f;
|
|
|
|
if (IsHotkey(HK_FREELOOK_UP, true))
|
|
|
|
VertexShaderManager::TranslateView(0.0f, 0.0f, -debugSpeed);
|
|
|
|
if (IsHotkey(HK_FREELOOK_DOWN, true))
|
|
|
|
VertexShaderManager::TranslateView(0.0f, 0.0f, debugSpeed);
|
|
|
|
if (IsHotkey(HK_FREELOOK_LEFT, true))
|
|
|
|
VertexShaderManager::TranslateView(debugSpeed, 0.0f);
|
|
|
|
if (IsHotkey(HK_FREELOOK_RIGHT, true))
|
|
|
|
VertexShaderManager::TranslateView(-debugSpeed, 0.0f);
|
|
|
|
if (IsHotkey(HK_FREELOOK_ZOOM_IN, true))
|
|
|
|
VertexShaderManager::TranslateView(0.0f, debugSpeed);
|
|
|
|
if (IsHotkey(HK_FREELOOK_ZOOM_OUT, true))
|
|
|
|
VertexShaderManager::TranslateView(0.0f, -debugSpeed);
|
|
|
|
if (IsHotkey(HK_FREELOOK_RESET, true))
|
|
|
|
VertexShaderManager::ResetView();
|
|
|
|
|
|
|
|
// Savestates
|
|
|
|
for (u32 i = 0; i < State::NUM_STATES; i++)
|
|
|
|
{
|
|
|
|
if (IsHotkey(HK_LOAD_STATE_SLOT_1 + i))
|
|
|
|
State::Load(1 + i);
|
|
|
|
|
|
|
|
if (IsHotkey(HK_SAVE_STATE_SLOT_1 + i))
|
|
|
|
State::Save(1 + i);
|
|
|
|
|
|
|
|
if (IsHotkey(HK_LOAD_LAST_STATE_1 + i))
|
|
|
|
State::LoadLastSaved(1 + i);
|
|
|
|
|
|
|
|
if (IsHotkey(HK_SELECT_STATE_SLOT_1 + i))
|
|
|
|
{
|
|
|
|
wxCommandEvent slot_event;
|
|
|
|
slot_event.SetId(IDM_SELECT_SLOT_1 + i);
|
|
|
|
CFrame::OnSelectSlot(slot_event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsHotkey(HK_SAVE_FIRST_STATE))
|
|
|
|
State::SaveFirstSaved();
|
|
|
|
if (IsHotkey(HK_UNDO_LOAD_STATE))
|
|
|
|
State::UndoLoadState();
|
|
|
|
if (IsHotkey(HK_UNDO_SAVE_STATE))
|
|
|
|
State::UndoSaveState();
|
2015-01-27 01:24:47 +00:00
|
|
|
}
|
2015-07-05 16:20:42 +00:00
|
|
|
|
|
|
|
void CFrame::HandleFrameSkipHotkeys()
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
static const int MAX_FRAME_SKIP_DELAY = 60;
|
|
|
|
static int frameStepCount = 0;
|
|
|
|
static const int FRAME_STEP_DELAY = 30;
|
|
|
|
static int holdFrameStepDelay = 1;
|
|
|
|
static int holdFrameStepDelayCount = 0;
|
|
|
|
static bool holdFrameStep = false;
|
|
|
|
|
|
|
|
if (IsHotkey(HK_FRAME_ADVANCE_DECREASE_SPEED))
|
|
|
|
{
|
|
|
|
++holdFrameStepDelay;
|
|
|
|
if (holdFrameStepDelay > MAX_FRAME_SKIP_DELAY)
|
|
|
|
holdFrameStepDelay = MAX_FRAME_SKIP_DELAY;
|
|
|
|
}
|
|
|
|
else if (IsHotkey(HK_FRAME_ADVANCE_INCREASE_SPEED))
|
|
|
|
{
|
|
|
|
--holdFrameStepDelay;
|
|
|
|
if (holdFrameStepDelay < 0)
|
|
|
|
holdFrameStepDelay = 0;
|
|
|
|
}
|
|
|
|
else if (IsHotkey(HK_FRAME_ADVANCE_RESET_SPEED))
|
|
|
|
{
|
|
|
|
holdFrameStepDelay = 1;
|
|
|
|
}
|
|
|
|
else if (IsHotkey(HK_FRAME_ADVANCE, true))
|
|
|
|
{
|
|
|
|
if (holdFrameStepDelayCount < holdFrameStepDelay && holdFrameStep)
|
|
|
|
++holdFrameStepDelayCount;
|
|
|
|
|
|
|
|
if ((frameStepCount == 0 || frameStepCount == FRAME_STEP_DELAY) && !holdFrameStep)
|
|
|
|
{
|
|
|
|
wxCommandEvent evt;
|
|
|
|
evt.SetId(IDM_FRAMESTEP);
|
|
|
|
CFrame::OnFrameStep(evt);
|
|
|
|
if (holdFrameStepDelay > 0)
|
|
|
|
holdFrameStep = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frameStepCount < FRAME_STEP_DELAY)
|
|
|
|
{
|
|
|
|
++frameStepCount;
|
|
|
|
if (holdFrameStep)
|
|
|
|
holdFrameStep = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frameStepCount == FRAME_STEP_DELAY && holdFrameStep &&
|
|
|
|
holdFrameStepDelayCount >= holdFrameStepDelay)
|
|
|
|
{
|
|
|
|
holdFrameStep = false;
|
|
|
|
holdFrameStepDelayCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (frameStepCount > 0)
|
|
|
|
{
|
|
|
|
// Reset values of frame advance to default
|
|
|
|
frameStepCount = 0;
|
|
|
|
holdFrameStep = false;
|
|
|
|
holdFrameStepDelayCount = 0;
|
|
|
|
}
|
2015-07-05 16:20:42 +00:00
|
|
|
}
|
2016-07-08 14:35:03 +00:00
|
|
|
|
|
|
|
void CFrame::HandleSignal(wxTimerEvent& event)
|
|
|
|
{
|
|
|
|
if (!s_shutdown_signal_received.TestAndClear())
|
|
|
|
return;
|
2016-10-04 20:54:55 +00:00
|
|
|
m_bClosing = true;
|
2016-07-08 14:35:03 +00:00
|
|
|
Close();
|
|
|
|
}
|