diff --git a/src/PowderToy.cpp b/src/PowderToy.cpp index e49a8a1f6..8ef3dd403 100644 --- a/src/PowderToy.cpp +++ b/src/PowderToy.cpp @@ -81,12 +81,13 @@ void SaveWindowPosition() void LargeScreenDialog() { StringBuilder message; + auto scale = ui::Engine::Ref().windowFrameOps.scale; message << "Switching to " << scale << "x size mode since your screen was determined to be large enough: "; - message << desktopWidth << "x" << desktopHeight << " detected, " << WINDOWW*scale << "x" << WINDOWH*scale << " required"; + message << desktopWidth << "x" << desktopHeight << " detected, " << WINDOWW * scale << "x" << WINDOWH * scale << " required"; message << "\nTo undo this, hit Cancel. You can change this in settings at any time."; new ConfirmPrompt("Large screen detected", message.Build(), { nullptr, []() { GlobalPrefs::Ref().Set("Scale", 1); - ui::Engine::Ref().SetScale(1); + ui::Engine::Ref().windowFrameOps.scale = 1; } }); } @@ -285,7 +286,14 @@ int Main(int argc, char *argv[]) explicitSingletons->globalPrefs = std::make_unique(); auto &prefs = GlobalPrefs::Ref(); - scale = prefs.Get("Scale", 1); + + WindowFrameOps windowFrameOps{ + prefs.Get("Scale", 1), + prefs.Get("Resizable", false), + prefs.Get("Fullscreen", false), + prefs.Get("AltFullscreen", false), + prefs.Get("ForceIntegerScaling", true), + }; auto graveExitsConsole = prefs.Get("GraveExitsConsole", true); momentumScroll = prefs.Get("MomentumScroll", true); showAvatars = prefs.Get("ShowAvatars", true); @@ -307,8 +315,8 @@ int Main(int argc, char *argv[]) auto kioskArg = arguments["kiosk"]; if (kioskArg.has_value()) { - currentFrameOps.fullscreen = true_string(kioskArg.value()); - prefs.Set("Fullscreen", currentFrameOps.fullscreen); + windowFrameOps.fullscreen = true_string(kioskArg.value()); + prefs.Set("Fullscreen", windowFrameOps.fullscreen); } if (true_arg(arguments["redirect"])) @@ -326,8 +334,8 @@ int Main(int argc, char *argv[]) { try { - scale = scaleArg.value().ToNumber(); - prefs.Set("Scale", scale); + windowFrameOps.scale = scaleArg.value().ToNumber(); + prefs.Set("Scale", windowFrameOps.scale); } catch (const std::runtime_error &e) { @@ -366,40 +374,29 @@ int Main(int argc, char *argv[]) explicitSingletons->engine = std::make_unique(); // TODO: maybe bind the maximum allowed scale to screen size somehow - if(scale < 1 || scale > SCALE_MAXIMUM) - scale = 1; - - SDLOpen(); - - StopTextInput(); + if(windowFrameOps.scale < 1 || windowFrameOps.scale > SCALE_MAXIMUM) + windowFrameOps.scale = 1; auto &engine = ui::Engine::Ref(); engine.g = new Graphics(); - engine.Scale = scale; engine.GraveExitsConsole = graveExitsConsole; - engine.SetWindowFrameOps(currentFrameOps); engine.MomentumScroll = momentumScroll; engine.ShowAvatars = showAvatars; engine.Begin(); engine.SetFastQuit(prefs.Get("FastQuit", true)); engine.TouchUI = prefs.Get("TouchUI", DEFAULT_TOUCH_UI); - if (Client::Ref().IsFirstRun() && FORCE_WINDOW_FRAME_OPS == forceWindowFrameOpsNone) { - scale = GuessBestScale(); - if (scale > 1) + windowFrameOps.scale = GuessBestScale(); + if (windowFrameOps.scale) { - prefs.Set("Scale", scale); + prefs.Set("Scale", windowFrameOps.scale); showLargeScreenDialog = true; } } + engine.windowFrameOps = windowFrameOps; - SDLSetScreen(scale, { - prefs.Get("Resizable", false), - prefs.Get("Fullscreen", false), - prefs.Get("AltFullscreen", false), - prefs.Get("ForceIntegerScaling", true), - }, vsyncHint); + SDLOpen(); bool enableBluescreen = USE_BLUESCREEN && !true_arg(arguments["disable-bluescreen"]); if (enableBluescreen) diff --git a/src/PowderToyFontEditor.cpp b/src/PowderToyFontEditor.cpp index a2c1be11b..6abf05eaa 100644 --- a/src/PowderToyFontEditor.cpp +++ b/src/PowderToyFontEditor.cpp @@ -41,31 +41,30 @@ int main(int argc, char * argv[]) }); explicitSingletons = std::make_unique(); - scale = 1; + WindowFrameOps windowFrameOps; if (argc >= 3) { std::istringstream ss(argv[2]); int buf; if (ss >> buf) { - scale = buf; + windowFrameOps.scale = buf; } } // TODO: maybe bind the maximum allowed scale to screen size somehow - if(scale < 1 || scale > 10) - scale = 1; + if (windowFrameOps.scale < 1 || windowFrameOps.scale > 10) + { + windowFrameOps.scale = 1; + } explicitSingletons->engine = std::make_unique(); - SDLOpen(); - - StopTextInput(); - auto &engine = ui::Engine::Ref(); engine.g = new Graphics(); - engine.Scale = scale; - engine.SetWindowFrameOps({ false, false, false, false }); + engine.windowFrameOps = windowFrameOps; + + SDLOpen(); engine.Begin(); engine.SetFastQuit(true); diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 34127d00e..c5323e52f 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -12,9 +12,8 @@ int desktopHeight = 1024; SDL_Window *sdl_window = NULL; SDL_Renderer *sdl_renderer = NULL; SDL_Texture *sdl_texture = NULL; -int scale = 1; bool vsyncHint = false; -WindowFrameOps currentFrameOps = { false, false, false, false }; +WindowFrameOps currentFrameOps; bool momentumScroll = true; bool showAvatars = true; uint64_t lastTick = 0; @@ -71,7 +70,7 @@ unsigned int GetTicks() return SDL_GetTicks(); } -void CalculateMousePosition(int *x, int *y) +static void CalculateMousePosition(int *x, int *y) { int globalMx, globalMy; SDL_GetGlobalMouseState(&globalMx, &globalMy); @@ -79,9 +78,9 @@ void CalculateMousePosition(int *x, int *y) SDL_GetWindowPosition(sdl_window, &windowX, &windowY); if (x) - *x = (globalMx - windowX) / scale; + *x = (globalMx - windowX) / currentFrameOps.scale; if (y) - *y = (globalMy - windowY) / scale; + *y = (globalMy - windowY) / currentFrameOps.scale; } void blit(pixel *vid) @@ -102,11 +101,7 @@ void SDLOpen() Platform::Exit(-1); } - if (!RecreateWindow()) - { - fprintf(stderr, "Creating SDL window: %s\n", SDL_GetError()); - Platform::Exit(-1); - } + SDLSetScreen(); int displayIndex = SDL_GetWindowDisplayIndex(sdl_window); if (displayIndex >= 0) @@ -123,6 +118,8 @@ void SDLOpen() { WindowIcon(sdl_window); } + + StopTextInput(); } void SDLClose() @@ -141,8 +138,10 @@ void SDLClose() SDL_Quit(); } -void SDLSetScreen(int scale_, WindowFrameOps newFrameOps, bool vsyncHint_) +void SDLSetScreen() { + auto newFrameOps = ui::Engine::Ref().windowFrameOps; + auto newVsyncHint = std::holds_alternative(ui::Engine::Ref().GetFpsLimit()); if (FORCE_WINDOW_FRAME_OPS == forceWindowFrameOpsEmbedded) { newFrameOps.resizable = false; @@ -157,95 +156,107 @@ void SDLSetScreen(int scale_, WindowFrameOps newFrameOps, bool vsyncHint_) newFrameOps.changeResolution = false; newFrameOps.forceIntegerScaling = false; } -// bool changingScale = scale != scale_; - bool changingFullscreen = newFrameOps.fullscreen != currentFrameOps.fullscreen || (newFrameOps.changeResolution != currentFrameOps.changeResolution && currentFrameOps.fullscreen); - bool changingResizable = currentFrameOps.resizable != newFrameOps.resizable; - bool changingVsync = vsyncHint != vsyncHint_; - scale = scale_; - currentFrameOps.fullscreen = newFrameOps.fullscreen; - currentFrameOps.changeResolution = newFrameOps.changeResolution; - currentFrameOps.resizable = newFrameOps.resizable; - currentFrameOps.forceIntegerScaling = newFrameOps.forceIntegerScaling; - vsyncHint = vsyncHint_; - // Recreate the window when toggling fullscreen, due to occasional issues - // Also recreate it when enabling resizable windows, to fix bugs on windows, - // see https://github.com/jacob1/The-Powder-Toy/issues/24 - if (changingFullscreen || currentFrameOps.changeResolution || (changingResizable && currentFrameOps.resizable && !currentFrameOps.fullscreen) || changingVsync) + + auto currentFrameOpsNorm = currentFrameOps.Normalize(); + auto newFrameOpsNorm = newFrameOps.Normalize(); + auto recreate = !sdl_window || + // Recreate the window when toggling fullscreen, due to occasional issues + newFrameOpsNorm.fullscreen != currentFrameOpsNorm.fullscreen || + // Also recreate it when enabling resizable windows, to fix bugs on windows, + // see https://github.com/jacob1/The-Powder-Toy/issues/24 + newFrameOpsNorm.resizable != currentFrameOpsNorm.resizable || + newFrameOpsNorm.changeResolution != currentFrameOpsNorm.changeResolution || + newVsyncHint != vsyncHint; + + if (!(recreate || + newFrameOpsNorm.scale != currentFrameOpsNorm.scale || + newFrameOpsNorm.forceIntegerScaling != currentFrameOpsNorm.forceIntegerScaling)) { - RecreateWindow(); return; } - if (changingResizable) - SDL_RestoreWindow(sdl_window); - SDL_SetWindowSize(sdl_window, WINDOWW * scale, WINDOWH * scale); - SDL_RenderSetIntegerScale(sdl_renderer, currentFrameOps.forceIntegerScaling && currentFrameOps.fullscreen ? SDL_TRUE : SDL_FALSE); - unsigned int flags = 0; - if (currentFrameOps.fullscreen) - flags = currentFrameOps.changeResolution ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP; - SDL_SetWindowFullscreen(sdl_window, flags); - if (currentFrameOps.fullscreen) - SDL_RaiseWindow(sdl_window); - SDL_SetWindowResizable(sdl_window, currentFrameOps.resizable ? SDL_TRUE : SDL_FALSE); -} + auto size = WINDOW * newFrameOpsNorm.scale; -bool RecreateWindow() -{ - unsigned int flags = 0; - unsigned int rendererFlags = 0; - if (currentFrameOps.fullscreen) - flags = currentFrameOps.changeResolution ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP; - if (currentFrameOps.resizable && !currentFrameOps.fullscreen) - flags |= SDL_WINDOW_RESIZABLE; - if (vsyncHint) - rendererFlags |= SDL_RENDERER_PRESENTVSYNC; - - if (sdl_texture) - SDL_DestroyTexture(sdl_texture); - if (sdl_renderer) - SDL_DestroyRenderer(sdl_renderer); - if (sdl_window) + if (recreate) { - SaveWindowPosition(); - SDL_DestroyWindow(sdl_window); - } - - sdl_window = SDL_CreateWindow(APPNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOWW * scale, WINDOWH * scale, - flags); - if (!sdl_window) - { - return false; - } - sdl_renderer = SDL_CreateRenderer(sdl_window, -1, rendererFlags); - if (!sdl_renderer) - { - fprintf(stderr, "SDL_CreateRenderer failed; available renderers:\n"); - int num = SDL_GetNumRenderDrivers(); - for (int i = 0; i < num; ++i) + if (sdl_texture) { - SDL_RendererInfo info; - SDL_GetRenderDriverInfo(i, &info); - fprintf(stderr, " - %s\n", info.name); + SDL_DestroyTexture(sdl_texture); + sdl_texture = NULL; } - return false; + if (sdl_renderer) + { + SDL_DestroyRenderer(sdl_renderer); + sdl_renderer = NULL; + } + if (sdl_window) + { + SaveWindowPosition(); + SDL_DestroyWindow(sdl_window); + sdl_window = NULL; + } + + unsigned int flags = 0; + unsigned int rendererFlags = 0; + if (newFrameOpsNorm.fullscreen) + { + flags = newFrameOpsNorm.changeResolution ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP; + } + if (newFrameOpsNorm.resizable) + { + flags |= SDL_WINDOW_RESIZABLE; + } + if (vsyncHint) + { + rendererFlags |= SDL_RENDERER_PRESENTVSYNC; + } + sdl_window = SDL_CreateWindow(APPNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, size.X, size.Y, flags); + if (!sdl_window) + { + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); + Platform::Exit(-1); + } + sdl_renderer = SDL_CreateRenderer(sdl_window, -1, rendererFlags); + if (!sdl_renderer) + { + fprintf(stderr, "SDL_CreateRenderer failed; available renderers:\n"); + int num = SDL_GetNumRenderDrivers(); + for (int i = 0; i < num; ++i) + { + SDL_RendererInfo info; + SDL_GetRenderDriverInfo(i, &info); + fprintf(stderr, " - %s\n", info.name); + } + Platform::Exit(-1); + } + SDL_RenderSetLogicalSize(sdl_renderer, WINDOWW, WINDOWH); + sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WINDOWW, WINDOWH); + if (!sdl_texture) + { + fprintf(stderr, "SDL_CreateTexture failed: %s\n", SDL_GetError()); + Platform::Exit(-1); + } + SDL_RaiseWindow(sdl_window); + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); + //Uncomment this to enable resizing + //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + //SDL_SetWindowResizable(sdl_window, SDL_TRUE); + + LoadWindowPosition(); + UpdateFpsLimit(); } - SDL_RenderSetLogicalSize(sdl_renderer, WINDOWW, WINDOWH); - if (currentFrameOps.forceIntegerScaling && currentFrameOps.fullscreen) - SDL_RenderSetIntegerScale(sdl_renderer, SDL_TRUE); - sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WINDOWW, WINDOWH); - SDL_RaiseWindow(sdl_window); - SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); - //Uncomment this to enable resizing - //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - //SDL_SetWindowResizable(sdl_window, SDL_TRUE); - LoadWindowPosition(); - UpdateFpsLimit(); - - return true; + SDL_SetWindowSize(sdl_window, size.X, size.Y); + SDL_RenderSetIntegerScale(sdl_renderer, newFrameOpsNorm.forceIntegerScaling ? SDL_TRUE : SDL_FALSE); + if (newFrameOpsNorm.fullscreen) + { + SDL_RaiseWindow(sdl_window); + } + currentFrameOps = newFrameOps; + vsyncHint = newVsyncHint; } -void EventProcess(const SDL_Event &event) +static void EventProcess(const SDL_Event &event) { auto &engine = ui::Engine::Ref(); switch (event.type) @@ -399,13 +410,7 @@ void EngineProcess() { engine.Draw(); drawingTimer = 0; - - auto wantVsync = bool(std::get_if(&fpsLimit)); - if (scale != engine.Scale || currentFrameOps != engine.GetWindowFrameOps() || vsyncHint != wantVsync) - { - SDLSetScreen(engine.Scale, engine.GetWindowFrameOps(), wantVsync); - } - + SDLSetScreen(); blit(engine.g->Data()); } auto now = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000); diff --git a/src/PowderToySDL.h b/src/PowderToySDL.h index 85613f661..43e3f69e0 100644 --- a/src/PowderToySDL.h +++ b/src/PowderToySDL.h @@ -12,9 +12,6 @@ extern int desktopHeight; extern SDL_Window *sdl_window; extern SDL_Renderer *sdl_renderer; extern SDL_Texture *sdl_texture; -extern int scale; -extern bool vsyncHint; -extern WindowFrameOps currentFrameOps; extern bool momentumScroll; extern bool showAvatars; extern uint64_t lastTick; @@ -36,16 +33,13 @@ void ClipboardPush(ByteString text); ByteString ClipboardPull(); int GetModifiers(); unsigned int GetTicks(); -void CalculateMousePosition(int *x, int *y); void blit(pixel *vid); void SDLOpen(); void SDLClose(); -void SDLSetScreen(int scale_, WindowFrameOps newFrameOps, bool vsyncHint_); +void SDLSetScreen(); void SetFpsLimit(FpsLimit newFpsLimit); -bool RecreateWindow(); void LoadWindowPosition(); void SaveWindowPosition(); void LargeScreenDialog(); void TickClient(); -void EventProcess(const SDL_Event &event); void UpdateFpsLimit(); diff --git a/src/gui/WindowFrameOps.h b/src/gui/WindowFrameOps.h index 483b8f1c3..cceac8920 100644 --- a/src/gui/WindowFrameOps.h +++ b/src/gui/WindowFrameOps.h @@ -1,26 +1,22 @@ #pragma once +#include struct WindowFrameOps { - bool resizable; - bool fullscreen; - bool changeResolution; - bool forceIntegerScaling; + int scale = 1; + bool resizable = false; + bool fullscreen = false; + bool changeResolution = false; + bool forceIntegerScaling = false; - bool operator ==(const WindowFrameOps &other) const + WindowFrameOps Normalize() const { - if (resizable != other.resizable ) return false; - if (fullscreen != other.fullscreen) return false; - if (fullscreen) - { - if (changeResolution != other.changeResolution ) return false; - if (forceIntegerScaling != other.forceIntegerScaling) return false; - } - return true; - } - - bool operator !=(const WindowFrameOps &other) const - { - return !(*this == other); + return { + fullscreen ? 1 : scale , + fullscreen ? false : resizable , + fullscreen , + fullscreen ? changeResolution : false, + fullscreen ? forceIntegerScaling : false, + }; } }; diff --git a/src/gui/interface/Engine.cpp b/src/gui/interface/Engine.cpp index febe140a6..08887d23d 100644 --- a/src/gui/interface/Engine.cpp +++ b/src/gui/interface/Engine.cpp @@ -12,8 +12,6 @@ using namespace ui; Engine::Engine(): drawingFrequencyLimit(0), - Scale(1), - Fullscreen(false), FrameIndex(0), state_(NULL), windowTargetPosition(0, 0), @@ -333,5 +331,6 @@ void Engine::StopTextInput() void Engine::TextInputRect(Point position, Point size) { - ::SetTextInputRect(position.X * Scale, position.Y * Scale, size.X * Scale, size.Y * Scale); + auto scale = windowFrameOps.scale; + ::SetTextInputRect(position.X * scale, position.Y * scale, size.X * scale, size.Y * scale); } diff --git a/src/gui/interface/Engine.h b/src/gui/interface/Engine.h index a048309e1..b2145cfd0 100644 --- a/src/gui/interface/Engine.h +++ b/src/gui/interface/Engine.h @@ -48,8 +48,6 @@ namespace ui void SetDrawingFrequencyLimit(int limit) {drawingFrequencyLimit = limit;} inline int GetDrawingFrequencyLimit() {return drawingFrequencyLimit;} - void SetScale(int scale) { Scale = scale; } - inline int GetScale() { return Scale; } void SetFastQuit(bool fastquit) { FastQuit = fastquit; } inline bool GetFastQuit() {return FastQuit; } @@ -79,9 +77,7 @@ namespace ui int drawingFrequencyLimit; Graphics * g; - int Scale; bool GraveExitsConsole; - bool Fullscreen; unsigned int FrameIndex; private: @@ -121,31 +117,21 @@ namespace ui String textEditingBuf; - WindowFrameOps windowFrameOps = { false, false, false, false }; - public: bool MomentumScroll = true; bool ShowAvatars = true; bool TouchUI = false; + WindowFrameOps windowFrameOps; - inline WindowFrameOps GetWindowFrameOps() const - { - return windowFrameOps; - } - - inline void SetWindowFrameOps(WindowFrameOps newWindowFrameOps) - { - windowFrameOps = newWindowFrameOps; - } - + void SetScale (int newScale ) { windowFrameOps.scale = newScale; } void SetFullscreen (bool newFullscreen ) { windowFrameOps.fullscreen = newFullscreen; } void SetChangeResolution (bool setChangeResolution ) { windowFrameOps.changeResolution = setChangeResolution; } void SetForceIntegerScaling(bool newForceIntegerScaling) { windowFrameOps.forceIntegerScaling = newForceIntegerScaling; } void SetResizable (bool newResizable ) { windowFrameOps.resizable = newResizable; } - inline bool GetFullscreen () const { return windowFrameOps.fullscreen; } - inline bool GetChangeResolution () const { return windowFrameOps.changeResolution; } - inline bool GetForceIntegerScaling() const { return windowFrameOps.forceIntegerScaling; } - inline bool GetResizable () const { return windowFrameOps.resizable; } + int GetScale () const { return windowFrameOps.scale; } + bool GetFullscreen () const { return windowFrameOps.fullscreen; } + bool GetChangeResolution () const { return windowFrameOps.changeResolution; } + bool GetForceIntegerScaling() const { return windowFrameOps.forceIntegerScaling; } + bool GetResizable () const { return windowFrameOps.resizable; } }; - }