Frame.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. // Copyright 2008 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #ifdef __APPLE__
  5. #include <Cocoa/Cocoa.h>
  6. #endif
  7. #include <cstddef>
  8. #include <fstream>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include <wx/filename.h>
  13. #include <wx/frame.h>
  14. #include <wx/icon.h>
  15. #include <wx/listbase.h>
  16. #include <wx/menu.h>
  17. #include <wx/msgdlg.h>
  18. #include <wx/panel.h>
  19. #include <wx/sizer.h>
  20. #include <wx/statusbr.h>
  21. #include <wx/textctrl.h>
  22. #include <wx/thread.h>
  23. #include <wx/aui/auibook.h>
  24. #include <wx/aui/framemanager.h>
  25. #include "AudioCommon/AudioCommon.h"
  26. #include "Common/CommonTypes.h"
  27. #include "Common/FileUtil.h"
  28. #include "Common/Thread.h"
  29. #include "Common/Logging/ConsoleListener.h"
  30. #include "Core/ConfigManager.h"
  31. #include "Core/Core.h"
  32. #include "Core/CoreParameter.h"
  33. #include "Core/HotkeyManager.h"
  34. #include "Core/Movie.h"
  35. #include "Core/State.h"
  36. #include "Core/HW/DVDInterface.h"
  37. #include "Core/HW/GCKeyboard.h"
  38. #include "Core/HW/GCPad.h"
  39. #include "Core/HW/Wiimote.h"
  40. #include "DolphinWX/Frame.h"
  41. #include "DolphinWX/GameListCtrl.h"
  42. #include "DolphinWX/Globals.h"
  43. #include "DolphinWX/LogWindow.h"
  44. #include "DolphinWX/Main.h"
  45. #include "DolphinWX/TASInputDlg.h"
  46. #include "DolphinWX/WxUtils.h"
  47. #include "DolphinWX/Debugger/CodeWindow.h"
  48. #include "InputCommon/GCPadStatus.h"
  49. #include "VideoCommon/OnScreenDisplay.h"
  50. #include "VideoCommon/RenderBase.h"
  51. #include "VideoCommon/VertexShaderManager.h"
  52. #include "VideoCommon/VideoConfig.h"
  53. // Resources
  54. extern "C" {
  55. #include "DolphinWX/resources/Dolphin.c" // NOLINT: Dolphin icon
  56. };
  57. int g_saveSlot = 1;
  58. #if defined(HAVE_X11) && HAVE_X11
  59. // X11Utils nastiness that's only used here
  60. namespace X11Utils {
  61. Window XWindowFromHandle(void *Handle)
  62. {
  63. return GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(Handle)));
  64. }
  65. Display *XDisplayFromHandle(void *Handle)
  66. {
  67. return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(GTK_WIDGET(Handle)));
  68. }
  69. }
  70. #endif
  71. CRenderFrame::CRenderFrame(wxFrame* parent, wxWindowID id, const wxString& title,
  72. const wxPoint& pos, const wxSize& size, long style)
  73. : wxFrame(parent, id, title, pos, size, style)
  74. {
  75. // Give it an icon
  76. wxIcon IconTemp;
  77. IconTemp.CopyFromBitmap(wxGetBitmapFromMemory(Dolphin_png));
  78. SetIcon(IconTemp);
  79. DragAcceptFiles(true);
  80. Bind(wxEVT_DROP_FILES, &CRenderFrame::OnDropFiles, this);
  81. }
  82. void CRenderFrame::OnDropFiles(wxDropFilesEvent& event)
  83. {
  84. if (event.GetNumberOfFiles() != 1)
  85. return;
  86. if (File::IsDirectory(WxStrToStr(event.GetFiles()[0])))
  87. return;
  88. wxFileName file = event.GetFiles()[0];
  89. const std::string filepath = WxStrToStr(file.GetFullPath());
  90. if (file.GetExt() == "dtm")
  91. {
  92. if (Core::IsRunning())
  93. return;
  94. if (!Movie::IsReadOnly())
  95. {
  96. // let's make the read-only flag consistent at the start of a movie.
  97. Movie::SetReadOnly(true);
  98. main_frame->GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Check(true);
  99. }
  100. if (Movie::PlayInput(filepath))
  101. main_frame->BootGame("");
  102. }
  103. else if (!Core::IsRunning())
  104. {
  105. main_frame->BootGame(filepath);
  106. }
  107. else if (IsValidSavestateDropped(filepath) && Core::IsRunning())
  108. {
  109. State::LoadAs(filepath);
  110. }
  111. else
  112. {
  113. DVDInterface::ChangeDisc(filepath);
  114. }
  115. }
  116. bool CRenderFrame::IsValidSavestateDropped(const std::string& filepath)
  117. {
  118. const int game_id_length = 6;
  119. std::ifstream file(filepath, std::ios::in | std::ios::binary);
  120. if (!file)
  121. return false;
  122. std::string internal_game_id(game_id_length, ' ');
  123. file.read(&internal_game_id[0], game_id_length);
  124. return internal_game_id == SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID();
  125. }
  126. #ifdef _WIN32
  127. WXLRESULT CRenderFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
  128. {
  129. switch (nMsg)
  130. {
  131. case WM_SYSCOMMAND:
  132. switch (wParam)
  133. {
  134. case SC_SCREENSAVE:
  135. case SC_MONITORPOWER:
  136. if (Core::GetState() == Core::CORE_RUN && SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver)
  137. break;
  138. default:
  139. return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
  140. }
  141. break;
  142. case WM_USER:
  143. switch (wParam)
  144. {
  145. case WM_USER_STOP:
  146. main_frame->DoStop();
  147. break;
  148. case WM_USER_SETCURSOR:
  149. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor &&
  150. main_frame->RendererHasFocus() && Core::GetState() == Core::CORE_RUN)
  151. SetCursor(wxCURSOR_BLANK);
  152. else
  153. SetCursor(wxNullCursor);
  154. break;
  155. }
  156. break;
  157. case WM_CLOSE:
  158. // Let Core finish initializing before accepting any WM_CLOSE messages
  159. if (!Core::IsRunning()) break;
  160. // Use default action otherwise
  161. default:
  162. // By default let wxWidgets do what it normally does with this event
  163. return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
  164. }
  165. return 0;
  166. }
  167. #endif
  168. bool CRenderFrame::ShowFullScreen(bool show, long style)
  169. {
  170. #if defined WIN32
  171. if (show && !g_Config.bBorderlessFullscreen)
  172. {
  173. // OpenGL requires the pop-up style to activate exclusive mode.
  174. SetWindowStyle((GetWindowStyle() & ~wxDEFAULT_FRAME_STYLE) | wxPOPUP_WINDOW);
  175. // Some backends don't support exclusive fullscreen, so we
  176. // can't tell exactly when exclusive mode is activated.
  177. if (!g_Config.backend_info.bSupportsExclusiveFullscreen)
  178. OSD::AddMessage("Enabled exclusive fullscreen.");
  179. }
  180. #endif
  181. bool result = wxTopLevelWindow::ShowFullScreen(show, style);
  182. #if defined WIN32
  183. if (!show)
  184. {
  185. // Restore the default style.
  186. SetWindowStyle((GetWindowStyle() & ~wxPOPUP_WINDOW) | wxDEFAULT_FRAME_STYLE);
  187. }
  188. #endif
  189. return result;
  190. }
  191. // event tables
  192. // Notice that wxID_HELP will be processed for the 'About' menu and the toolbar
  193. // help button.
  194. wxDEFINE_EVENT(wxEVT_HOST_COMMAND, wxCommandEvent);
  195. BEGIN_EVENT_TABLE(CFrame, CRenderFrame)
  196. // Menu bar
  197. EVT_MENU(wxID_OPEN, CFrame::OnOpen)
  198. EVT_MENU(wxID_EXIT, CFrame::OnQuit)
  199. EVT_MENU(IDM_HELP_WEBSITE, CFrame::OnHelp)
  200. EVT_MENU(IDM_HELP_ONLINE_DOCS, CFrame::OnHelp)
  201. EVT_MENU(IDM_HELP_GITHUB, CFrame::OnHelp)
  202. EVT_MENU(wxID_ABOUT, CFrame::OnHelp)
  203. EVT_MENU(wxID_REFRESH, CFrame::OnRefresh)
  204. EVT_MENU(IDM_PLAY, CFrame::OnPlay)
  205. EVT_MENU(IDM_STOP, CFrame::OnStop)
  206. EVT_MENU(IDM_RESET, CFrame::OnReset)
  207. EVT_MENU(IDM_RECORD, CFrame::OnRecord)
  208. EVT_MENU(IDM_PLAY_RECORD, CFrame::OnPlayRecording)
  209. EVT_MENU(IDM_RECORD_EXPORT, CFrame::OnRecordExport)
  210. EVT_MENU(IDM_RECORD_READ_ONLY, CFrame::OnRecordReadOnly)
  211. EVT_MENU(IDM_TAS_INPUT, CFrame::OnTASInput)
  212. EVT_MENU(IDM_TOGGLE_PAUSE_MOVIE, CFrame::OnTogglePauseMovie)
  213. EVT_MENU(IDM_SHOW_LAG, CFrame::OnShowLag)
  214. EVT_MENU(IDM_SHOW_FRAME_COUNT, CFrame::OnShowFrameCount)
  215. EVT_MENU(IDM_SHOW_INPUT_DISPLAY, CFrame::OnShowInputDisplay)
  216. EVT_MENU(IDM_FRAMESTEP, CFrame::OnFrameStep)
  217. EVT_MENU(IDM_SCREENSHOT, CFrame::OnScreenshot)
  218. EVT_MENU(IDM_TOGGLE_DUMP_FRAMES, CFrame::OnToggleDumpFrames)
  219. EVT_MENU(IDM_TOGGLE_DUMP_AUDIO, CFrame::OnToggleDumpAudio)
  220. EVT_MENU(wxID_PREFERENCES, CFrame::OnConfigMain)
  221. EVT_MENU(IDM_CONFIG_GFX_BACKEND, CFrame::OnConfigGFX)
  222. EVT_MENU(IDM_CONFIG_AUDIO, CFrame::OnConfigAudio)
  223. EVT_MENU(IDM_CONFIG_CONTROLLERS, CFrame::OnConfigControllers)
  224. EVT_MENU(IDM_CONFIG_HOTKEYS, CFrame::OnConfigHotkey)
  225. EVT_MENU(IDM_SAVE_PERSPECTIVE, CFrame::OnPerspectiveMenu)
  226. EVT_MENU(IDM_EDIT_PERSPECTIVES, CFrame::OnPerspectiveMenu)
  227. // Drop down
  228. EVT_MENU(IDM_PERSPECTIVES_ADD_PANE_TOP, CFrame::OnPerspectiveMenu)
  229. EVT_MENU(IDM_PERSPECTIVES_ADD_PANE_BOTTOM, CFrame::OnPerspectiveMenu)
  230. EVT_MENU(IDM_PERSPECTIVES_ADD_PANE_LEFT, CFrame::OnPerspectiveMenu)
  231. EVT_MENU(IDM_PERSPECTIVES_ADD_PANE_RIGHT, CFrame::OnPerspectiveMenu)
  232. EVT_MENU(IDM_PERSPECTIVES_ADD_PANE_CENTER, CFrame::OnPerspectiveMenu)
  233. EVT_MENU_RANGE(IDM_PERSPECTIVES_0, IDM_PERSPECTIVES_100, CFrame::OnSelectPerspective)
  234. EVT_MENU(IDM_ADD_PERSPECTIVE, CFrame::OnPerspectiveMenu)
  235. EVT_MENU(IDM_TAB_SPLIT, CFrame::OnPerspectiveMenu)
  236. EVT_MENU(IDM_NO_DOCKING, CFrame::OnPerspectiveMenu)
  237. // Drop down float
  238. EVT_MENU_RANGE(IDM_FLOAT_LOG_WINDOW, IDM_FLOAT_CODE_WINDOW, CFrame::OnFloatWindow)
  239. EVT_MENU(IDM_NETPLAY, CFrame::OnNetPlay)
  240. EVT_MENU(IDM_BROWSE, CFrame::OnBrowse)
  241. EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard)
  242. EVT_MENU(IDM_IMPORT_SAVE, CFrame::OnImportSave)
  243. EVT_MENU(IDM_EXPORT_ALL_SAVE, CFrame::OnExportAllSaves)
  244. EVT_MENU(IDM_CHEATS, CFrame::OnShowCheatsWindow)
  245. EVT_MENU(IDM_CHANGE_DISC, CFrame::OnChangeDisc)
  246. EVT_MENU(IDM_MENU_INSTALL_WAD, CFrame::OnInstallWAD)
  247. EVT_MENU(IDM_LIST_INSTALL_WAD, CFrame::OnInstallWAD)
  248. EVT_MENU(IDM_LOAD_WII_MENU, CFrame::OnLoadWiiMenu)
  249. EVT_MENU(IDM_FIFOPLAYER, CFrame::OnFifoPlayer)
  250. EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen)
  251. EVT_MENU(IDM_TOGGLE_DUAL_CORE, CFrame::OnToggleDualCore)
  252. EVT_MENU(IDM_TOGGLE_SKIP_IDLE, CFrame::OnToggleSkipIdle)
  253. EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar)
  254. EVT_MENU(IDM_TOGGLE_STATUSBAR, CFrame::OnToggleStatusbar)
  255. EVT_MENU_RANGE(IDM_LOG_WINDOW, IDM_VIDEO_WINDOW, CFrame::OnToggleWindow)
  256. EVT_MENU_RANGE(IDM_SHOW_SYSTEM, IDM_SHOW_STATE, CFrame::OnChangeColumnsVisible)
  257. EVT_MENU(IDM_PURGE_CACHE, CFrame::GameListChanged)
  258. EVT_MENU(IDM_SAVE_FIRST_STATE, CFrame::OnSaveFirstState)
  259. EVT_MENU(IDM_UNDO_LOAD_STATE, CFrame::OnUndoLoadState)
  260. EVT_MENU(IDM_UNDO_SAVE_STATE, CFrame::OnUndoSaveState)
  261. EVT_MENU(IDM_LOAD_STATE_FILE, CFrame::OnLoadStateFromFile)
  262. EVT_MENU(IDM_SAVE_STATE_FILE, CFrame::OnSaveStateToFile)
  263. EVT_MENU(IDM_SAVE_SELECTED_SLOT, CFrame::OnSaveCurrentSlot)
  264. EVT_MENU(IDM_LOAD_SELECTED_SLOT, CFrame::OnLoadCurrentSlot)
  265. EVT_MENU_RANGE(IDM_LOAD_SLOT_1, IDM_LOAD_SLOT_10, CFrame::OnLoadState)
  266. EVT_MENU_RANGE(IDM_LOAD_LAST_1, IDM_LOAD_LAST_8, CFrame::OnLoadLastState)
  267. EVT_MENU_RANGE(IDM_SAVE_SLOT_1, IDM_SAVE_SLOT_10, CFrame::OnSaveState)
  268. EVT_MENU_RANGE(IDM_SELECT_SLOT_1, IDM_SELECT_SLOT_10, CFrame::OnSelectSlot)
  269. EVT_MENU_RANGE(IDM_FRAME_SKIP_0, IDM_FRAME_SKIP_9, CFrame::OnFrameSkip)
  270. EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive)
  271. EVT_MENU_RANGE(IDM_CONNECT_WIIMOTE1, IDM_CONNECT_BALANCEBOARD, CFrame::OnConnectWiimote)
  272. EVT_MENU_RANGE(IDM_LIST_WAD, IDM_LIST_DRIVES, CFrame::GameListChanged)
  273. // Other
  274. EVT_ACTIVATE(CFrame::OnActive)
  275. EVT_CLOSE(CFrame::OnClose)
  276. EVT_SIZE(CFrame::OnResize)
  277. EVT_MOVE(CFrame::OnMove)
  278. EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage)
  279. EVT_AUI_PANE_CLOSE(CFrame::OnPaneClose)
  280. EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, CFrame::OnNotebookPageClose)
  281. EVT_AUINOTEBOOK_ALLOW_DND(wxID_ANY, CFrame::OnAllowNotebookDnD)
  282. EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, CFrame::OnNotebookPageChanged)
  283. EVT_AUINOTEBOOK_TAB_RIGHT_UP(wxID_ANY, CFrame::OnTab)
  284. // Post events to child panels
  285. EVT_MENU_RANGE(IDM_INTERPRETER, IDM_ADDRBOX, CFrame::PostEvent)
  286. EVT_TEXT(IDM_ADDRBOX, CFrame::PostEvent)
  287. END_EVENT_TABLE()
  288. // ---------------
  289. // Creation and close, quit functions
  290. bool CFrame::InitControllers()
  291. {
  292. if (!g_controller_interface.IsInit())
  293. {
  294. #if defined(HAVE_X11) && HAVE_X11
  295. Window win = X11Utils::XWindowFromHandle(GetHandle());
  296. Pad::Initialize(reinterpret_cast<void*>(win));
  297. Keyboard::Initialize(reinterpret_cast<void*>(win));
  298. Wiimote::Initialize(reinterpret_cast<void*>(win));
  299. HotkeyManagerEmu::Initialize(reinterpret_cast<void*>(win));
  300. #else
  301. Pad::Initialize(reinterpret_cast<void*>(GetHandle()));
  302. Keyboard::Initialize(reinterpret_cast<void*>(GetHandle()));
  303. Wiimote::Initialize(reinterpret_cast<void*>(GetHandle()));
  304. HotkeyManagerEmu::Initialize(reinterpret_cast<void*>(GetHandle()));
  305. #endif
  306. return true;
  307. }
  308. return false;
  309. }
  310. CFrame::CFrame(wxFrame* parent,
  311. wxWindowID id,
  312. const wxString& title,
  313. const wxPoint& pos,
  314. const wxSize& size,
  315. bool _UseDebugger,
  316. bool _BatchMode,
  317. bool ShowLogWindow,
  318. long style)
  319. : CRenderFrame(parent, id, title, pos, size, style)
  320. , g_pCodeWindow(nullptr), g_NetPlaySetupDiag(nullptr), g_CheatsWindow(nullptr)
  321. , m_SavedPerspectives(nullptr), m_ToolBar(nullptr)
  322. , m_GameListCtrl(nullptr), m_Panel(nullptr)
  323. , m_RenderFrame(nullptr), m_RenderParent(nullptr)
  324. , m_LogWindow(nullptr), m_LogConfigWindow(nullptr)
  325. , m_FifoPlayerDlg(nullptr), UseDebugger(_UseDebugger)
  326. , m_bBatchMode(_BatchMode), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false)
  327. , m_bGameLoading(false), m_bClosing(false), m_confirmStop(false), m_menubar_shadow(nullptr)
  328. {
  329. for (int i = 0; i <= IDM_CODE_WINDOW - IDM_LOG_WINDOW; i++)
  330. bFloatWindow[i] = false;
  331. if (ShowLogWindow)
  332. SConfig::GetInstance().m_InterfaceLogWindow = true;
  333. // Start debugging maximized
  334. if (UseDebugger)
  335. this->Maximize(true);
  336. // Debugger class
  337. if (UseDebugger)
  338. {
  339. g_pCodeWindow = new CCodeWindow(SConfig::GetInstance().m_LocalCoreStartupParameter, this, IDM_CODE_WINDOW);
  340. LoadIniPerspectives();
  341. g_pCodeWindow->Load();
  342. }
  343. // Create toolbar bitmaps
  344. InitBitmaps();
  345. // Give it a status bar
  346. SetStatusBar(CreateStatusBar(2, wxST_SIZEGRIP, ID_STATUSBAR));
  347. if (!SConfig::GetInstance().m_InterfaceStatusbar)
  348. GetStatusBar()->Hide();
  349. // Give it a menu bar
  350. wxMenuBar* menubar_active = CreateMenu();
  351. SetMenuBar(menubar_active);
  352. // Create a menubar to service requests while the real menubar is hidden from the screen
  353. m_menubar_shadow = CreateMenu();
  354. // ---------------
  355. // Main panel
  356. // This panel is the parent for rendering and it holds the gamelistctrl
  357. m_Panel = new wxPanel(this, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0);
  358. m_GameListCtrl = new CGameListCtrl(m_Panel, wxID_ANY,
  359. wxDefaultPosition, wxDefaultSize,
  360. wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT);
  361. m_GameListCtrl->Bind(wxEVT_LIST_ITEM_ACTIVATED, &CFrame::OnGameListCtrlItemActivated, this);
  362. wxBoxSizer *sizerPanel = new wxBoxSizer(wxHORIZONTAL);
  363. sizerPanel->Add(m_GameListCtrl, 1, wxEXPAND | wxALL);
  364. m_Panel->SetSizer(sizerPanel);
  365. // ---------------
  366. // Manager
  367. m_Mgr = new wxAuiManager(this, wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE);
  368. m_Mgr->AddPane(m_Panel, wxAuiPaneInfo()
  369. .Name("Pane 0").Caption("Pane 0").PaneBorder(false)
  370. .CaptionVisible(false).Layer(0).Center().Show());
  371. if (!g_pCodeWindow)
  372. m_Mgr->AddPane(CreateEmptyNotebook(), wxAuiPaneInfo()
  373. .Name("Pane 1").Caption(_("Logging")).CaptionVisible(true)
  374. .Layer(0).FloatingSize(wxSize(600, 350)).CloseButton(true).Hide());
  375. AuiFullscreen = m_Mgr->SavePerspective();
  376. // Create toolbar
  377. RecreateToolbar();
  378. if (!SConfig::GetInstance().m_InterfaceToolbar) DoToggleToolbar(false);
  379. m_LogWindow = new CLogWindow(this, IDM_LOG_WINDOW);
  380. m_LogWindow->Hide();
  381. m_LogWindow->Disable();
  382. for (int i = 0; i < 8; ++i)
  383. g_TASInputDlg[i] = new TASInputDlg(this);
  384. Movie::SetGCInputManip(GCTASManipFunction);
  385. Movie::SetWiiInputManip(WiiTASManipFunction);
  386. State::SetOnAfterLoadCallback(OnAfterLoadCallback);
  387. Core::SetOnStoppedCallback(OnStoppedCallback);
  388. // Setup perspectives
  389. if (g_pCodeWindow)
  390. {
  391. // Load perspective
  392. DoLoadPerspective();
  393. }
  394. else
  395. {
  396. if (SConfig::GetInstance().m_InterfaceLogWindow)
  397. ToggleLogWindow(true);
  398. if (SConfig::GetInstance().m_InterfaceLogConfigWindow)
  399. ToggleLogConfigWindow(true);
  400. }
  401. // Show window
  402. Show();
  403. // Commit
  404. m_Mgr->Update();
  405. #ifdef _WIN32
  406. SetToolTip("");
  407. GetToolTip()->SetAutoPop(25000);
  408. #endif
  409. #if defined(HAVE_XRANDR) && HAVE_XRANDR
  410. m_XRRConfig = new X11Utils::XRRConfiguration(X11Utils::XDisplayFromHandle(GetHandle()),
  411. X11Utils::XWindowFromHandle(GetHandle()));
  412. #endif
  413. // -------------------------
  414. // Connect event handlers
  415. m_Mgr->Bind(wxEVT_AUI_RENDER, &CFrame::OnManagerResize, this);
  416. // ----------
  417. // Update controls
  418. UpdateGUI();
  419. if (g_pCodeWindow)
  420. g_pCodeWindow->UpdateButtonStates();
  421. // check if game is running
  422. InitControllers();
  423. m_poll_hotkey_timer.SetOwner(this);
  424. Bind(wxEVT_TIMER, &CFrame::PollHotkeys, this);
  425. m_poll_hotkey_timer.Start(1000 / 60, wxTIMER_CONTINUOUS);
  426. }
  427. // Destructor
  428. CFrame::~CFrame()
  429. {
  430. Wiimote::Shutdown();
  431. Keyboard::Shutdown();
  432. Pad::Shutdown();
  433. HotkeyManagerEmu::Shutdown();
  434. drives.clear();
  435. #if defined(HAVE_XRANDR) && HAVE_XRANDR
  436. delete m_XRRConfig;
  437. #endif
  438. ClosePages();
  439. delete m_Mgr;
  440. // This object is owned by us, not wxw
  441. m_menubar_shadow->Destroy();
  442. m_menubar_shadow = nullptr;
  443. }
  444. bool CFrame::RendererIsFullscreen()
  445. {
  446. bool fullscreen = false;
  447. if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
  448. {
  449. fullscreen = m_RenderFrame->IsFullScreen();
  450. }
  451. #if defined(__APPLE__)
  452. if (m_RenderFrame != nullptr)
  453. {
  454. NSView *view = (NSView *) m_RenderFrame->GetHandle();
  455. NSWindow *window = [view window];
  456. fullscreen = (([window styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask);
  457. }
  458. #endif
  459. return fullscreen;
  460. }
  461. void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event))
  462. {
  463. Close(true);
  464. }
  465. // --------
  466. // Events
  467. void CFrame::OnActive(wxActivateEvent& event)
  468. {
  469. if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
  470. {
  471. if (event.GetActive() && event.GetEventObject() == m_RenderFrame)
  472. {
  473. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
  474. m_RenderParent->SetFocus();
  475. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor &&
  476. Core::GetState() == Core::CORE_RUN)
  477. m_RenderParent->SetCursor(wxCURSOR_BLANK);
  478. }
  479. else
  480. {
  481. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
  482. m_RenderParent->SetCursor(wxNullCursor);
  483. }
  484. }
  485. event.Skip();
  486. }
  487. void CFrame::OnClose(wxCloseEvent& event)
  488. {
  489. m_bClosing = true;
  490. // Before closing the window we need to shut down the emulation core.
  491. // We'll try to close this window again once that is done.
  492. if (Core::GetState() != Core::CORE_UNINITIALIZED)
  493. {
  494. DoStop();
  495. if (event.CanVeto())
  496. {
  497. event.Veto();
  498. }
  499. return;
  500. }
  501. // Stop Dolphin from saving the minimized Xpos and Ypos
  502. if (main_frame->IsIconized())
  503. main_frame->Iconize(false);
  504. // Don't forget the skip or the window won't be destroyed
  505. event.Skip();
  506. // Save GUI settings
  507. if (g_pCodeWindow)
  508. {
  509. SaveIniPerspectives();
  510. }
  511. else
  512. {
  513. // Close the log window now so that its settings are saved
  514. if (m_LogWindow)
  515. m_LogWindow->Close();
  516. m_LogWindow = nullptr;
  517. }
  518. // Uninit
  519. m_Mgr->UnInit();
  520. }
  521. // Post events
  522. // Warning: This may cause an endless loop if the event is propagated back to its parent
  523. void CFrame::PostEvent(wxCommandEvent& event)
  524. {
  525. if (g_pCodeWindow &&
  526. event.GetId() >= IDM_INTERPRETER &&
  527. event.GetId() <= IDM_ADDRBOX)
  528. {
  529. event.StopPropagation();
  530. g_pCodeWindow->GetEventHandler()->AddPendingEvent(event);
  531. }
  532. else
  533. {
  534. event.Skip();
  535. }
  536. }
  537. void CFrame::OnMove(wxMoveEvent& event)
  538. {
  539. event.Skip();
  540. if (!IsMaximized() &&
  541. !(SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && RendererIsFullscreen()))
  542. {
  543. SConfig::GetInstance().m_LocalCoreStartupParameter.iPosX = GetPosition().x;
  544. SConfig::GetInstance().m_LocalCoreStartupParameter.iPosY = GetPosition().y;
  545. }
  546. }
  547. void CFrame::OnResize(wxSizeEvent& event)
  548. {
  549. event.Skip();
  550. if (!IsMaximized() &&
  551. !(SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && RendererIsFullscreen()) &&
  552. !(Core::GetState() != Core::CORE_UNINITIALIZED &&
  553. SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain &&
  554. SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize))
  555. {
  556. SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth = GetSize().GetWidth();
  557. SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight = GetSize().GetHeight();
  558. }
  559. // Make sure the logger pane is a sane size
  560. if (!g_pCodeWindow && m_LogWindow && m_Mgr->GetPane("Pane 1").IsShown() &&
  561. !m_Mgr->GetPane("Pane 1").IsFloating() &&
  562. (m_LogWindow->x > GetClientRect().GetWidth() ||
  563. m_LogWindow->y > GetClientRect().GetHeight()))
  564. ShowResizePane();
  565. }
  566. // Host messages
  567. #ifdef _WIN32
  568. WXLRESULT CFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
  569. {
  570. if (WM_SYSCOMMAND == nMsg && (SC_SCREENSAVE == wParam || SC_MONITORPOWER == wParam))
  571. {
  572. return 0;
  573. }
  574. else if (nMsg == WM_QUERYENDSESSION)
  575. {
  576. // Indicate that the application will be able to close
  577. return 1;
  578. }
  579. else if (nMsg == WM_ENDSESSION)
  580. {
  581. // Actually trigger the close now
  582. Close(true);
  583. return 0;
  584. }
  585. else
  586. {
  587. return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
  588. }
  589. }
  590. #endif
  591. void CFrame::UpdateTitle(const std::string &str)
  592. {
  593. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain &&
  594. SConfig::GetInstance().m_InterfaceStatusbar)
  595. {
  596. GetStatusBar()->SetStatusText(str, 0);
  597. m_RenderFrame->SetTitle(scm_rev_str);
  598. }
  599. else
  600. {
  601. std::string titleStr = StringFromFormat("%s | %s", scm_rev_str, str.c_str());
  602. m_RenderFrame->SetTitle(titleStr);
  603. }
  604. }
  605. void CFrame::OnHostMessage(wxCommandEvent& event)
  606. {
  607. switch (event.GetId())
  608. {
  609. case IDM_UPDATE_GUI:
  610. UpdateGUI();
  611. break;
  612. case IDM_UPDATE_STATUS_BAR:
  613. if (GetStatusBar() != nullptr)
  614. GetStatusBar()->SetStatusText(event.GetString(), event.GetInt());
  615. break;
  616. case IDM_UPDATE_TITLE:
  617. UpdateTitle(WxStrToStr(event.GetString()));
  618. break;
  619. case IDM_WINDOW_SIZE_REQUEST:
  620. {
  621. std::pair<int, int> *win_size = (std::pair<int, int> *)(event.GetClientData());
  622. OnRenderWindowSizeRequest(win_size->first, win_size->second);
  623. delete win_size;
  624. }
  625. break;
  626. case IDM_FULLSCREEN_REQUEST:
  627. {
  628. bool enable_fullscreen = event.GetInt() == 0 ? false : true;
  629. ToggleDisplayMode(enable_fullscreen);
  630. if (m_RenderFrame != nullptr)
  631. m_RenderFrame->ShowFullScreen(enable_fullscreen);
  632. // If the stop dialog initiated this fullscreen switch then we need
  633. // to pause the emulator after we've completed the switch.
  634. // TODO: Allow the renderer to switch fullscreen modes while paused.
  635. if (m_confirmStop)
  636. Core::SetState(Core::CORE_PAUSE);
  637. }
  638. break;
  639. case WM_USER_CREATE:
  640. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
  641. m_RenderParent->SetCursor(wxCURSOR_BLANK);
  642. break;
  643. #ifdef __WXGTK__
  644. case IDM_PANIC:
  645. {
  646. wxString caption = event.GetString().BeforeFirst(':');
  647. wxString text = event.GetString().AfterFirst(':');
  648. bPanicResult = (wxYES == wxMessageBox(text,
  649. caption, event.GetInt() ? wxYES_NO : wxOK, wxWindow::FindFocus()));
  650. panic_event.Set();
  651. }
  652. break;
  653. #endif
  654. case WM_USER_STOP:
  655. DoStop();
  656. break;
  657. case IDM_STOPPED:
  658. OnStopped();
  659. break;
  660. }
  661. }
  662. void CFrame::OnRenderWindowSizeRequest(int width, int height)
  663. {
  664. if (!Core::IsRunning() ||
  665. !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize ||
  666. RendererIsFullscreen() || m_RenderFrame->IsMaximized())
  667. return;
  668. int old_width, old_height, log_width = 0, log_height = 0;
  669. m_RenderFrame->GetClientSize(&old_width, &old_height);
  670. // Add space for the log/console/debugger window
  671. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain &&
  672. (SConfig::GetInstance().m_InterfaceLogWindow ||
  673. SConfig::GetInstance().m_InterfaceLogConfigWindow) &&
  674. !m_Mgr->GetPane("Pane 1").IsFloating())
  675. {
  676. switch (m_Mgr->GetPane("Pane 1").dock_direction)
  677. {
  678. case wxAUI_DOCK_LEFT:
  679. case wxAUI_DOCK_RIGHT:
  680. log_width = m_Mgr->GetPane("Pane 1").rect.GetWidth();
  681. break;
  682. case wxAUI_DOCK_TOP:
  683. case wxAUI_DOCK_BOTTOM:
  684. log_height = m_Mgr->GetPane("Pane 1").rect.GetHeight();
  685. break;
  686. }
  687. }
  688. if (old_width != width + log_width || old_height != height + log_height)
  689. m_RenderFrame->SetClientSize(width + log_width, height + log_height);
  690. }
  691. bool CFrame::RendererHasFocus()
  692. {
  693. if (m_RenderParent == nullptr)
  694. return false;
  695. #ifdef _WIN32
  696. HWND window = GetForegroundWindow();
  697. if (window == nullptr)
  698. return false;
  699. if (m_RenderFrame->GetHWND() == window)
  700. return true;
  701. #else
  702. wxWindow *window = wxWindow::FindFocus();
  703. if (window == nullptr)
  704. return false;
  705. // Why these different cases?
  706. if (m_RenderParent == window ||
  707. m_RenderParent == window->GetParent() ||
  708. m_RenderParent->GetParent() == window->GetParent())
  709. {
  710. return true;
  711. }
  712. #endif
  713. return false;
  714. }
  715. bool CFrame::UIHasFocus()
  716. {
  717. // UIHasFocus should return true any time any one of our UI
  718. // windows has the focus, including any dialogs or other windows.
  719. //
  720. // wxWindow::FindFocus() returns the current wxWindow which has
  721. // focus. If it's not one of our windows, then it will return
  722. // null.
  723. wxWindow *focusWindow = wxWindow::FindFocus();
  724. return (focusWindow != nullptr);
  725. }
  726. void CFrame::OnGameListCtrlItemActivated(wxListEvent& WXUNUSED(event))
  727. {
  728. // Show all platforms and regions if...
  729. // 1. All platforms are set to hide
  730. // 2. All Regions are set to hide
  731. // Otherwise call BootGame to either...
  732. // 1. Boot the selected iso
  733. // 2. Boot the default or last loaded iso.
  734. // 3. Call BrowseForDirectory if the gamelist is empty
  735. if (!m_GameListCtrl->GetISO(0) &&
  736. !((SConfig::GetInstance().m_ListGC &&
  737. SConfig::GetInstance().m_ListWii &&
  738. SConfig::GetInstance().m_ListWad) &&
  739. (SConfig::GetInstance().m_ListJap &&
  740. SConfig::GetInstance().m_ListUsa &&
  741. SConfig::GetInstance().m_ListPal &&
  742. SConfig::GetInstance().m_ListAustralia &&
  743. SConfig::GetInstance().m_ListFrance &&
  744. SConfig::GetInstance().m_ListGermany &&
  745. SConfig::GetInstance().m_ListItaly &&
  746. SConfig::GetInstance().m_ListKorea &&
  747. SConfig::GetInstance().m_ListNetherlands &&
  748. SConfig::GetInstance().m_ListRussia &&
  749. SConfig::GetInstance().m_ListSpain &&
  750. SConfig::GetInstance().m_ListTaiwan &&
  751. SConfig::GetInstance().m_ListWorld &&
  752. SConfig::GetInstance().m_ListUnknown)))
  753. {
  754. SConfig::GetInstance().m_ListGC =
  755. SConfig::GetInstance().m_ListWii =
  756. SConfig::GetInstance().m_ListWad =
  757. SConfig::GetInstance().m_ListJap =
  758. SConfig::GetInstance().m_ListUsa =
  759. SConfig::GetInstance().m_ListPal =
  760. SConfig::GetInstance().m_ListAustralia =
  761. SConfig::GetInstance().m_ListFrance =
  762. SConfig::GetInstance().m_ListGermany =
  763. SConfig::GetInstance().m_ListItaly =
  764. SConfig::GetInstance().m_ListKorea =
  765. SConfig::GetInstance().m_ListNetherlands =
  766. SConfig::GetInstance().m_ListRussia =
  767. SConfig::GetInstance().m_ListSpain =
  768. SConfig::GetInstance().m_ListTaiwan =
  769. SConfig::GetInstance().m_ListWorld =
  770. SConfig::GetInstance().m_ListUnknown = true;
  771. GetMenuBar()->FindItem(IDM_LIST_GC)->Check(true);
  772. GetMenuBar()->FindItem(IDM_LIST_WII)->Check(true);
  773. GetMenuBar()->FindItem(IDM_LIST_WAD)->Check(true);
  774. GetMenuBar()->FindItem(IDM_LIST_JAP)->Check(true);
  775. GetMenuBar()->FindItem(IDM_LIST_USA)->Check(true);
  776. GetMenuBar()->FindItem(IDM_LIST_PAL)->Check(true);
  777. GetMenuBar()->FindItem(IDM_LIST_AUSTRALIA)->Check(true);
  778. GetMenuBar()->FindItem(IDM_LIST_FRANCE)->Check(true);
  779. GetMenuBar()->FindItem(IDM_LIST_GERMANY)->Check(true);
  780. GetMenuBar()->FindItem(IDM_LIST_ITALY)->Check(true);
  781. GetMenuBar()->FindItem(IDM_LIST_KOREA)->Check(true);
  782. GetMenuBar()->FindItem(IDM_LIST_NETHERLANDS)->Check(true);
  783. GetMenuBar()->FindItem(IDM_LIST_RUSSIA)->Check(true);
  784. GetMenuBar()->FindItem(IDM_LIST_SPAIN)->Check(true);
  785. GetMenuBar()->FindItem(IDM_LIST_TAIWAN)->Check(true);
  786. GetMenuBar()->FindItem(IDM_LIST_WORLD)->Check(true);
  787. GetMenuBar()->FindItem(IDM_LIST_UNKNOWN)->Check(true);
  788. m_GameListCtrl->Update();
  789. }
  790. else if (!m_GameListCtrl->GetISO(0))
  791. {
  792. m_GameListCtrl->BrowseForDirectory();
  793. }
  794. else
  795. {
  796. // Game started by double click
  797. BootGame("");
  798. }
  799. }
  800. static bool IsHotkey(int id, bool held = false)
  801. {
  802. return HotkeyManagerEmu::IsPressed(id, held);
  803. }
  804. int GetCmdForHotkey(unsigned int key)
  805. {
  806. switch (key)
  807. {
  808. case HK_OPEN: return wxID_OPEN;
  809. case HK_CHANGE_DISC: return IDM_CHANGE_DISC;
  810. case HK_REFRESH_LIST: return wxID_REFRESH;
  811. case HK_PLAY_PAUSE: return IDM_PLAY;
  812. case HK_STOP: return IDM_STOP;
  813. case HK_RESET: return IDM_RESET;
  814. case HK_FRAME_ADVANCE: return IDM_FRAMESTEP;
  815. case HK_START_RECORDING: return IDM_RECORD;
  816. case HK_PLAY_RECORDING: return IDM_PLAY_RECORD;
  817. case HK_EXPORT_RECORDING: return IDM_RECORD_EXPORT;
  818. case HK_READ_ONLY_MODE: return IDM_RECORD_READ_ONLY;
  819. case HK_FULLSCREEN: return IDM_TOGGLE_FULLSCREEN;
  820. case HK_SCREENSHOT: return IDM_SCREENSHOT;
  821. case HK_EXIT: return wxID_EXIT;
  822. case HK_WIIMOTE1_CONNECT: return IDM_CONNECT_WIIMOTE1;
  823. case HK_WIIMOTE2_CONNECT: return IDM_CONNECT_WIIMOTE2;
  824. case HK_WIIMOTE3_CONNECT: return IDM_CONNECT_WIIMOTE3;
  825. case HK_WIIMOTE4_CONNECT: return IDM_CONNECT_WIIMOTE4;
  826. case HK_BALANCEBOARD_CONNECT: return IDM_CONNECT_BALANCEBOARD;
  827. case HK_LOAD_STATE_SLOT_1: return IDM_LOAD_SLOT_1;
  828. case HK_LOAD_STATE_SLOT_2: return IDM_LOAD_SLOT_2;
  829. case HK_LOAD_STATE_SLOT_3: return IDM_LOAD_SLOT_3;
  830. case HK_LOAD_STATE_SLOT_4: return IDM_LOAD_SLOT_4;
  831. case HK_LOAD_STATE_SLOT_5: return IDM_LOAD_SLOT_5;
  832. case HK_LOAD_STATE_SLOT_6: return IDM_LOAD_SLOT_6;
  833. case HK_LOAD_STATE_SLOT_7: return IDM_LOAD_SLOT_7;
  834. case HK_LOAD_STATE_SLOT_8: return IDM_LOAD_SLOT_8;
  835. case HK_LOAD_STATE_SLOT_9: return IDM_LOAD_SLOT_9;
  836. case HK_LOAD_STATE_SLOT_10: return IDM_LOAD_SLOT_10;
  837. case HK_SAVE_STATE_SLOT_1: return IDM_SAVE_SLOT_1;
  838. case HK_SAVE_STATE_SLOT_2: return IDM_SAVE_SLOT_2;
  839. case HK_SAVE_STATE_SLOT_3: return IDM_SAVE_SLOT_3;
  840. case HK_SAVE_STATE_SLOT_4: return IDM_SAVE_SLOT_4;
  841. case HK_SAVE_STATE_SLOT_5: return IDM_SAVE_SLOT_5;
  842. case HK_SAVE_STATE_SLOT_6: return IDM_SAVE_SLOT_6;
  843. case HK_SAVE_STATE_SLOT_7: return IDM_SAVE_SLOT_7;
  844. case HK_SAVE_STATE_SLOT_8: return IDM_SAVE_SLOT_8;
  845. case HK_SAVE_STATE_SLOT_9: return IDM_SAVE_SLOT_9;
  846. case HK_SAVE_STATE_SLOT_10: return IDM_SAVE_SLOT_10;
  847. case HK_LOAD_LAST_STATE_1: return IDM_LOAD_LAST_1;
  848. case HK_LOAD_LAST_STATE_2: return IDM_LOAD_LAST_2;
  849. case HK_LOAD_LAST_STATE_3: return IDM_LOAD_LAST_3;
  850. case HK_LOAD_LAST_STATE_4: return IDM_LOAD_LAST_4;
  851. case HK_LOAD_LAST_STATE_5: return IDM_LOAD_LAST_5;
  852. case HK_LOAD_LAST_STATE_6: return IDM_LOAD_LAST_6;
  853. case HK_LOAD_LAST_STATE_7: return IDM_LOAD_LAST_7;
  854. case HK_LOAD_LAST_STATE_8: return IDM_LOAD_LAST_8;
  855. case HK_SAVE_FIRST_STATE: return IDM_SAVE_FIRST_STATE;
  856. case HK_UNDO_LOAD_STATE: return IDM_UNDO_LOAD_STATE;
  857. case HK_UNDO_SAVE_STATE: return IDM_UNDO_SAVE_STATE;
  858. case HK_LOAD_STATE_FILE: return IDM_LOAD_STATE_FILE;
  859. case HK_SAVE_STATE_FILE: return IDM_SAVE_STATE_FILE;
  860. case HK_SELECT_STATE_SLOT_1: return IDM_SELECT_SLOT_1;
  861. case HK_SELECT_STATE_SLOT_2: return IDM_SELECT_SLOT_2;
  862. case HK_SELECT_STATE_SLOT_3: return IDM_SELECT_SLOT_3;
  863. case HK_SELECT_STATE_SLOT_4: return IDM_SELECT_SLOT_4;
  864. case HK_SELECT_STATE_SLOT_5: return IDM_SELECT_SLOT_5;
  865. case HK_SELECT_STATE_SLOT_6: return IDM_SELECT_SLOT_6;
  866. case HK_SELECT_STATE_SLOT_7: return IDM_SELECT_SLOT_7;
  867. case HK_SELECT_STATE_SLOT_8: return IDM_SELECT_SLOT_8;
  868. case HK_SELECT_STATE_SLOT_9: return IDM_SELECT_SLOT_9;
  869. case HK_SELECT_STATE_SLOT_10: return IDM_SELECT_SLOT_10;
  870. case HK_SAVE_STATE_SLOT_SELECTED: return IDM_SAVE_SELECTED_SLOT;
  871. case HK_LOAD_STATE_SLOT_SELECTED: return IDM_LOAD_SELECTED_SLOT;
  872. case HK_FREELOOK_DECREASE_SPEED: return IDM_FREELOOK_DECREASE_SPEED;
  873. case HK_FREELOOK_INCREASE_SPEED: return IDM_FREELOOK_INCREASE_SPEED;
  874. case HK_FREELOOK_RESET_SPEED: return IDM_FREELOOK_RESET_SPEED;
  875. case HK_FREELOOK_LEFT: return IDM_FREELOOK_LEFT;
  876. case HK_FREELOOK_RIGHT: return IDM_FREELOOK_RIGHT;
  877. case HK_FREELOOK_UP: return IDM_FREELOOK_UP;
  878. case HK_FREELOOK_DOWN: return IDM_FREELOOK_DOWN;
  879. case HK_FREELOOK_ZOOM_IN: return IDM_FREELOOK_ZOOM_IN;
  880. case HK_FREELOOK_ZOOM_OUT: return IDM_FREELOOK_ZOOM_OUT;
  881. case HK_FREELOOK_RESET: return IDM_FREELOOK_RESET;
  882. }
  883. return -1;
  884. }
  885. void OnAfterLoadCallback()
  886. {
  887. // warning: this gets called from the CPU thread, so we should only queue things to do on the proper thread
  888. if (main_frame)
  889. {
  890. wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATE_GUI);
  891. main_frame->GetEventHandler()->AddPendingEvent(event);
  892. }
  893. }
  894. void OnStoppedCallback()
  895. {
  896. // warning: this gets called from the EmuThread, so we should only queue things to do on the proper thread
  897. if (main_frame)
  898. {
  899. wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_STOPPED);
  900. main_frame->GetEventHandler()->AddPendingEvent(event);
  901. }
  902. }
  903. void GCTASManipFunction(GCPadStatus* PadStatus, int controllerID)
  904. {
  905. if (main_frame)
  906. main_frame->g_TASInputDlg[controllerID]->GetValues(PadStatus);
  907. }
  908. void WiiTASManipFunction(u8* data, WiimoteEmu::ReportFeatures rptf, int controllerID, int ext, const wiimote_key key)
  909. {
  910. if (main_frame)
  911. {
  912. main_frame->g_TASInputDlg[controllerID + 4]->GetValues(data, rptf, ext, key);
  913. }
  914. }
  915. bool TASInputHasFocus()
  916. {
  917. for (int i = 0; i < 8; ++i)
  918. {
  919. if (main_frame->g_TASInputDlg[i]->TASHasFocus())
  920. return true;
  921. }
  922. return false;
  923. }
  924. void CFrame::OnKeyDown(wxKeyEvent& event)
  925. {
  926. // On OS X, we claim all keyboard events while
  927. // emulation is running to avoid wxWidgets sounding
  928. // the system beep for unhandled key events when
  929. // receiving pad/Wiimote keypresses which take an
  930. // entirely different path through the HID subsystem.
  931. #ifndef __APPLE__
  932. // On other platforms, we leave the key event alone
  933. // so it can be passed on to the windowing system.
  934. event.Skip();
  935. #endif
  936. }
  937. void CFrame::OnMouse(wxMouseEvent& event)
  938. {
  939. // next handlers are all for FreeLook, so we don't need to check them if disabled
  940. if (!g_Config.bFreeLook)
  941. {
  942. event.Skip();
  943. return;
  944. }
  945. // Free look variables
  946. static bool mouseLookEnabled = false;
  947. static bool mouseMoveEnabled = false;
  948. static float lastMouse[2];
  949. if (event.MiddleDown())
  950. {
  951. lastMouse[0] = event.GetX();
  952. lastMouse[1] = event.GetY();
  953. mouseMoveEnabled = true;
  954. }
  955. else if (event.RightDown())
  956. {
  957. lastMouse[0] = event.GetX();
  958. lastMouse[1] = event.GetY();
  959. mouseLookEnabled = true;
  960. }
  961. else if (event.MiddleUp())
  962. {
  963. mouseMoveEnabled = false;
  964. }
  965. else if (event.RightUp())
  966. {
  967. mouseLookEnabled = false;
  968. }
  969. // no button, so it's a move event
  970. else if (event.GetButton() == wxMOUSE_BTN_NONE)
  971. {
  972. if (mouseLookEnabled)
  973. {
  974. VertexShaderManager::RotateView((event.GetX() - lastMouse[0]) / 200.0f,
  975. (event.GetY() - lastMouse[1]) / 200.0f);
  976. lastMouse[0] = event.GetX();
  977. lastMouse[1] = event.GetY();
  978. }
  979. if (mouseMoveEnabled)
  980. {
  981. VertexShaderManager::TranslateView((event.GetX() - lastMouse[0]) / 50.0f,
  982. (event.GetY() - lastMouse[1]) / 50.0f);
  983. lastMouse[0] = event.GetX();
  984. lastMouse[1] = event.GetY();
  985. }
  986. }
  987. event.Skip();
  988. }
  989. void CFrame::OnFocusChange(wxFocusEvent& event)
  990. {
  991. if (SConfig::GetInstance().m_PauseOnFocusLost && Core::IsRunningAndStarted())
  992. {
  993. if (RendererHasFocus())
  994. {
  995. if (Core::GetState() == Core::CORE_PAUSE)
  996. {
  997. Core::SetState(Core::CORE_RUN);
  998. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
  999. m_RenderParent->SetCursor(wxCURSOR_BLANK);
  1000. }
  1001. }
  1002. else
  1003. {
  1004. if (Core::GetState() == Core::CORE_RUN)
  1005. {
  1006. Core::SetState(Core::CORE_PAUSE);
  1007. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
  1008. m_RenderParent->SetCursor(wxNullCursor);
  1009. Core::UpdateTitle();
  1010. }
  1011. }
  1012. UpdateGUI();
  1013. }
  1014. event.Skip();
  1015. }
  1016. void CFrame::DoFullscreen(bool enable_fullscreen)
  1017. {
  1018. if (g_Config.bExclusiveMode && Core::GetState() == Core::CORE_PAUSE)
  1019. {
  1020. // A responsive renderer is required for exclusive fullscreen, but the
  1021. // renderer can only respond in the running state. Therefore we ignore
  1022. // fullscreen switches if we are in exclusive fullscreen, but the
  1023. // renderer is not running.
  1024. // TODO: Allow the renderer to switch fullscreen modes while paused.
  1025. return;
  1026. }
  1027. ToggleDisplayMode(enable_fullscreen);
  1028. #if defined(__APPLE__)
  1029. NSView *view = (NSView *)m_RenderFrame->GetHandle();
  1030. NSWindow *window = [view window];
  1031. if (enable_fullscreen != RendererIsFullscreen())
  1032. {
  1033. [window toggleFullScreen : nil];
  1034. }
  1035. #else
  1036. if (enable_fullscreen)
  1037. {
  1038. m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL);
  1039. }
  1040. else if (!g_Config.bExclusiveMode)
  1041. {
  1042. // Exiting exclusive fullscreen should be done from a Renderer callback.
  1043. // Therefore we don't exit fullscreen from here if we are in exclusive mode.
  1044. m_RenderFrame->ShowFullScreen(false, wxFULLSCREEN_ALL);
  1045. }
  1046. #endif
  1047. if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
  1048. {
  1049. if (enable_fullscreen)
  1050. {
  1051. // Save the current mode before going to fullscreen
  1052. AuiCurrent = m_Mgr->SavePerspective();
  1053. m_Mgr->LoadPerspective(AuiFullscreen, true);
  1054. // Hide toolbar
  1055. DoToggleToolbar(false);
  1056. // Hide menubar (by having wxwidgets delete it)
  1057. SetMenuBar(nullptr);
  1058. // Hide the statusbar if enabled
  1059. if (GetStatusBar()->IsShown())
  1060. {
  1061. GetStatusBar()->Hide();
  1062. this->SendSizeEvent();
  1063. }
  1064. }
  1065. else
  1066. {
  1067. // Restore saved perspective
  1068. m_Mgr->LoadPerspective(AuiCurrent, true);
  1069. // Restore toolbar to the status it was at before going fullscreen.
  1070. DoToggleToolbar(SConfig::GetInstance().m_InterfaceToolbar);
  1071. // Recreate the menubar if needed.
  1072. if (wxFrame::GetMenuBar() == nullptr)
  1073. {
  1074. SetMenuBar(CreateMenu());
  1075. }
  1076. // Show statusbar if enabled
  1077. if (SConfig::GetInstance().m_InterfaceStatusbar)
  1078. {
  1079. GetStatusBar()->Show();
  1080. this->SendSizeEvent();
  1081. }
  1082. }
  1083. }
  1084. else
  1085. {
  1086. m_RenderFrame->Raise();
  1087. }
  1088. g_Config.bFullscreen = enable_fullscreen;
  1089. }
  1090. const CGameListCtrl *CFrame::GetGameListCtrl() const
  1091. {
  1092. return m_GameListCtrl;
  1093. }
  1094. void CFrame::PollHotkeys(wxTimerEvent& event)
  1095. {
  1096. if (!HotkeyManagerEmu::IsEnabled())
  1097. return;
  1098. if (Core::GetState() == Core::CORE_UNINITIALIZED || Core::GetState() == Core::CORE_PAUSE)
  1099. g_controller_interface.UpdateInput();
  1100. if (Core::GetState() != Core::CORE_STOPPING)
  1101. {
  1102. HotkeyManagerEmu::GetStatus();
  1103. ParseHotkeys();
  1104. }
  1105. }
  1106. void CFrame::ParseHotkeys()
  1107. {
  1108. for (int i = 0; i < NUM_HOTKEYS; i++)
  1109. {
  1110. switch (i)
  1111. {
  1112. case HK_OPEN:
  1113. case HK_CHANGE_DISC:
  1114. case HK_REFRESH_LIST:
  1115. case HK_RESET:
  1116. case HK_FRAME_ADVANCE:
  1117. case HK_START_RECORDING:
  1118. case HK_PLAY_RECORDING:
  1119. case HK_EXPORT_RECORDING:
  1120. case HK_READ_ONLY_MODE:
  1121. case HK_LOAD_STATE_FILE:
  1122. case HK_SAVE_STATE_FILE:
  1123. case HK_LOAD_STATE_SLOT_SELECTED:
  1124. if (IsHotkey(i))
  1125. {
  1126. int cmd = GetCmdForHotkey(i);
  1127. if (cmd >= 0)
  1128. {
  1129. wxCommandEvent evt(wxEVT_MENU, cmd);
  1130. wxMenuItem* item = GetMenuBar()->FindItem(cmd);
  1131. if (item && item->IsCheckable())
  1132. {
  1133. item->wxMenuItemBase::Toggle();
  1134. evt.SetInt(item->IsChecked());
  1135. }
  1136. GetEventHandler()->AddPendingEvent(evt);
  1137. }
  1138. }
  1139. default:
  1140. break;
  1141. // do nothing
  1142. }
  1143. }
  1144. if (!Core::IsRunningAndStarted())
  1145. {
  1146. return;
  1147. }
  1148. // Toggle fullscreen
  1149. if (IsHotkey(HK_FULLSCREEN))
  1150. DoFullscreen(!RendererIsFullscreen());
  1151. // Pause and Unpause
  1152. if (IsHotkey(HK_PLAY_PAUSE))
  1153. DoPause();
  1154. // Stop
  1155. if (IsHotkey(HK_STOP))
  1156. DoStop();
  1157. // Screenshot hotkey
  1158. if (IsHotkey(HK_SCREENSHOT))
  1159. Core::SaveScreenShot();
  1160. if (IsHotkey(HK_EXIT))
  1161. wxPostEvent(this, wxCommandEvent(wxID_EXIT));
  1162. if (IsHotkey(HK_VOLUME_DOWN))
  1163. AudioCommon::DecreaseVolume(3);
  1164. if (IsHotkey(HK_VOLUME_UP))
  1165. AudioCommon::IncreaseVolume(3);
  1166. if (IsHotkey(HK_VOLUME_TOGGLE_MUTE))
  1167. AudioCommon::ToggleMuteVolume();
  1168. // Wiimote connect and disconnect hotkeys
  1169. int WiimoteId = -1;
  1170. if (IsHotkey(HK_WIIMOTE1_CONNECT))
  1171. WiimoteId = 0;
  1172. if (IsHotkey(HK_WIIMOTE2_CONNECT))
  1173. WiimoteId = 1;
  1174. if (IsHotkey(HK_WIIMOTE3_CONNECT))
  1175. WiimoteId = 2;
  1176. if (IsHotkey(HK_WIIMOTE4_CONNECT))
  1177. WiimoteId = 3;
  1178. if (IsHotkey(HK_BALANCEBOARD_CONNECT))
  1179. WiimoteId = 4;
  1180. // Actually perform the Wiimote connection or disconnection
  1181. if (WiimoteId >= 0 && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
  1182. {
  1183. wxCommandEvent evt;
  1184. evt.SetId(IDM_CONNECT_WIIMOTE1 + WiimoteId);
  1185. OnConnectWiimote(evt);
  1186. }
  1187. if (IsHotkey(HK_TOGGLE_IR))
  1188. {
  1189. OSDChoice = 1;
  1190. // Toggle native resolution
  1191. if (++g_Config.iEFBScale > 11) // 8X Internal Resolution
  1192. g_Config.iEFBScale = SCALE_AUTO;
  1193. }
  1194. if (IsHotkey(HK_INCREASE_IR))
  1195. {
  1196. OSDChoice = 1;
  1197. ++g_Config.iEFBScale;
  1198. }
  1199. if (IsHotkey(HK_DECREASE_IR))
  1200. {
  1201. OSDChoice = 1;
  1202. if (--g_Config.iEFBScale < SCALE_1X)
  1203. g_Config.iEFBScale = SCALE_1X;
  1204. }
  1205. if (IsHotkey(HK_TOGGLE_AR))
  1206. {
  1207. OSDChoice = 2;
  1208. // Toggle aspect ratio
  1209. g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
  1210. }
  1211. if (IsHotkey(HK_TOGGLE_EFBCOPIES))
  1212. {
  1213. OSDChoice = 3;
  1214. // Toggle EFB copies between EFB2RAM and EFB2Texture
  1215. g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam;
  1216. }
  1217. if (IsHotkey(HK_TOGGLE_FOG))
  1218. {
  1219. OSDChoice = 4;
  1220. g_Config.bDisableFog = !g_Config.bDisableFog;
  1221. }
  1222. Core::SetIsFramelimiterTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true));
  1223. if (IsHotkey(HK_DECREASE_FRAME_LIMIT))
  1224. {
  1225. if (--SConfig::GetInstance().m_Framelimit > 0x19)
  1226. SConfig::GetInstance().m_Framelimit = 0x19;
  1227. }
  1228. if (IsHotkey(HK_INCREASE_FRAME_LIMIT))
  1229. {
  1230. if (++SConfig::GetInstance().m_Framelimit > 0x19)
  1231. SConfig::GetInstance().m_Framelimit = 0;
  1232. }
  1233. if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED))
  1234. {
  1235. State::Save(g_saveSlot);
  1236. }
  1237. if (IsHotkey(HK_LOAD_STATE_SLOT_SELECTED))
  1238. {
  1239. State::Load(g_saveSlot);
  1240. }
  1241. if (IsHotkey(HK_DECREASE_DEPTH, true))
  1242. {
  1243. if (--g_Config.iStereoDepth < 0)
  1244. g_Config.iStereoDepth = 0;
  1245. }
  1246. if (IsHotkey(HK_INCREASE_DEPTH, true))
  1247. {
  1248. if (++g_Config.iStereoDepth > 100)
  1249. g_Config.iStereoDepth = 100;
  1250. }
  1251. if (IsHotkey(HK_DECREASE_CONVERGENCE, true))
  1252. {
  1253. g_Config.iStereoConvergence -= 5;
  1254. if (g_Config.iStereoConvergence < 0)
  1255. g_Config.iStereoConvergence = 0;
  1256. }
  1257. if (IsHotkey(HK_INCREASE_CONVERGENCE, true))
  1258. {
  1259. g_Config.iStereoConvergence += 5;
  1260. if (g_Config.iStereoConvergence > 500)
  1261. g_Config.iStereoConvergence = 500;
  1262. }
  1263. static float debugSpeed = 1.0f;
  1264. if (IsHotkey(HK_FREELOOK_DECREASE_SPEED, true))
  1265. debugSpeed /= 1.1f;
  1266. if (IsHotkey(HK_FREELOOK_INCREASE_SPEED, true))
  1267. debugSpeed *= 1.1f;
  1268. if (IsHotkey(HK_FREELOOK_RESET_SPEED, true))
  1269. debugSpeed = 1.0f;
  1270. if (IsHotkey(HK_FREELOOK_UP, true))
  1271. VertexShaderManager::TranslateView(0.0f, 0.0f, -debugSpeed);
  1272. if (IsHotkey(HK_FREELOOK_DOWN, true))
  1273. VertexShaderManager::TranslateView(0.0f, 0.0f, debugSpeed);
  1274. if (IsHotkey(HK_FREELOOK_LEFT, true))
  1275. VertexShaderManager::TranslateView(debugSpeed, 0.0f);
  1276. if (IsHotkey(HK_FREELOOK_RIGHT, true))
  1277. VertexShaderManager::TranslateView(-debugSpeed, 0.0f);
  1278. if (IsHotkey(HK_FREELOOK_ZOOM_IN, true))
  1279. VertexShaderManager::TranslateView(0.0f, debugSpeed);
  1280. if (IsHotkey(HK_FREELOOK_ZOOM_OUT, true))
  1281. VertexShaderManager::TranslateView(0.0f, -debugSpeed);
  1282. if (IsHotkey(HK_FREELOOK_RESET, true))
  1283. VertexShaderManager::ResetView();
  1284. // Savestates
  1285. for (int i = 0; i < 10; i++)
  1286. {
  1287. if (IsHotkey(HK_LOAD_STATE_SLOT_1 + i))
  1288. State::Load(1 + i);
  1289. if (IsHotkey(HK_SAVE_STATE_SLOT_1 + i))
  1290. State::Save(1 + i);
  1291. if (IsHotkey(HK_LOAD_LAST_STATE_1 + i))
  1292. State::LoadLastSaved(1 + i);
  1293. if (IsHotkey(HK_SELECT_STATE_SLOT_1 + i))
  1294. {
  1295. wxCommandEvent slot_event;
  1296. slot_event.SetId(IDM_SELECT_SLOT_1 + i);
  1297. CFrame::OnSelectSlot(slot_event);
  1298. }
  1299. }
  1300. if (IsHotkey(HK_SAVE_FIRST_STATE))
  1301. State::SaveFirstSaved();
  1302. if (IsHotkey(HK_UNDO_LOAD_STATE))
  1303. State::UndoLoadState();
  1304. if (IsHotkey(HK_UNDO_SAVE_STATE))
  1305. State::UndoSaveState();
  1306. }