Cemu/src/gui/wxgui/debugger/SymbolWindow.cpp
Jakob Linke ed4213a3be gui: close dialogs/frames on Esc, add Ctrl+Q exit shortcut
Several of Cemu's settings dialogs (GeneralSettings2, InputSettings2,
GraphicPacksWindow2, ...) and most of its tool wxFrames have no
Cancel/Close/OK button. On a Wayland compositor that doesn't draw
server-side decorations there is also no compositor-drawn close button,
so once opened these windows cannot be dismissed.

wxDialog's built-in Esc handling (wxDialogBase::OnCharHook in
src/common/dlgcmn.cpp) forwards Esc to a button with wxID_CANCEL or
the affirmative-id button via EmulateButtonClickIfPresent; with
neither button present, SendCloseButtonClickEvent returns false and
the handler just Skip()s. wxFrame has no Esc handling at all (the
event table in src/common/framecmn.cpp only carries menu-open/close
entries).

Add wxHelper::BindEscapeCloses(target), a one-liner that binds
WXK_ESCAPE on wxEVT_CHAR_HOOK to target->Close(). Close() goes
through the wxEVT_CLOSE_WINDOW path, where wxDialogBase::OnCloseWindow
does fall back to EndDialog(wxID_CANCEL) when no Cancel/OK button
is found - so the helper closes buttonless dialogs correctly. Apply
as the first statement of every wxDialog and wxFrame ctor in
src/gui/wxgui/, except:
  - MainWindow: Esc shouldn't quit Cemu.
  - PadViewFrame: already binds Esc to leave fullscreen.
  - HotkeySettings: inline variant guarded by !m_activeInputButton
    so an in-progress keyboard capture (whose cancel path is
    OnKeyUp + IsValidKeycodeUp rejecting WXK_ESCAPE) still wins.

Tag the File>Exit menu item label with "\tCtrl+Q"; wxMenuItemBase::
GetAccel() parses everything after the tab via wxAcceleratorEntry::
Create and wxMenuBar registers it as an accelerator.
2026-05-23 08:53:09 +02:00

56 lines
1.6 KiB
C++

#include "wxgui/wxgui.h"
#include "wxgui/debugger/SymbolWindow.h"
#include "wxgui/debugger/DebuggerWindow2.h"
#include "Cafe/HW/Espresso/Debugger/Debugger.h"
#include "Cafe/OS/RPL/rpl_symbol_storage.h"
#include "wxgui/helpers/wxHelpers.h"
enum ItemColumns
{
ColumnName = 0,
ColumnAddress,
ColumnModule,
};
SymbolWindow::SymbolWindow(DebuggerWindow2& parent, const wxPoint& main_position, const wxSize& main_size)
: wxFrame(&parent, wxID_ANY, _("Symbols"), wxDefaultPosition, wxSize(600, 250), wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT)
{
wxHelper::BindEscapeCloses(this);
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
m_symbol_ctrl = new SymbolListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
main_sizer->Add(m_symbol_ctrl, 1, wxEXPAND);
m_filter = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_NO_VSCROLL);
m_filter->Bind(wxEVT_TEXT, &SymbolWindow::OnFilterChanged, this);
main_sizer->Add(m_filter, 0, wxALL | wxEXPAND, 5);
this->SetSizer(main_sizer);
this->wxWindowBase::Layout();
this->Centre(wxHORIZONTAL);
if (parent.GetConfig().data().pin_to_main)
OnMainMove(main_position, main_size);
}
void SymbolWindow::OnMainMove(const wxPoint& main_position, const wxSize& main_size)
{
wxSize size(420, 250);
this->SetSize(size);
wxPoint position = main_position;
position.x -= 420;
this->SetPosition(position);
}
void SymbolWindow::OnGameLoaded()
{
m_symbol_ctrl->OnGameLoaded();
}
void SymbolWindow::OnFilterChanged(wxCommandEvent& event)
{
m_symbol_ctrl->ChangeListFilter(m_filter->GetValue());
}