From 9cbf0f3bbcf266829f903766bbad6763839210a5 Mon Sep 17 00:00:00 2001 From: Paul W Date: Mon, 4 Feb 2019 08:27:39 -0500 Subject: [PATCH] A Variety of Zoom Enhancements Once folks started using zoom, a variety of small enhancement requests came in. This PR covers all of them, covering several tickets. The issues resolved are: Closes #483. Zoom implemented on linux; in doing so remove the HOST_SUPPORTS_ZOOM switch, since all hosts support zoom. To make it testable, ahead of implementing DisplayInfo on linux, set the defaulted screen size to 1400x1050, a mid-range 15" laptop. Closes #433 Correct the error message at zoom time to explain we add a window-decoration-protection factor but don't show the confusing dimensions that result. Closes #473 Order and add separator to the setting menu to be more rational. Keep "About" at the end. Closes #457 If you ask for a zoom which outstrips screen parameters, rather than retain the current zoom look for the largest zoom that will fit those paramemters. Don't display the confusing-to-users message about how much space we are reserving for window decoration. --- .gitignore | 1 + src/common/gui/SurgeGUIEditor.cpp | 94 +++++++++++++++++++++---------- src/common/gui/SurgeGUIEditor.h | 21 ++++++- src/linux/DisplayInfoLinux.cpp | 4 +- 4 files changed, 86 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 7565480e3bc..d49907d5f0c 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ Makefile surge-*.make premake-stamp /Debug +src/linux/ScalablePiggy* diff --git a/src/common/gui/SurgeGUIEditor.cpp b/src/common/gui/SurgeGUIEditor.cpp index 6fdb1cfcf26..b057347f7e1 100644 --- a/src/common/gui/SurgeGUIEditor.cpp +++ b/src/common/gui/SurgeGUIEditor.cpp @@ -23,6 +23,10 @@ #include "UserInteractions.h" #include "DisplayInfo.h" +#include +#include +#include + #if TARGET_AUDIOUNIT #include "aulayer.h" #endif @@ -2425,8 +2429,6 @@ long SurgeGUIEditor::applyParameterOffset(long id) void SurgeGUIEditor::setZoomFactor(int zf) { -#if HOST_SUPPORTS_ZOOM - int minZoom = 50; if (zf < minZoom) { @@ -2451,22 +2453,36 @@ void SurgeGUIEditor::setZoomFactor(int zf) float baseW = (baseUISize->right - baseUISize->left); float baseH = (baseUISize->top - baseUISize->bottom); #endif - - // Leave enough room for window decoration with that .9. (You can probably do .95 on mac) - if (zf != 100.0 && ( - (baseW * zf / 100.0) > 0.9 * screenDim.getWidth() || - (baseH * zf / 100.0) > 0.9 * screenDim.getHeight() + + /* + ** Window decoration takes up some of the screen so don't zoom to full screen dimensions. + ** This heuristic seems to work on windows 10 and macos 10.14 weel enough. + ** Keep these as integers to be consistent wiht the other zoom factors, and to make + ** the error message cleaner. + */ +#ifdef WINDOWS + int maxScreenUsage = 90; +#else + int maxScreenUsage = 95; +#endif + + if (zf != 100.0 && zf > 100 && ( + (baseW * zf / 100.0) > maxScreenUsage * screenDim.getWidth() / 100.0 || + (baseH * zf / 100.0) > maxScreenUsage * screenDim.getHeight() / 100.0 ) ) { + int newZF = findLargestFittingZoomBetween(100.0 , zf, 5, maxScreenUsage, baseW, baseH); + zoomFactor = newZF; + std::ostringstream msg; - msg << "You attempted to resize Surge to a size larger than your screen. " - << "Your screen is " << screenDim.getWidth() << "x" << screenDim.getHeight() - << " and your zoom of " << zf << "% would make your Surge " - << baseW * zf / 100.0 << "x" << baseH * zf / 100.0 << "\n\n" - << "Retaining current zoom of " << zoomFactor << "%."; + msg << "Surge limits zoom levels so as not to grow Surge larger than your available screen. " + << "Your screen size is " << screenDim.getWidth() << "x" << screenDim.getHeight() << " " + << "and your target zoom of " << zf << "% would be too large." + << std::endl << std::endl + << "Surge is choosing the largest fitting zoom " << zoomFactor << "%."; Surge::UserInteractions::promptError(msg.str(), - "Screen too small for Zoom"); + "Limiting Zoom by Screen Size"); } else { @@ -2479,12 +2495,6 @@ void SurgeGUIEditor::setZoomFactor(int zf) int fullPhysicalZoomFactor = (int)(zf * dbs); CScalableBitmap::setPhysicalZoomFactor(fullPhysicalZoomFactor); -#else - /* - ** I don't support zoom, but lets at least keep my internal state consistent in case this gets called - */ - zoomFactor = zf; -#endif } void SurgeGUIEditor::showSettingsMenu(CRect &menuRect) @@ -2494,13 +2504,6 @@ void SurgeGUIEditor::showSettingsMenu(CRect &menuRect) int eid = 0; bool handled = false; - int id_about = eid; - settingsMenu->addEntry("About", eid++); - - int id_openmanual = eid; - settingsMenu->addEntry("Surge Manual", eid++); - -#if HOST_SUPPORTS_ZOOM // Zoom submenus COptionMenu *zoomSubMenu = new COptionMenu(menuRect, 0, 0, 0, 0, VSTGUI::COptionMenu::kNoDrawStyle); @@ -2537,8 +2540,15 @@ void SurgeGUIEditor::showSettingsMenu(CRect &menuRect) zoomSubMenu->addEntry(zcmd); zid++; } - settingsMenu->addEntry(zoomSubMenu, "Zoom"); -#endif // Supports Zoom + settingsMenu->addEntry(zoomSubMenu, "Zoom"); eid++; + + settingsMenu->addSeparator(eid++); + + int id_openmanual = eid; + settingsMenu->addEntry("Surge Manual", eid++); + + int id_about = eid; + settingsMenu->addEntry("About", eid++); frame->addView(settingsMenu); // add to frame settingsMenu->setDirty(); @@ -2579,7 +2589,7 @@ CPoint SurgeGUIEditor::getCurrentMouseLocationCorrectedForVSTGUIBugs() frame->getCurrentMouseLocation(where); where = frame->localToFrame(where); -#if ( TARGET_VST2 || TARGET_VST3 ) && HOST_SUPPORTS_ZOOM +#if ( TARGET_VST2 || TARGET_VST3 ) CGraphicsTransform vstfix = frame->getTransform().inverse(); vstfix.transform(where); vstfix.transform(where); @@ -2588,4 +2598,30 @@ CPoint SurgeGUIEditor::getCurrentMouseLocationCorrectedForVSTGUIBugs() return where; } +int SurgeGUIEditor::findLargestFittingZoomBetween(int zoomLow, // bottom of range + int zoomHigh, // top of range + int zoomQuanta, // step size + int percentageOfScreenAvailable, // How much to shrink actual screen + float baseW, + float baseH + ) +{ + // Here is a very crude implementation + int result = zoomHigh; + CRect screenDim = Surge::GUI::getScreenDimensions(getFrame()); + float sx = screenDim.getWidth() * percentageOfScreenAvailable / 100.0; + float sy = screenDim.getHeight() * percentageOfScreenAvailable / 100.0; + + while(result > zoomLow) + { + if(result * baseW / 100.0 <= sx && + result * baseH / 100.0 <= sy) + break; + result -= zoomQuanta; + } + if(result < zoomLow) + result = zoomLow; + + return result; +} //------------------------------------------------------------------------------------------------ diff --git a/src/common/gui/SurgeGUIEditor.h b/src/common/gui/SurgeGUIEditor.h index e3a77aa8a7b..a0cf262eb6c 100644 --- a/src/common/gui/SurgeGUIEditor.h +++ b/src/common/gui/SurgeGUIEditor.h @@ -139,6 +139,24 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi int getZoomFactor() { return zoomFactor; } void setZoomFactor(int zf); +private: + /** + * findLargestFittingZoomBetween + * + * Finds the largest zoom which will fit your current screen between a lower and upper bound. + * Will never return something smaller than lower or larger than upper. Default is as large as + * possible, quantized in units of zoomQuanta, with the maximum screen usage percentages + * protecting for screen real estate. The function also needs to know the 100% size of the UI + * the baseW and baseH) + * + * for instance findLargestFittingZoomBetween( 100, 200, 5, 90, bw, bh ) + * + * would find the largest possible zoom which uses at most 90% of your screen real estate but + * would also guarantee that the result % 5 == 0. + */ + int findLargestFittingZoomBetween(int zoomLow, int zoomHigh, int zoomQuanta, int percentageOfScreenAvailable, + float baseW, float baseH); + private: std::function< void(SurgeGUIEditor *) > zoom_callback; @@ -171,6 +189,3 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi VSTGUI::CVSTGUITimer* _idleTimer = nullptr; }; -#if MAC || WINDOWS -#define HOST_SUPPORTS_ZOOM 1 -#endif diff --git a/src/linux/DisplayInfoLinux.cpp b/src/linux/DisplayInfoLinux.cpp index 43f14ec6e06..9d9a9f577c8 100644 --- a/src/linux/DisplayInfoLinux.cpp +++ b/src/linux/DisplayInfoLinux.cpp @@ -17,9 +17,9 @@ float getDisplayBackingScaleFactor(CFrame *) CRect getScreenDimensions(CFrame *) { - Surge::UserInteractions::promptError("getScreenDimensions not implemented yet on linux.", + Surge::UserInteractions::promptError("getScreenDimensions not implemented yet on linux. Returning 1400x1050", "Software Error"); - return CRect(CPoint(0,0), CPoint(1024,768)); + return CRect(CPoint(0,0), CPoint(1400,1050)); // a typical mid-range 15" laptop } }