// 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(). #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 #if defined HAVE_X11 && HAVE_X11 #include #endif // 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) { // Pause case WM_USER_PAUSE: main_frame->DoPause(); break; // Stop case WM_USER_STOP: main_frame->DoStop(); break; 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; break; case WIIMOTE_DISCONNECT: if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { if (main_frame->bNoWiimoteMsg) main_frame->bNoWiimoteMsg = false; else { int wiimote_idx = lParam; int wiimote_num = wiimote_idx + 1; //Auto reconnect if option is turned on. //TODO: Make this only auto reconnect wiimotes that have the option activated. SConfig::GetInstance().LoadSettingsWii();//Make sure we are using the newest settings. if (SConfig::GetInstance().m_WiiAutoReconnect[wiimote_idx]) { GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); NOTICE_LOG(WIIMOTE, "Wiimote %i has been auto-reconnected...", wiimote_num); } else { // The Wiimote has been disconnected, 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?"), wiimote_num), wxT("Reconnect Wiimote Confirm"), wxYES_NO | wxSTAY_ON_TOP | wxICON_INFORMATION, //wxICON_QUESTION, wxDefaultPosition); if (dlg->ShowModal() == wxID_YES) GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); dlg->Destroy(); } } } } break; default: // By default let wxWidgets do what it normally does with this event return wxPanel::MSWWindowProc(nMsg, wParam, lParam); } return 0; } #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) EVT_MENU(IDM_NETPLAY, CFrame::OnNetPlay) 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) , bRenderToMain(false), bNoWiimoteMsg(false) , m_ToolBar(NULL), m_ToolBarDebug(NULL), m_ToolBarAui(NULL) , bFloatLogWindow(false), bFloatConsoleWindow(false) , m_pStatusBar(NULL), m_GameListCtrl(NULL), m_Panel(NULL) , m_LogWindow(NULL) , UseDebugger(_UseDebugger), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) , m_bControlsCreated(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 // wxAUI_MGR_LIVE_RESIZE does not exist in the wxWidgets 2.8.9 that comes with Ubuntu 9.04 // Could just check for wxWidgets version if it becomes a problem. m_Mgr = new wxAuiManager(this, wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE); 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*/; 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 winpos; ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX)); ini.Get("LogWindow", "pos", &winpos, 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(winpos); 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; drives.clear(); /* 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(); delete m_Mgr; } void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) { Close(true); } #if defined HAVE_X11 && HAVE_X11 void CFrame::X11_SendClientEvent(const char *message) { XEvent event; Display *dpy = (Display *)Core::GetWindowHandle(); Window win = *(Window *)Core::GetXWindow(); // Init X event structure for client message event.xclient.type = ClientMessage; event.xclient.format = 32; event.xclient.data.l[0] = XInternAtom(dpy, message, False); // Send the event if (!XSendEvent(dpy, win, False, False, &event)) ERROR_LOG(VIDEO, "Failed to send message %s to the emulator window.\n", message); } void X11_SendKeyEvent(int key) { XEvent event; Display *dpy = (Display *)Core::GetWindowHandle(); Window win = *(Window *)Core::GetXWindow(); // Init X event structure for key press event event.xkey.type = KeyPress; // WARNING: This works for '3' to '7'. If in the future other keys are needed // convert with InputCommon::wxCharCodeWXToX from X11InputBase.cpp. event.xkey.keycode = XKeysymToKeycode(dpy, key); // Send the event if (!XSendEvent(dpy, win, False, False, &event)) ERROR_LOG(VIDEO, "Failed to send key press event to the emulator window.\n"); } #endif // -------- // Events void CFrame::OnActive(wxActivateEvent& event) { #if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE) { if (event.GetActive()) X11_SendClientEvent("FOCUSIN"); else X11_SendClientEvent("FOCUSOUT"); } #endif 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(); } void CFrame::OnResizeAll(wxSizeEvent& event) { event.Skip(); #if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE) X11_SendClientEvent("RESIZE"); #endif //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: break; default: return wxFrame::MSWWindowProc(nMsg, wParam, lParam); } break; default: return wxFrame::MSWWindowProc(nMsg, wParam, lParam); } return 0; } #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_CREATE: bRenderToMain = true; break; case TOGGLE_FULLSCREEN: DoFullscreen(!IsFullScreen()); break; case WM_USER_STOP: DoStop(); break; case WM_USER_PAUSE: DoPause(); 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) { if(Core::GetState() != Core::CORE_UNINITIALIZED) { // Toggle fullscreen if (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(); } else if(event.GetKeyCode() == WXK_ESCAPE) { main_frame->DoPause(); } // 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(); if (event.GetKeyCode() >= '3' && event.GetKeyCode() <= '7') // Send this to the video plugin { #ifdef _WIN32 PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode()); #elif defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) X11_SendKeyEvent(event.GetKeyCode()); #endif } // Send the keyboard status to the Input plugin 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 ((Core::GetState() == Core::CORE_RUN) || (Core::GetState() == Core::CORE_PAUSE)) { if (bRenderToMain) { 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); } #ifdef _WIN32 // Show the cursor again, in case it was hidden if (IsFullScreen()) { MSWSetCursor(true); } #endif } #ifdef _WIN32 else // Post the message to the separate rendering window which will then handle it. { BringWindowToTop((HWND)Core::GetWindowHandle()); PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0); } #elif defined HAVE_X11 && HAVE_X11 else // Send the event to the separate rendering window which will then handle it. X11_SendClientEvent("TOGGLE_FULLSCREEN"); #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"); }