// Copyright (C) 2003 Dolphin Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ // CFrame is the main parent window. Inside CFrame there is an m_Panel that is the parent for // the rendering window (when we render to the main window). In Windows the rendering window is // created by giving CreateWindow() m_Panel->GetHandle() as parent window and creating a new // child window to m_Panel. The new child window handle that is returned by CreateWindow() can // be accessed from Core::GetWindowHandle(). // ---------- // Includes #include "Common.h" // Common #include "FileUtil.h" #include "Timer.h" #include "Setup.h" #include "Globals.h" // Local #include "Frame.h" #include "ConfigMain.h" #include "PluginManager.h" #include "MemcardManager.h" #include "CheatsWindow.h" #include "AboutDolphin.h" #include "GameListCtrl.h" #include "BootManager.h" #include "ConsoleListener.h" #include "ConfigManager.h" // Core #include "Core.h" #include "HW/DVDInterface.h" #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "State.h" #include "VolumeHandler.h" #include // wxWidgets // Resources extern "C" { #include "../resources/Dolphin.c" // Dolphin icon #include "../resources/toolbar_browse.c" #include "../resources/toolbar_file_open.c" #include "../resources/toolbar_fullscreen.c" #include "../resources/toolbar_help.c" #include "../resources/toolbar_pause.c" #include "../resources/toolbar_play.c" #include "../resources/toolbar_plugin_dsp.c" #include "../resources/toolbar_plugin_gfx.c" #include "../resources/toolbar_plugin_options.c" #include "../resources/toolbar_plugin_pad.c" #include "../resources/toolbar_refresh.c" #include "../resources/toolbar_stop.c" #include "../resources/Boomy.h" // Theme packages #include "../resources/Vista.h" #include "../resources/X-Plastik.h" #include "../resources/KDE.h" }; // Windows functions. Setting the cursor with wxSetCursor() did not work in // this instance. Probably because it's somehow reset from the WndProc() in // the child window #ifdef _WIN32 // Declare a blank icon and one that will be the normal cursor HCURSOR hCursor = NULL, hCursorBlank = NULL; // Create the default cursor void CreateCursor() { hCursor = LoadCursor( NULL, IDC_ARROW ); } void MSWSetCursor(bool Show) { if(Show) SetCursor(hCursor); else { SetCursor(hCursorBlank); //wxSetCursor(wxCursor(wxNullCursor)); } } // I could not use FindItemByHWND() instead of this, it crashed on that occation I used it */ HWND MSWGetParent_(HWND Parent) { return GetParent(Parent); } #endif // --------------- // The CPanel class to receive MSWWindowProc messages from the video plugin. extern CFrame* main_frame; class CPanel : public wxPanel { public: CPanel( wxWindow* parent, wxWindowID id = wxID_ANY ); private: DECLARE_EVENT_TABLE(); #ifdef _WIN32 // Receive WndProc messages WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); #endif }; BEGIN_EVENT_TABLE(CPanel, wxPanel) END_EVENT_TABLE() CPanel::CPanel( wxWindow *parent, wxWindowID id ) : wxPanel(parent, id) { } #ifdef _WIN32 WXLRESULT CPanel::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { switch (nMsg) { case WM_USER: switch(wParam) { // Stop case WM_USER_STOP: main_frame->DoStop(); return 0; case WM_USER_CREATE: // We don't have a local setting for bRenderToMain but we can detect it this way instead //PanicAlert("main call %i %i %i %i", lParam, (HWND)Core::GetWindowHandle(), MSWGetParent_((HWND)Core::GetWindowHandle()), (HWND)this->GetHWND()); if (lParam == NULL) main_frame->bRenderToMain = false; else main_frame->bRenderToMain = true; return 0; case WIIMOTE_DISCONNECT: if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { if (main_frame->bNoWiimoteMsg) main_frame->bNoWiimoteMsg = false; else { // The Wiimote has been disconnect, we offer reconnect here wxMessageDialog *dlg = new wxMessageDialog( this, wxString::Format(wxT("Wiimote %i has been disconnected by system.\n") wxT("Maybe this game doesn't support multi-wiimote,\n") wxT("or maybe it is due to idle time out or other reason.\n\n") wxT("Do you want to reconnect immediately?"), lParam + 1), wxT("Reconnect Wiimote Confirm"), wxYES_NO | wxSTAY_ON_TOP | wxICON_INFORMATION, //wxICON_QUESTION, wxDefaultPosition); if (dlg->ShowModal() == wxID_YES) GetUsbPointer()->AccessWiiMote(lParam | 0x100)->Activate(true); dlg->Destroy(); } } return 0; } break; } // By default let wxWidgets do what it normally does with this event return wxPanel::MSWWindowProc(nMsg, wParam, lParam); } #endif // event tables // Notice that wxID_HELP will be processed for the 'About' menu and the toolbar // help button. const wxEventType wxEVT_HOST_COMMAND = wxNewEventType(); BEGIN_EVENT_TABLE(CFrame, wxFrame) // Menu bar EVT_MENU(wxID_OPEN, CFrame::OnOpen) EVT_MENU(wxID_EXIT, CFrame::OnQuit) EVT_MENU(IDM_HELPWEBSITE, CFrame::OnHelp) EVT_MENU(IDM_HELPGOOGLECODE, CFrame::OnHelp) EVT_MENU(IDM_HELPABOUT, CFrame::OnHelp) EVT_MENU(wxID_REFRESH, CFrame::OnRefresh) EVT_MENU(IDM_PLAY, CFrame::OnPlay) EVT_MENU(IDM_STOP, CFrame::OnStop) EVT_MENU(IDM_RESET, CFrame::OnReset) EVT_MENU(IDM_RECORD, CFrame::OnRecord) EVT_MENU(IDM_PLAYRECORD, CFrame::OnPlayRecording) EVT_MENU(IDM_FRAMESTEP, CFrame::OnFrameStep) EVT_MENU(IDM_LUA, CFrame::OnOpenLuaWindow) EVT_MENU(IDM_SCREENSHOT, CFrame::OnScreenshot) EVT_MENU(IDM_CONFIG_MAIN, CFrame::OnConfigMain) EVT_MENU(IDM_CONFIG_GFX_PLUGIN, CFrame::OnPluginGFX) EVT_MENU(IDM_CONFIG_DSP_PLUGIN, CFrame::OnPluginDSP) EVT_MENU(IDM_CONFIG_PAD_PLUGIN, CFrame::OnPluginPAD) EVT_MENU(IDM_CONFIG_WIIMOTE_PLUGIN, CFrame::OnPluginWiimote) EVT_MENU(IDM_SAVE_PERSPECTIVE, CFrame::OnToolBar) EVT_AUITOOLBAR_TOOL_DROPDOWN(IDM_SAVE_PERSPECTIVE, CFrame::OnDropDownToolbarItem) EVT_MENU(IDM_EDIT_PERSPECTIVES, CFrame::OnToolBar) EVT_AUITOOLBAR_TOOL_DROPDOWN(IDM_EDIT_PERSPECTIVES, CFrame::OnDropDownSettingsToolbar) // Drop down EVT_MENU(IDM_PERSPECTIVES_ADD_PANE, CFrame::OnToolBar) EVT_MENU_RANGE(IDM_PERSPECTIVES_0, IDM_PERSPECTIVES_100, CFrame::OnSelectPerspective) EVT_MENU(IDM_ADD_PERSPECTIVE, CFrame::OnDropDownToolbarSelect) EVT_MENU(IDM_TAB_SPLIT, CFrame::OnDropDownToolbarSelect) EVT_MENU(IDM_NO_DOCKING, CFrame::OnDropDownToolbarSelect) // Drop down float EVT_MENU(IDM_FLOAT_LOGWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_CONSOLEWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_CODEWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_REGISTERWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_BREAKPOINTWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_MEMORYWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_JITWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_SOUNDWINDOW, CFrame::OnFloatWindow) EVT_MENU(IDM_FLOAT_VIDEOWINDOW, CFrame::OnFloatWindow) #if defined(HAVE_SFML) && HAVE_SFML EVT_MENU(IDM_NETPLAY, CFrame::OnNetPlay) #endif EVT_MENU(IDM_BROWSE, CFrame::OnBrowse) EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard) EVT_MENU(IDM_IMPORTSAVE, CFrame::OnImportSave) EVT_MENU(IDM_CHEATS, CFrame::OnShow_CheatsWindow) EVT_MENU(IDM_CHANGEDISC, CFrame::OnChangeDisc) EVT_MENU(IDM_LOAD_WII_MENU, CFrame::OnLoadWiiMenu) EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen) EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore) EVT_MENU(IDM_TOGGLE_SKIPIDLE, CFrame::OnToggleSkipIdle) EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar) EVT_MENU(IDM_TOGGLE_STATUSBAR, CFrame::OnToggleStatusbar) EVT_MENU(IDM_LOGWINDOW, CFrame::OnToggleLogWindow) EVT_MENU(IDM_CONSOLEWINDOW, CFrame::OnToggleConsole) EVT_MENU(IDM_PURGECACHE, CFrame::GameListChanged) EVT_MENU(IDM_LOADLASTSTATE, CFrame::OnLoadLastState) EVT_MENU(IDM_UNDOLOADSTATE, CFrame::OnUndoLoadState) EVT_MENU(IDM_UNDOSAVESTATE, CFrame::OnUndoSaveState) EVT_MENU(IDM_LOADSTATEFILE, CFrame::OnLoadStateFromFile) EVT_MENU(IDM_SAVESTATEFILE, CFrame::OnSaveStateToFile) EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT8, CFrame::OnLoadState) EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT8, CFrame::OnSaveState) EVT_MENU_RANGE(IDM_FRAMESKIP0, IDM_FRAMESKIP9, CFrame::OnFrameSkip) EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive) EVT_MENU_RANGE(IDM_CONNECT_WIIMOTE1, IDM_CONNECT_WIIMOTE4, CFrame::OnConnectWiimote) EVT_MENU_RANGE(IDM_LISTWAD, IDM_LISTDRIVES, CFrame::GameListChanged) // Other EVT_ACTIVATE(CFrame::OnActive) EVT_CLOSE(CFrame::OnClose) EVT_SIZE(CFrame::OnResize) EVT_MOVE(CFrame::OnMove) EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, CFrame::OnGameListCtrl_ItemActivated) EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage) #if wxUSE_TIMER EVT_TIMER(wxID_ANY, CFrame::OnTimer) #endif EVT_AUI_PANE_CLOSE(CFrame::OnPaneClose) EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, CFrame::OnNotebookPageClose) EVT_AUINOTEBOOK_ALLOW_DND(wxID_ANY, CFrame::OnAllowNotebookDnD) EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, CFrame::OnNotebookPageChanged) EVT_AUINOTEBOOK_TAB_RIGHT_UP(wxID_ANY, CFrame::OnTab) // Post events to child panels EVT_MENU(wxID_ANY, CFrame::PostEvent) EVT_TEXT(wxID_ANY, CFrame::PostEvent) //EVT_MENU_HIGHLIGHT_ALL(CFrame::PostMenuEvent) //EVT_UPDATE_UI(wxID_ANY, CFrame::PostUpdateUIEvent) END_EVENT_TABLE() // --------------- // Creation and close, quit functions CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, bool _UseDebugger, bool ShowLogWindow, long style) : wxFrame(parent, id, title, pos, size, style) , g_pCodeWindow(NULL) , m_MenuBar(NULL) , m_LogWindow(NULL) , m_ToolBar(NULL), m_ToolBarDebug(NULL), m_ToolBarAui(NULL) , m_pStatusBar(NULL), m_GameListCtrl(NULL), m_Panel(NULL) , UseDebugger(_UseDebugger), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) , bRenderToMain(false), bFloatLogWindow(false), bFloatConsoleWindow(false) , HaveLeds(false), HaveSpeakers(false) , m_bControlsCreated(false), m_bModalDialogOpen(false), bNoWiimoteMsg(false), m_StopDlg(NULL) #if wxUSE_TIMER #ifdef _WIN32 , m_fLastClickTime(0), m_iLastMotionTime(0), LastMouseX(0), LastMouseY(0) #endif , m_timer(this) #endif { if (ShowLogWindow) SConfig::GetInstance().m_InterfaceLogWindow = true; // Give it a console early to show potential messages from this onward ConsoleListener *Console = LogManager::GetInstance()->getConsoleListener(); if (SConfig::GetInstance().m_InterfaceConsole) Console->Open(); if (SConfig::GetInstance().m_InterfaceLogWindow) m_LogWindow = new CLogWindow(this, IDM_LOGWINDOW); // Start debugging mazimized if (UseDebugger) this->Maximize(true); // Debugger class if (UseDebugger) { g_pCodeWindow = new CCodeWindow(SConfig::GetInstance().m_LocalCoreStartupParameter, this, IDM_CODEWINDOW); g_pCodeWindow->Hide(); g_pCodeWindow->Load(); } // Create timer #if wxUSE_TIMER int TimesPerSecond = 10; // We don't need more than this m_timer.Start( floor((double)(1000 / TimesPerSecond)) ); #endif // Create toolbar bitmaps InitBitmaps(); // Give it an icon wxIcon IconTemp; IconTemp.CopyFromBitmap(wxGetBitmapFromMemory(dolphin_ico32x32)); SetIcon(IconTemp); // Give it a status bar m_pStatusBar = CreateStatusBar(1, wxST_SIZEGRIP, ID_STATUSBAR); if (!SConfig::GetInstance().m_InterfaceStatusbar) m_pStatusBar->Hide(); // Give it a menu bar CreateMenu(); // --------------- // Main panel // This panel is the parent for rendering and it holds the gamelistctrl m_Panel = new CPanel(this, IDM_MPANEL); m_GameListCtrl = new CGameListCtrl(m_Panel, LIST_CTRL, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT); sizerPanel = new wxBoxSizer(wxHORIZONTAL); sizerPanel->Add(m_GameListCtrl, 1, wxEXPAND | wxALL); m_Panel->SetSizer(sizerPanel); // --------------- // Manager #ifdef _WIN32 m_Mgr = new wxAuiManager(this, wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE); #else // wxAUI_MGR_LIVE_RESIZE does not exist in the wxWidgets 2.8 that comes with the latest ubuntu. m_Mgr = new wxAuiManager(this, wxAUI_MGR_DEFAULT); #endif NOTEBOOK_STYLE = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON | wxNO_BORDER; TOOLBAR_STYLE = wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_TEXT /*wxAUI_TB_OVERFLOW overflow visible*/; wxBitmap aNormalFile = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, wxSize(16,16)); if (g_pCodeWindow) { m_Mgr->AddPane(m_Panel, wxAuiPaneInfo().Name(wxT("Pane 0")).Caption(wxT("Pane 0")).Show()); } else { m_Mgr->AddPane(m_Panel, wxAuiPaneInfo().Name(wxT("Pane 0")).Caption(wxT("Pane 0")).Hide()); m_Mgr->AddPane(CreateEmptyNotebook(), wxAuiPaneInfo().Name(wxT("Pane 1")).Caption(wxT("Logging")).Hide()); } // Setup perspectives if (g_pCodeWindow) { m_Mgr->GetPane(wxT("Pane 0")).CenterPane().PaneBorder(false); AuiFullscreen = m_Mgr->SavePerspective(); m_Mgr->GetPane(wxT("Pane 0")).CenterPane().PaneBorder(true); } else { IniFile ini; int pos; ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX)); ini.Get("LogWindow", "pos", &pos, 2); m_Mgr->GetPane(wxT("Pane 0")).Show().PaneBorder(false).CaptionVisible(false).Layer(0).Center(); m_Mgr->GetPane(wxT("Pane 1")).Hide().PaneBorder(false).CaptionVisible(true).Layer(0) .FloatingSize(wxSize(600, 350)).CloseButton(false).Direction(pos); AuiFullscreen = m_Mgr->SavePerspective(); } // Create toolbar RecreateToolbar(); if (!SConfig::GetInstance().m_InterfaceToolbar) DoToggleToolbar(false); // Create list of available plugins for the configuration window CPluginManager::GetInstance().ScanForPlugins(); // Setup perspectives if (g_pCodeWindow) { // Load perspective SaveLocal(); DoLoadPerspective(); } else { SetSimplePaneSize(); if (SConfig::GetInstance().m_InterfaceLogWindow) DoToggleWindow(IDM_LOGWINDOW, true); if (SConfig::GetInstance().m_InterfaceConsole) DoToggleWindow(IDM_CONSOLEWINDOW, true); } // Show window Show(); // Commit m_Mgr->Update(); // Create cursors #ifdef _WIN32 CreateCursor(); #endif // ------------------------- // Connect event handlers wxTheApp->Connect(wxID_ANY, wxEVT_SIZE, // Keyboard wxSizeEventHandler(CFrame::OnResizeAll), (wxObject*)0, this); wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard wxKeyEventHandler(CFrame::OnKeyDown), (wxObject*)0, this); wxTheApp->Connect(wxID_ANY, wxEVT_KEY_UP, wxKeyEventHandler(CFrame::OnKeyUp), (wxObject*)0, this); m_Mgr->Connect(wxID_ANY, wxEVT_AUI_RENDER, // Resize wxAuiManagerEventHandler(CFrame::OnManagerResize), (wxObject*)0, this); wxTheApp->Connect(wxID_ANY, wxEVT_LEFT_DCLICK, wxMouseEventHandler(CFrame::OnDoubleClick), (wxObject*)0, this); #ifdef _WIN32 wxTheApp->Connect(wxID_ANY, wxEVT_MOTION, wxMouseEventHandler(CFrame::OnMotion), (wxObject*)0, this); #endif // ---------- // Update controls m_bControlsCreated = true; UpdateGUI(); //if we are ever going back to optional iso caching: //m_GameListCtrl->Update(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableIsoCache); if (m_GameListCtrl) m_GameListCtrl->Update(); // If we are rerecording create the status bar now instead of later when a game starts #ifdef RERECORDING ModifyStatusBar(); // It's to early for the OnHostMessage(), we will update the status when Ctrl or Space is pressed //Core::WriteStatus(); #endif } // Destructor CFrame::~CFrame() { m_bControlsCreated = false; cdio_free_device_list(drives); /* The statbar sample has this so I add this to, but I guess timer will be deleted after this anyway */ #if wxUSE_TIMER if (m_timer.IsRunning()) m_timer.Stop(); #endif ClosePages(); } void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) { Close(true); } // -------- // Events void CFrame::OnActive(wxActivateEvent& event) { event.Skip(); } void CFrame::OnClose(wxCloseEvent& event) { //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) Save(); // Uninit m_Mgr->UnInit(); if (Core::GetState() != Core::CORE_UNINITIALIZED) { Core::Stop(); UpdateGUI(); } } // Post events // Warning: This may cause an endless loop if the event is propagated back to its parent void CFrame::PostEvent(wxCommandEvent& event) { if (g_pCodeWindow && event.GetId() >= IDM_INTERPRETER && event.GetId() <= IDM_ADDRBOX //&& event.GetId() != IDM_JITUNLIMITED ) { event.StopPropagation(); g_pCodeWindow->GetEventHandler()->AddPendingEvent(event); } else event.Skip(); } void CFrame::PostMenuEvent(wxMenuEvent& event) { if (g_pCodeWindow) g_pCodeWindow->GetEventHandler()->AddPendingEvent(event); } void CFrame::PostUpdateUIEvent(wxUpdateUIEvent& event) { if (g_pCodeWindow) g_pCodeWindow->GetEventHandler()->AddPendingEvent(event); } void CFrame::OnMove(wxMoveEvent& event) { event.Skip(); SConfig::GetInstance().m_LocalCoreStartupParameter.iPosX = GetPosition().x; SConfig::GetInstance().m_LocalCoreStartupParameter.iPosY = GetPosition().y; } void CFrame::OnResize(wxSizeEvent& event) { event.Skip(); SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth = GetSize().GetWidth(); SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight = GetSize().GetHeight(); DoMoveIcons(); // In FrameWiimote.cpp } void CFrame::OnResizeAll(wxSizeEvent& event) { event.Skip(); //wxWindow * Win = (wxWindow*)event.GetEventObject(); //NOTICE_LOG(CONSOLE, "OnResizeAll: %i", (HWND)Win->GetHWND()); } // Host messages #ifdef _WIN32 WXLRESULT CFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { switch (nMsg) { case WM_SYSCOMMAND: switch (wParam & 0xFFF0) { case SC_SCREENSAVE: case SC_MONITORPOWER: return 0; } } return wxFrame::MSWWindowProc(nMsg, wParam, lParam); } #endif void CFrame::OnTimer(wxTimerEvent& WXUNUSED(event)) { #ifdef _WIN32 Update(); #else // Process events in linux. Primarily to update the statusbar text. // This should be unnecessary if we ever get WXGL and render to main working if (wxGetApp().Pending()) wxGetApp().ProcessPendingEvents(); #endif } void CFrame::OnHostMessage(wxCommandEvent& event) { switch (event.GetId()) { case IDM_UPDATEGUI: UpdateGUI(); break; case IDM_UPDATESTATUSBAR: if (m_pStatusBar != NULL) { m_pStatusBar->SetStatusText(event.GetString(), event.GetInt()); } break; #if defined(HAVE_X11) && HAVE_X11 case WM_USER_STOP: main_frame->DoStop(); break; #endif } } void CFrame::OnCustomHostMessage(int Id) { wxWindow *Win; switch(Id) { // Destroy windows case AUDIO_DESTROY: Win = GetWxWindow(wxT("Sound")); if (Win) { DoRemovePage(Win, false); CPluginManager::GetInstance().OpenDebug( GetHandle(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(), PLUGIN_TYPE_DSP, false ); //Win->Reparent(NULL); //g_pCodeWindow->OnToggleDLLWindow(false, 0); GetMenuBar()->FindItem(IDM_SOUNDWINDOW)->Check(false); NOTICE_LOG(CONSOLE, "%s", Core::StopMessage(true, "Sound debugging window closed").c_str()); } break; case VIDEO_DESTROY: break; } } void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) { // 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->GetGameNames().size() && !((SConfig::GetInstance().m_ListGC && SConfig::GetInstance().m_ListWii && SConfig::GetInstance().m_ListWad) && (SConfig::GetInstance().m_ListJap && SConfig::GetInstance().m_ListUsa && SConfig::GetInstance().m_ListPal && SConfig::GetInstance().m_ListFrance && SConfig::GetInstance().m_ListItaly && SConfig::GetInstance().m_ListKorea && SConfig::GetInstance().m_ListTaiwan && SConfig::GetInstance().m_ListUnknown))) { SConfig::GetInstance().m_ListGC = SConfig::GetInstance().m_ListWii = SConfig::GetInstance().m_ListWad = SConfig::GetInstance().m_ListJap = SConfig::GetInstance().m_ListUsa = SConfig::GetInstance().m_ListPal = SConfig::GetInstance().m_ListFrance = SConfig::GetInstance().m_ListItaly = SConfig::GetInstance().m_ListKorea = SConfig::GetInstance().m_ListTaiwan = SConfig::GetInstance().m_ListUnknown= true; GetMenuBar()->FindItem(IDM_LISTGC)->Check(true); GetMenuBar()->FindItem(IDM_LISTWII)->Check(true); GetMenuBar()->FindItem(IDM_LISTWAD)->Check(true); GetMenuBar()->FindItem(IDM_LISTJAP)->Check(true); GetMenuBar()->FindItem(IDM_LISTUSA)->Check(true); GetMenuBar()->FindItem(IDM_LISTPAL)->Check(true); GetMenuBar()->FindItem(IDM_LISTFRANCE)->Check(true); GetMenuBar()->FindItem(IDM_LISTITALY)->Check(true); GetMenuBar()->FindItem(IDM_LISTKOREA)->Check(true); GetMenuBar()->FindItem(IDM_LISTTAIWAN)->Check(true); GetMenuBar()->FindItem(IDM_LIST_UNK)->Check(true); m_GameListCtrl->Update(); } else // Game started by double click StartGame(std::string("")); } void CFrame::OnKeyDown(wxKeyEvent& event) { // Toggle fullscreen if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT)) { DoFullscreen(!IsFullScreen()); // We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen) event.StopPropagation(); } // event.Skip() allows the event to propagate to the gamelist for example else if (! (Core::GetState() == Core::CORE_RUN && bRenderToMain && event.GetEventObject() == this)) event.Skip(); #ifdef _WIN32 if(event.GetKeyCode() == 'M', '3', '4', '5', '6', '7') // Send this to the video plugin WndProc { PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode()); } #endif // Send the keyboard status to the Input plugin if(Core::GetState() != Core::CORE_UNINITIALIZED) CPluginManager::GetInstance().GetPad(0)->PAD_Input(event.GetKeyCode(), 1); // 1 = Down } void CFrame::OnKeyUp(wxKeyEvent& event) { event.Skip(); if(Core::GetState() != Core::CORE_UNINITIALIZED) CPluginManager::GetInstance().GetPad(0)->PAD_Input(event.GetKeyCode(), 0); // 0 = Up } // --------------- // Detect double click void CFrame::OnDoubleClick(wxMouseEvent& event) { // Don't block the mouse click event.Skip(); // Don't use this in Wii mode since we use the mouse as input to the game there if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) return; // Only detect double clicks in the rendering window, and only use this when a game is running if (! (Core::GetState() == Core::CORE_RUN && bRenderToMain && event.GetEventObject() == m_Panel)) return; DoFullscreen(!IsFullScreen()); } // Check for mouse motion. Here we process the bHideCursor setting. #if wxUSE_TIMER && defined _WIN32 void CFrame::OnMotion(wxMouseEvent& event) { event.Skip(); // The following is only interesting when a game is running if(Core::GetState() == Core::CORE_UNINITIALIZED) return; /* For some reason WM_MOUSEMOVE events are sent from the plugin even when there is no movement so we have to check that the cursor position has actually changed */ if(bRenderToMain) // { bool PositionIdentical = false; if (event.GetX() == LastMouseX && event.GetY() == LastMouseY) PositionIdentical = true; LastMouseX = event.GetX(); LastMouseY = event.GetY(); if(PositionIdentical) return; } // Now we know that we have an actual mouse movement event // Update motion for the auto hide option and return if(IsFullScreen() && SConfig::GetInstance().m_LocalCoreStartupParameter.bAutoHideCursor) { m_iLastMotionTime = Common::Timer::GetDoubleTime(); MSWSetCursor(true); return; } if(SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor && event.GetId() == IDM_MPANEL) { if(bRenderToMain) MSWSetCursor(false); /* We only need to use this if we are rendering to a separate window. It does work for rendering to the main window to, but in that case our MSWSetCursor() works to so we can use that instead. If we one day determine that the separate window rendering is superfluous we could do without this */ else PostMessage((HWND)Core::GetWindowHandle(), WM_USER, 10, 0); } // For some reason we need this to, otherwise the cursor can get stuck with the resizing arrows else { if(bRenderToMain) MSWSetCursor(true); else PostMessage((HWND)Core::GetWindowHandle(), WM_USER, 10, 1); } } #endif // Check for mouse status a couple of times per second for the auto hide option #if wxUSE_TIMER && defined _WIN32 void CFrame::Update() { // Check if auto hide is on, or if we are already hiding the cursor all the time if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bAutoHideCursor || SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) return; if(IsFullScreen()) { int HideDelay = 1; // Wait 1 second to hide the cursor, just like Windows Media Player double TmpSeconds = Common::Timer::GetDoubleTime(); // Get timestamp double CompareTime = TmpSeconds - HideDelay; // Compare it if(m_iLastMotionTime < CompareTime) // Update cursor MSWSetCursor(false); } } #endif // -------- // Functions wxFrame * CFrame::CreateParentFrame(wxWindowID Id, const wxString& Title, wxWindow * Child) { wxFrame * Frame = new wxFrame(this, Id, Title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE); Child->Reparent(Frame); Child->Show(); wxBoxSizer * m_MainSizer = new wxBoxSizer(wxHORIZONTAL); m_MainSizer->Add(Child, 1, wxEXPAND); Frame->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(CFrame::OnFloatingPageClosed), (wxObject*)0, this); if (Id == IDM_CONSOLEWINDOW_PARENT) { Frame->Connect(wxID_ANY, wxEVT_SIZE, wxSizeEventHandler(CFrame::OnFloatingPageSize), (wxObject*)0, this); } // Main sizer Frame->SetSizer( m_MainSizer ); // Minimum frame size Frame->SetMinSize(wxSize(200, -1)); Frame->Show(); return Frame; } wxPanel* CFrame::CreateEmptyPanel(wxWindowID Id) { wxPanel* Panel = new wxPanel(this, Id); return Panel; } wxAuiNotebook* CFrame::CreateEmptyNotebook() { wxAuiNotebook* NB = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, NOTEBOOK_STYLE); return NB; } void CFrame::DoFullscreen(bool bF) { // Only switch this to fullscreen if we're rendering to main AND if we're running a game // plus if a modal dialog is open, this will still process the keyboard events, and may cause // the main window to become unresponsive, so we have to avoid that. if ((bRenderToMain && Core::GetState() == Core::CORE_RUN) && !m_bModalDialogOpen) { ShowFullScreen(bF); if (bF) { // Save the current mode before going to fullscreen AuiCurrent = m_Mgr->SavePerspective(); m_Mgr->LoadPerspective(AuiFullscreen, true); } else { // Restore saved perspective m_Mgr->LoadPerspective(AuiCurrent, true); } // Show the cursor again, in case it was hidden if (IsFullScreen()) { #ifdef _WIN32 MSWSetCursor(true); #endif } } #ifdef _WIN32 else // Post the message to the separate rendering window which will then handle it. PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0); #endif } // Debugging, show loose windows void CFrame::ListChildren() { ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener(); wxAuiNotebook * NB = NULL; Console->Log(LogTypes::LNOTICE, "--------------------------------------------------------------------\n"); for (u32 i = 0; i < this->GetChildren().size(); i++) { wxWindow * Win = this->GetChildren().Item(i)->GetData(); Console->Log(LogTypes::LNOTICE, StringFromFormat( "%i: %s (%s) :: %s", i, (const char*)Win->GetName().mb_str(), (const char*)Win->GetLabel().mb_str(), (const char*)Win->GetParent()->GetName().mb_str()).c_str()); //if (Win->GetName().IsSameAs(wxT("control"))) if (Win->IsKindOf(CLASSINFO(wxAuiNotebook))) { NB = (wxAuiNotebook*)Win; Console->Log(LogTypes::LNOTICE, StringFromFormat(" :: NB", (const char*)NB->GetName().mb_str()).c_str()); } else { NB = NULL; } Console->Log(LogTypes::LNOTICE, StringFromFormat("\n").c_str()); Win = this->GetChildren().Item(i)->GetData(); for (u32 j = 0; j < Win->GetChildren().size(); j++) { Console->Log(LogTypes::LNOTICE, StringFromFormat( " %i.%i: %s (%s) :: %s", i, j, (const char*)Win->GetName().mb_str(), (const char*)Win->GetLabel().mb_str(), (const char*)Win->GetParent()->GetName().mb_str()).c_str()); if (NB) { if (j < NB->GetPageCount()) Console->Log(LogTypes::LNOTICE, StringFromFormat(" :: %s", (const char*)NB->GetPage(j)->GetName().mb_str()).c_str()); } Console->Log(LogTypes::LNOTICE, StringFromFormat("\n").c_str()); /* Win = this->GetChildren().Item(j)->GetData(); for (int k = 0; k < Win->GetChildren().size(); k++) { Console->Log(LogTypes::LNOTICE, StringFromFormat( " %i.%i.%i: %s (%s) :: %s\n", i, j, k, Win->GetName().mb_str(), Win->GetLabel().mb_str(), Win->GetParent()->GetName().mb_str()).c_str()); } */ } } Console->Log(LogTypes::LNOTICE, "--------------------------------------------------------------------\n"); for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) continue; wxAuiNotebook * _NB = (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; Console->Log(LogTypes::LNOTICE, StringFromFormat("%i: %s\n", i, (const char *)m_Mgr->GetAllPanes().Item(i).name.mb_str()).c_str()); for (u32 j = 0; j < _NB->GetPageCount(); j++) { Console->Log(LogTypes::LNOTICE, StringFromFormat("%i.%i: %s\n", i, j, (const char *)_NB->GetPageText(j).mb_str()).c_str()); } } Console->Log(LogTypes::LNOTICE, "--------------------------------------------------------------------\n"); } void CFrame::ListTopWindows() { wxWindowList::const_iterator i; int j = 0; const wxWindowList::const_iterator end = wxTopLevelWindows.end(); for (i = wxTopLevelWindows.begin(); i != end; ++i) { wxTopLevelWindow * const Win = wx_static_cast(wxTopLevelWindow *, *i); NOTICE_LOG(CONSOLE, "%i: %i %s", j, Win, (const char *)Win->GetTitle().mb_str()); /* if ( win->ShouldPreventAppExit() ) { // there remains at least one important TLW, don't exit return false; } */ j++; } NOTICE_LOG(CONSOLE, "\n"); }