Move display options to owned_opts

This also removes limits on the main window position so it can now be
negative. This is necessary on Windows where multiple screens to the
left and top of the main screen have negative coordinates. A check at
startup ensures we always restore the window within the drawable area.
This commit is contained in:
Fabrice de Gans 2023-02-05 17:44:04 -08:00 committed by Rafael Kitover
parent 216bf4d7e4
commit 950a4070c1
16 changed files with 240 additions and 129 deletions

View File

@ -765,6 +765,7 @@ set(
config/option.cpp
config/user-input.cpp
dialogs/display-config.cpp
widgets/keep-on-top-styler.cpp
widgets/keyedit.cpp
widgets/joyedit.cpp
widgets/option-validator.cpp
@ -811,6 +812,7 @@ set(
config/user-input.h
dialogs/display-config.h
widgets/dpi-support.h
widgets/keep-on-top-styler.h
widgets/option-validator.h
widgets/render-plugin.h
widgets/wx/keyedit.h

View File

@ -2267,12 +2267,6 @@ EVT_HANDLER(Logging, "Logging...")
{
wxDialog* dlg = wxGetApp().frame->logdlg;
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
dlg->Show();
dlg->Raise();
}
@ -2741,15 +2735,6 @@ EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
{
if (gopts.max_threads != 1) {
gopts.max_threads = wxThread::GetCPUCount();
}
// Just in case GetCPUCount() returns 0 or -1
if (gopts.max_threads < 0) {
gopts.max_threads = 1;
}
wxDialog* dlg = GetXRCDialog("DisplayConfig");
if (ShowModal(dlg) != wxID_OK) {
return;
@ -2965,18 +2950,12 @@ EVT_HANDLER(wxID_ABOUT, "About...")
EVT_HANDLER(Bilinear, "Use bilinear filter with 3d renderer")
{
GetMenuOptionBool("Bilinear", &gopts.bilinear);
// Force new panel with new bilinear option.
panel->ResetPanel();
update_opts();
GetMenuOptionConfig("Bilinear", config::OptionID::kDispBilinear);
}
EVT_HANDLER(RetainAspect, "Retain aspect ratio when resizing")
{
GetMenuOptionBool("RetainAspect", &gopts.retain_aspect);
// Force new panel with new aspect ratio options.
panel->ResetPanel();
update_opts();
GetMenuOptionConfig("RetainAspect", config::OptionID::kDispStretch);
}
EVT_HANDLER(Printer, "Enable printer emulation")
@ -3080,15 +3059,7 @@ EVT_HANDLER(ApplyPatches, "Apply IPS/UPS/IPF patches if found")
EVT_HANDLER(KeepOnTop, "Keep window on top")
{
GetMenuOptionBool("KeepOnTop", &gopts.keep_on_top);
MainFrame* mf = wxGetApp().frame;
if (gopts.keep_on_top)
mf->SetWindowStyle(mf->GetWindowStyle() | wxSTAY_ON_TOP);
else
mf->SetWindowStyle(mf->GetWindowStyle() & ~wxSTAY_ON_TOP);
update_opts();
GetMenuOptionConfig("KeepOnTop", config::OptionID::kDispKeepOnTop);
}
EVT_HANDLER(StatusBar, "Enable status bar")

View File

@ -6,6 +6,7 @@
#include <wx/log.h>
#include <algorithm>
#include <limits>
#include "../common/ConfigManager.h"
#include "../gb/gbGlobals.h"
@ -145,20 +146,27 @@ wxString AllEnumValuesForArray(const std::array<wxString, SIZE>& input) {
// static
std::array<Option, kNbOptions>& Option::All() {
struct OwnedOptions {
double video_scale = 3;
wxString filter_plugin = wxEmptyString;
/// Display
bool bilinear = true;
Filter filter = Filter::kNone;
wxString filter_plugin = wxEmptyString;
Interframe interframe = Interframe::kNone;
bool keep_on_top = false;
int32_t max_threads = 0;
#if defined(NO_OGL)
RenderMethod render_method = RenderMethod::kSimple;
#else
RenderMethod render_method = RenderMethod::kOpenGL;
#endif
double video_scale = 3;
bool retain_aspect = true;
/// Geometry
bool window_maximized = false;
uint32_t window_height = 0;
uint32_t window_width = 0;
int window_pos_x = -1;
int window_pos_y = -1;
int32_t window_pos_x = -1;
int32_t window_pos_y = -1;
};
static OwnedOptions g_owned_opts;
@ -170,15 +178,15 @@ std::array<Option, kNbOptions>& Option::All() {
// clang-format off
static std::array<Option, kNbOptions> g_all_opts = {
/// Display
Option(OptionID::kDispBilinear, &gopts.bilinear),
Option(OptionID::kDispBilinear, &g_owned_opts.bilinear),
Option(OptionID::kDispFilter, &g_owned_opts.filter),
Option(OptionID::kDispFilterPlugin, &g_owned_opts.filter_plugin),
Option(OptionID::kDispIFB, &g_owned_opts.interframe),
Option(OptionID::kDispKeepOnTop, &gopts.keep_on_top),
Option(OptionID::kDispMaxThreads, &gopts.max_threads, 1, 256),
Option(OptionID::kDispKeepOnTop, &g_owned_opts.keep_on_top),
Option(OptionID::kDispMaxThreads, &g_owned_opts.max_threads, 0, 256),
Option(OptionID::kDispRenderMethod, &g_owned_opts.render_method),
Option(OptionID::kDispScale, &g_owned_opts.video_scale, 1, 6),
Option(OptionID::kDispStretch, &gopts.retain_aspect),
Option(OptionID::kDispStretch, &g_owned_opts.retain_aspect),
/// GB
Option(OptionID::kGBBiosFile, &gopts.gb_bios),
@ -270,8 +278,8 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kGeomIsMaximized, &g_owned_opts.window_maximized),
Option(OptionID::kGeomWindowHeight, &g_owned_opts.window_height, 0, 99999),
Option(OptionID::kGeomWindowWidth, &g_owned_opts.window_width, 0, 99999),
Option(OptionID::kGeomWindowX, &g_owned_opts.window_pos_x, -1, 99999),
Option(OptionID::kGeomWindowY, &g_owned_opts.window_pos_y, -1, 99999),
Option(OptionID::kGeomWindowX, &g_owned_opts.window_pos_x, std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()),
Option(OptionID::kGeomWindowY, &g_owned_opts.window_pos_y, std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()),
/// UI
Option(OptionID::kUIAllowKeyboardBackgroundInput, &allowKeyboardBackgroundInput),

View File

@ -4,7 +4,7 @@
namespace config {
enum class OptionID {
// Display
/// Display
kDispBilinear = 0,
kDispFilter,
kDispFilterPlugin,

View File

@ -18,6 +18,7 @@
#include "config/option-id.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "keep-on-top-styler.h"
#include "rpi.h"
#include "wayland.h"
#include "widgets/option-validator.h"
@ -250,7 +251,8 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
interframe_observer_(config::OptionID::kDispIFB,
std::bind(&DisplayConfig::OnInterframeChanged,
this,
std::placeholders::_1)) {
std::placeholders::_1)),
keep_on_top_styler_(this) {
#if !wxCHECK_VERSION(3, 1, 0)
// This needs to be set before loading any element on the window. This also
// has no effect since wx 3.1.0, where it became the default.
@ -337,6 +339,9 @@ void DisplayConfig::OnDialogShowEvent(wxShowEvent& event) {
} else {
StopPluginHandler();
}
// Let the event propagate.
event.Skip();
}
void DisplayConfig::PopulatePluginOptions() {
@ -408,6 +413,9 @@ void DisplayConfig::UpdatePlugin(wxCommandEvent& event) {
config::Filter::kPlugin);
plugin_label_->Enable(is_plugin);
plugin_selector_->Enable(is_plugin);
// Let the event propagate.
event.Skip();
}
void DisplayConfig::OnFilterChanged(config::Option* option) {

View File

@ -5,6 +5,7 @@
#include <wx/event.h>
#include "config/option-observer.h"
#include "widgets/keep-on-top-styler.h"
// Forward declarations.
class wxChoice;
@ -55,8 +56,9 @@ private:
wxChoice* plugin_selector_;
wxChoice* filter_selector_;
wxChoice* interframe_selector_;
config::OptionsObserver filter_observer_;
config::OptionsObserver interframe_observer_;
const config::OptionsObserver filter_observer_;
const config::OptionsObserver interframe_observer_;
const widgets::KeepOnTopStyler keep_on_top_styler_;
};
} // namespace dialogs

View File

@ -26,6 +26,7 @@
#include "../gba/CheatSearch.h"
#include "config/game-control.h"
#include "config/option.h"
#include "config/option-proxy.h"
#include "config/user-input.h"
#include "dialogs/display-config.h"
#include "opts.h"
@ -322,7 +323,7 @@ public:
wxDialog* subdlg = GetXRCDialog("CheatEdit");
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
@ -545,7 +546,7 @@ public:
wxDialog* subdlg = GetXRCDialog("CheatEdit");
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
@ -1075,7 +1076,7 @@ public:
wxDialog* subdlg = GetXRCDialog("CheatAdd");
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
@ -3785,7 +3786,7 @@ bool MainFrame::BindControls()
else
mf->GetStatusBar()->Hide();
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
mf->SetWindowStyle(mf->GetWindowStyle() | wxSTAY_ON_TOP);
else
mf->SetWindowStyle(mf->GetWindowStyle() & ~wxSTAY_ON_TOP);

View File

@ -8,6 +8,7 @@
#include <wx/display.h>
#include "config/option-observer.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "strutils.h"
#include "wxvbam.h"
@ -308,14 +309,6 @@ wxAcceleratorEntry_v sys_accels;
// This constructor only works with globally allocated gopts.
opts_t::opts_t()
{
// handle erroneous thread count values appropriately
max_threads = wxThread::GetCPUCount();
if (max_threads > 256)
max_threads = 256;
if (max_threads < 1)
max_threads = 1;
recent = new wxFileHistory(10);
// These are globals being set here.
@ -556,6 +549,20 @@ void load_opts() {
cfg->SetPath(wxT("/"));
cfg->Flush();
// We default the MaxThreads option to 0, so set it to the CPU count here.
config::OptionProxy<config::OptionID::kDispMaxThreads> max_threads;
if (max_threads == 0) {
// Handle erroneous thread count values appropriately.
const int cpu_count = wxThread::GetCPUCount();
if (cpu_count > 256) {
max_threads = 256;
} else if (cpu_count < 1) {
max_threads = 1;
} else {
max_threads = cpu_count;
}
}
InitializeOptionObservers();
}

View File

@ -23,11 +23,7 @@ extern struct opts_t {
// I instead organized this by opts.cpp table order
/// Display
bool bilinear = true;
wxVideoMode fs_mode;
int max_threads = 0;
bool retain_aspect = true;
bool keep_on_top = false;
/// GB
wxString gb_bios;

View File

@ -110,8 +110,9 @@ GameArea::GameArea()
pointer_blanked(false),
mouse_active_time(0),
render_observer_(
{config::OptionID::kDispRenderMethod, config::OptionID::kDispFilter,
config::OptionID::kDispIFB},
{config::OptionID::kDispBilinear, config::OptionID::kDispFilter,
config::OptionID::kDispRenderMethod, config::OptionID::kDispIFB,
config::OptionID::kDispStretch},
std::bind(&GameArea::ResetPanel, this)),
scale_observer_(config::OptionID::kDispScale,
std::bind(&GameArea::AdjustSize, this, true)) {
@ -1158,32 +1159,28 @@ void GameArea::OnIdle(wxIdleEvent& event)
AdjustMinSize();
AdjustSize(false);
unsigned frame_priority = gopts.retain_aspect ? 0 : 1;
const bool retain_aspect = OPTION(kDispStretch);
const unsigned frame_priority = retain_aspect ? 0 : 1;
GetSizer()->Clear();
// add spacers on top and bottom to center panel vertically
// but not on 2.8 which does not handle this correctly
if (gopts.retain_aspect)
#if wxCHECK_VERSION(2, 9, 0)
if (retain_aspect) {
GetSizer()->Add(0, 0, wxEXPAND);
#else
frame_priority = 1;
#endif
}
// this triggers an assertion dialog in <= 3.1.2 in debug mode
GetSizer()->Add(w, frame_priority, gopts.retain_aspect ? (wxSHAPED | wxALIGN_CENTER | wxEXPAND) : wxEXPAND);
GetSizer()->Add(
w, frame_priority,
retain_aspect ? (wxSHAPED | wxALIGN_CENTER | wxEXPAND) : wxEXPAND);
#if wxCHECK_VERSION(2, 9, 0)
if (gopts.retain_aspect)
if (retain_aspect) {
GetSizer()->Add(0, 0, wxEXPAND);
#endif
}
Layout();
#if wxCHECK_VERSION(2, 9, 0)
SendSizeEvent();
#endif
if (pointer_blanked)
w->SetCursor(wxCursor(wxCURSOR_BLANK));
@ -1196,7 +1193,8 @@ void GameArea::OnIdle(wxIdleEvent& event)
utilUpdateSystemColorMaps(gopts.gba_lcd_filter);
else if (loaded == IMAGE_GB)
utilUpdateSystemColorMaps(gopts.gb_lcd_filter);
else utilUpdateSystemColorMaps(false);
else
utilUpdateSystemColorMaps(false);
}
mf->PollJoysticks();
@ -1806,13 +1804,13 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
todraw = pixbuf2;
// FIXME: filters race condition?
gopts.max_threads = 1;
const int max_threads = 1;
// First, apply filters, if applicable, in parallel, if enabled
// FIXME: && (gopts.ifb != FF_MOTION_BLUR || !renderer_can_motion_blur)
if (OPTION(kDispFilter) != config::Filter::kNone ||
OPTION(kDispIFB) != config::Interframe::kNone) {
if (nthreads != gopts.max_threads) {
if (nthreads != max_threads) {
if (nthreads) {
if (nthreads > 1)
for (int i = 0; i < nthreads; i++) {
@ -1826,7 +1824,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
delete[] threads;
}
nthreads = gopts.max_threads;
nthreads = max_threads;
threads = new FilterThread[nthreads];
// first time around, no threading in order to avoid
// static initializer conflicts
@ -2217,6 +2215,8 @@ void GLDrawingPanel::DrawingPanelInit()
AdjustViewport();
const bool bilinear = OPTION(kDispBilinear);
// taken from GTK front end almost verbatim
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
@ -2241,9 +2241,9 @@ void GLDrawingPanel::DrawingPanelInit()
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
bilinear ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
bilinear ? GL_LINEAR : GL_NEAREST);
#define int_fmt out_16 ? GL_RGB5 : GL_RGB
#define tex_fmt out_16 ? GL_BGRA : GL_RGBA, \

View File

@ -1,5 +1,6 @@
#include "../common/SoundSDL.h"
#include "config/game-control.h"
#include "config/option-proxy.h"
#include "wxvbam.h"
#include "SDL.h"
#include <wx/ffile.h>
@ -777,7 +778,7 @@ public:
{
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP);

View File

@ -4,11 +4,13 @@
#include "../common/cstdint.h"
#include "../gba/armdis.h"
#include "viewsupt.h"
#include "wxvbam.h"
#include <wx/ffile.h>
#include <wx/vlbox.h>
#include "../gba/armdis.h"
#include "config/option-proxy.h"
#include "keep-on-top-styler.h"
#include "viewsupt.h"
#include "wxvbam.h"
// avoid exporting classes
namespace Viewers {
@ -515,8 +517,7 @@ void MainFrame::IOViewer()
baddialog(); \
cb->SetValidator(wxBoolIntValidator(&systemVerbose, val, val)); \
} while (0)
LogDialog::LogDialog()
{
LogDialog::LogDialog() : keep_on_top_styler_(this) {
const wxString dname = wxT("Logging");
if (!wxXmlResource::Get()->LoadDialog(this, wxGetApp().frame, dname))
@ -727,7 +728,7 @@ public:
selreg_len->SetValue(s);
selregion->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
selregion->SetWindowStyle(selregion->GetWindowStyle() | wxSTAY_ON_TOP);
else
selregion->SetWindowStyle(selregion->GetWindowStyle() & ~wxSTAY_ON_TOP);
@ -752,7 +753,7 @@ public:
selreg_len->SetValue(wxEmptyString);
selregion->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
selregion->SetWindowStyle(selregion->GetWindowStyle() | wxSTAY_ON_TOP);
else
selregion->SetWindowStyle(selregion->GetWindowStyle() & ~wxSTAY_ON_TOP);

View File

@ -0,0 +1,44 @@
#include "widgets/keep-on-top-styler.h"
#include <wx/toplevel.h>
#include "config/option-proxy.h"
#include "config/option.h"
namespace widgets {
KeepOnTopStyler::KeepOnTopStyler(wxTopLevelWindow* window)
: window_(window),
on_top_observer_(config::OptionID::kDispKeepOnTop,
std::bind(&KeepOnTopStyler::OnKeepOnTopChanged,
this,
std::placeholders::_1)) {
assert(window_);
window_->Bind(wxEVT_SHOW, &KeepOnTopStyler::OnShow, this);
}
KeepOnTopStyler::~KeepOnTopStyler() {
// Need to manually unbind to stop processing events for this window.
window_->Unbind(wxEVT_SHOW, &KeepOnTopStyler::OnShow, this);
}
void KeepOnTopStyler::OnShow(wxShowEvent& show_event) {
if (show_event.IsShown()) {
// This must be called when the window is shown or it has no effect.
OnKeepOnTopChanged(
config::Option::ByID(config::OptionID::kDispKeepOnTop));
}
// Let the event propagate.
show_event.Skip();
}
void KeepOnTopStyler::OnKeepOnTopChanged(config::Option* option) {
if (option->GetBool()) {
window_->SetWindowStyle(window_->GetWindowStyle() | wxSTAY_ON_TOP);
} else {
window_->SetWindowStyle(window_->GetWindowStyle() & ~wxSTAY_ON_TOP);
}
}
} // namespace widgets

View File

@ -0,0 +1,58 @@
#ifndef VBAM_WX_DIALOGS_BASE_DIALOG_H_
#define VBAM_WX_DIALOGS_BASE_DIALOG_H_
#include <wx/event.h>
#include "config/option-observer.h"
// Forward declarations.
class wxTopLevelWindow;
namespace config {
class Option;
}
namespace widgets {
// Helper class to automatically set and unset the wxSTAY_ON_TOP to any
// top-level window. Simply add it as a private member to any top-level window
// implementation and pass the reference to the window in the constructor.
//
// Sample usage:
//
// class MyDialog: public wxDialog {
// public:
// MyDialog() : wxDialog(), keep_on_top_styler_(this) {}
// ~MyDialog() override = default;
// private:
// KeepOnTopStyler keep_on_top_styler_;
// };
class KeepOnTopStyler {
public:
// `window` must outlive this object. The easiest way to do so is to add
// this object as a private member of the top-level window.
explicit KeepOnTopStyler(wxTopLevelWindow* window);
~KeepOnTopStyler();
// Disable copy and assignment.
KeepOnTopStyler(const KeepOnTopStyler&) = delete;
KeepOnTopStyler& operator=(const KeepOnTopStyler&) = delete;
private:
// Callback for the `window` wxEVT_SHOW event.
void OnShow(wxShowEvent& show_event);
// Callback fired when the KeepOnTop setting has changed.
void OnKeepOnTopChanged(config::Option* option);
// The non-owned window whose style should be modified.
wxTopLevelWindow *const window_;
// Observer for the KeepOnTop setting changed event.
const config::OptionsObserver on_top_observer_;
};
} // namespace widgets
#endif // VBAM_WX_DIALOGS_BASE_DIALOG_H_

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <wx/cmdline.h>
#include <wx/display.h>
#include <wx/file.h>
#include <wx/filesys.h>
#include <wx/fs_arc.h>
@ -39,10 +40,10 @@
#ifdef __WXMSW__
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
int __stdcall WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
bool console_attached = AttachConsole(ATTACH_PARENT_PROCESS) != FALSE;
#ifdef DEBUG
// In debug builds, create a console if none is attached.
@ -470,32 +471,45 @@ bool wxvbamApp::OnInit() {
// and command line overrides have been applied.
config::GameControlState::Instance().OnGameBindingsChanged();
// create the main window
int x = OPTION(kGeomWindowX);
int y = OPTION(kGeomWindowY);
int width = OPTION(kGeomWindowHeight);
int height = OPTION(kGeomWindowHeight);
bool isFullscreen = OPTION(kGeomFullScreen);
bool isMaximized = OPTION(kGeomIsMaximized);
frame = wxDynamicCast(xr->LoadFrame(nullptr, "MainFrame"), MainFrame);
// We need to gather this information before crating the MainFrame as the
// OnSize / OnMove event handlers can fire during construction.
const wxRect client_rect(
OPTION(kGeomWindowX).Get(),
OPTION(kGeomWindowY).Get(),
OPTION(kGeomWindowWidth).Get(),
OPTION(kGeomWindowHeight).Get());
const bool is_fullscreen = OPTION(kGeomFullScreen);
const bool is_maximized = OPTION(kGeomIsMaximized);
// Create the main window.
frame = wxDynamicCast(xr->LoadFrame(nullptr, "MainFrame"), MainFrame);
if (!frame) {
wxLogError(_("Could not create main window"));
return false;
}
// Create() cannot be overridden easily
if (!frame->BindControls())
if (!frame->BindControls()) {
return false;
}
if (x >= 0 && y >= 0 && width > 0 && height > 0)
frame->SetSize(x, y, width, height);
// Measure the full display area.
wxRect display_rect;
for (unsigned int i = 0; i < wxDisplay::GetCount(); i++) {
display_rect.Union(wxDisplay(i).GetClientArea());
}
if (isMaximized)
// Ensure we are not drawing out of bounds.
if (display_rect.Intersects(client_rect)) {
frame->SetSize(client_rect);
}
if (is_maximized) {
frame->Maximize();
}
if (is_fullscreen && wxGetApp().pending_load != wxEmptyString)
frame->ShowFullScreen(is_fullscreen);
if (isFullscreen && wxGetApp().pending_load != wxEmptyString)
frame->ShowFullScreen(isFullscreen);
frame->Show(true);
#ifndef NO_ONLINEUPDATES
@ -760,12 +774,12 @@ wxvbamApp::~wxvbamApp() {
}
MainFrame::MainFrame()
: wxFrame()
, paused(false)
, menus_opened(0)
, dialog_opened(0)
, focused(false)
{
: wxFrame(),
paused(false),
menus_opened(0),
dialog_opened(0),
focused(false),
keep_on_top_styler_(this) {
jpoll = new JoystickPoller();
this->Connect(wxID_ANY, wxEVT_SHOW, wxShowEventHandler(JoystickPoller::ShowDialog), jpoll, jpoll);
}
@ -835,13 +849,10 @@ void MainFrame::OnMenu(wxContextMenuEvent& event)
}
void MainFrame::OnMove(wxMoveEvent&) {
wxPoint window_pos = GetScreenPosition();
if (!IsFullScreen() && !IsMaximized()) {
if (window_pos.x >= 0 && window_pos.y >= 0) {
OPTION(kGeomWindowX) = window_pos.x;
OPTION(kGeomWindowY) = window_pos.y;
}
const wxPoint window_pos = GetScreenPosition();
OPTION(kGeomWindowX) = window_pos.x;
OPTION(kGeomWindowY) = window_pos.y;
}
}
@ -856,10 +867,8 @@ void MainFrame::OnSize(wxSizeEvent& event)
OPTION(kGeomWindowHeight) = window_rect.GetHeight();
OPTION(kGeomWindowWidth) = window_rect.GetWidth();
}
if (window_pos.x >= 0 && window_pos.y >= 0) {
OPTION(kGeomWindowX) = window_pos.x;
OPTION(kGeomWindowY) = window_pos.y;
}
OPTION(kGeomWindowX) = window_pos.x;
OPTION(kGeomWindowY) = window_pos.y;
}
OPTION(kGeomIsMaximized) = IsMaximized();
@ -1161,7 +1170,7 @@ int MainFrame::ShowModal(wxDialog* dlg)
{
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxCAPTION | wxRESIZE_BORDER);
if (gopts.keep_on_top)
if (OPTION(kDispKeepOnTop))
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP);
else
dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP);

View File

@ -13,6 +13,7 @@
#include "config/option-observer.h"
#include "widgets/dpi-support.h"
#include "widgets/keep-on-top-styler.h"
#include "wx/joyedit.h"
#include "wx/keyedit.h"
#include "wx/sdljoy.h"
@ -212,7 +213,7 @@ extern bool pause_next;
class MainFrame : public wxFrame {
public:
MainFrame();
~MainFrame();
~MainFrame() override;
bool BindControls();
void MenuOptionIntMask(const wxString& menuName, int field, int mask);
@ -361,14 +362,15 @@ private:
// joystick reader
wxJoyPoller joy;
JoystickPoller* jpoll = nullptr;
// quicker & more accurate than FindFocus() != NULL
bool focused;
const widgets::KeepOnTopStyler keep_on_top_styler_;
// helper function for adding menu to accel editor
void add_menu_accels(wxTreeCtrl* tc, wxTreeItemId& parent, wxMenu* menu);
// for detecting window focus
void OnActivate(wxActivateEvent&);
// quicker & more accurate than FindFocus() != NULL
bool focused;
// may work, may not... if so, load dropped file
void OnDropFile(wxDropFilesEvent&);
// pop up menu in fullscreen mode
@ -689,6 +691,7 @@ public:
private:
wxTextCtrl* log;
widgets::KeepOnTopStyler keep_on_top_styler_;
void Save(wxCommandEvent& ev);
void Clear(wxCommandEvent& ev);