Merge pull request #1153 from redtide/hidpi

HiDPI: handle system scale factor in LV2, custom zoom
This commit is contained in:
redtide 2023-04-09 14:00:34 +02:00 committed by GitHub
commit 289d6efc25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 12 deletions

View file

@ -440,6 +440,22 @@ widget_class mainView {open
xywh {435 220 80 25} labelsize 14 textsize 14
class ValueMenu
}
Fl_Box {} {
label Zoom
xywh {555 195 95 25} labelsize 12 align 20
class Label
}
Fl_Spinner zoomMenu_ {
comment {tag=kTagZoomMenu}
xywh {680 195 100 25} labelsize 12 textsize 12
class OptionMenu
}
Fl_Button defaultZoomButton_ {
label {Set Default}
comment {tag=kTagSetDefaultZoom}
xywh {680 220 100 25} labelsize 12
class ValueButton
}
}
}
Fl_Box piano_ {

View file

@ -38,5 +38,7 @@ EditRange EditRange::get(EditId id)
return { 0, 0, 1 };
case EditId::UIActivePanel:
return { 0, 0, 255 };
case EditId::UIZoom:
return { 100, 100, 300 };
}
}

View file

@ -51,6 +51,7 @@ enum class EditId : int {
UINumPreloadedSamples,
UINumActiveVoices,
UIActivePanel,
UIZoom,
//
BackgroundImage,
//

View file

@ -18,6 +18,7 @@
#include "BitArray.h"
#include "Theme.h"
#include "plugin/MessageUtils.h"
#include "plugin/SfizzSettings.h"
#include <absl/strings/string_view.h>
#include <absl/strings/match.h>
#include <absl/strings/ascii.h>
@ -29,6 +30,7 @@
#include <unordered_map>
#include <algorithm>
#include <functional>
#include <iterator>
#include <type_traits>
#include <system_error>
#include <fstream>
@ -62,6 +64,8 @@ struct Editor::Impl : EditorController::Receiver,
std::string fallbackFilesDir_;
bool multi_ { false };
float zoom_ = 1.0f;
int currentKeyswitch_ = -1;
std::unordered_map<unsigned, std::string> keyswitchNames_;
@ -106,6 +110,8 @@ struct Editor::Impl : EditorController::Receiver,
kTagChooseUserFilesDir,
kTagAbout,
kTagThemeMenu,
kTagZoomMenu,
kTagSetDefaultZoom,
kTagFirstChangePanel,
kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1,
};
@ -140,6 +146,8 @@ struct Editor::Impl : EditorController::Receiver,
CTextLabel* keyswitchBadge_ = nullptr;
CTextLabel* lblHover_ = nullptr;
COptionMenu* themeMenu_ = nullptr;
COptionMenu* zoomMenu_ = nullptr;
STextButton* defaultZoomButton_ = nullptr;
std::unique_ptr<Theme> theme_;
STitleContainer* userFilesGroup_ = nullptr;
@ -272,6 +280,9 @@ struct Editor::Impl : EditorController::Receiver,
void onThemeChanged() override;
std::vector<std::function<void()>> OnThemeChanged;
// Zoom
void setZoom(int zoom);
// Misc
static std::string getUnicodeNoteName(unsigned key)
{
@ -315,8 +326,14 @@ void Editor::open(CFrame& frame)
getResourceBasePath().u8string().c_str());
impl.frame_ = &frame;
frame.addView(impl.mainView_.get());
SfizzSettings settings;
int zoom = atoi(settings.load_or("default_zoom", "100").c_str());
impl.setZoom(zoom);
fprintf(stderr, "[sfizz] zoom factor: %f\n", impl.frame_->getZoom());
impl.frameDisabler_ = makeOwned<SFrameDisabler>(&frame);
impl.memQueryTimer_ = makeOwned<CVSTGUITimer>([this](CVSTGUITimer*) {
@ -1167,6 +1184,7 @@ void Editor::Impl::createFrameContents()
adjustMinMaxToEditRange(freewheelingSampleQualitySlider_, EditId::FreewheelingSampleQuality);
adjustMinMaxToEditRange(freewheelingOscillatorQualitySlider_, EditId::FreewheelingOscillatorQuality);
adjustMinMaxToEditRange(sustainCancelsReleaseCheckbox_, EditId::SustainCancelsRelease);
adjustMinMaxToEditRange(zoomMenu_, EditId::UIZoom);
for (int value : {1, 2, 4, 8, 16, 32, 64, 96, 128, 160, 192, 224, 256})
numVoicesSlider_->addEntry(std::to_string(value), value);
@ -1175,6 +1193,7 @@ void Editor::Impl::createFrameContents()
int value = 1 << log2value;
oversamplingSlider_->addEntry(std::to_string(value) + "x", log2value);
}
oversamplingSlider_->setValueToStringFunction2(
[](float value, std::string& result, CParamDisplay*) -> bool
{
@ -1182,6 +1201,17 @@ void Editor::Impl::createFrameContents()
return true;
});
for (int value : { 100, 125, 150, 175, 200, 225, 250, 275, 300 }) {
zoomMenu_->addEntry(std::to_string(value) + "%", value);
}
zoomMenu_->setValueToStringFunction2(
[](float value, std::string& result, CParamDisplay*) -> bool
{
result = std::to_string(static_cast<int>(value) * 100) + "%";
return true;
});
for (int log2value = 10; log2value <= 16; ++log2value) {
int value = 1 << log2value;
char text[256];
@ -1978,6 +2008,29 @@ void Editor::Impl::setActivePanel(unsigned panelId)
}
}
void Editor::Impl::setZoom(int zoom)
{
if (!zoomMenu_)
return;
float zoomFactor = static_cast<float>(zoom) / 100;
std::vector<int> values =
{ 100, 125, 150, 175, 200, 225, 250, 275, 300 };
size_t pos = std::distance(values.cbegin(),
find(values.cbegin(), values.cend(), zoom));
if (pos < values.size()) {
zoom_ = zoomFactor;
zoomMenu_->setCurrent(pos);
frame_->setZoom(zoom_);
} else {
zoom_ = 1.0f;
zoomMenu_->setCurrent(0);
}
}
void Editor::Impl::formatLabel(CTextLabel* label, const char* fmt, ...)
{
va_list ap;
@ -2159,6 +2212,26 @@ void Editor::Impl::valueChanged(CControl* ctl)
}
break;
case kTagZoomMenu: {
std::vector<float> values =
{ 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0 };
auto zoom = values.at(value);
zoom_ = zoom;
#if 0
fprintf(stderr, "[sfizz] valueChanged: %f\n", zoom_);
// TODO: Recreate frame with the new size
frame_->setZoom(zoom_);
#endif
} break;
case kTagSetDefaultZoom: {
SfizzSettings settings;
char zoom[64];
sprintf(zoom, "%i", static_cast<int>(zoom_ * 100));
zoom[sizeof(zoom) - 1] = '\0';
settings.store("default_zoom", zoom);
} break;
default:
if (tag >= kTagFirstChangePanel && tag <= kTagLastChangePanel) {
int panelId = tag - kTagFirstChangePanel;

View file

@ -228,16 +228,24 @@ view__49->addView(view__87);
auto* const view__88 = createValueMenu(CRect(430, 110, 510, 135), kTagSetFreewheelingOscillatorQuality, "", kCenterText, 14);
freewheelingOscillatorQualitySlider_ = view__88;
view__49->addView(view__88);
auto* const view__89 = createPiano(CRect(0, 410, 800, 480), -1, "", kCenterText, 16);
piano_ = view__89;
view__0->addView(view__89);
auto* const view__90 = createLogicalGroup(CRect(5, 110, 795, 410), -1, "", kCenterText, 14);
subPanels_[kPanelGeneral] = view__90;
view__0->addView(view__90);
view__90->setVisible(false);
auto* const view__89 = createLabel(CRect(550, 85, 645, 110), -1, "Zoom", kLeftText, 12);
view__49->addView(view__89);
auto* const view__90 = createOptionMenu(CRect(675, 85, 775, 110), kTagZoomMenu, "", kCenterText, 12);
zoomMenu_ = view__90;
view__49->addView(view__90);
auto* const view__91 = createValueButton(CRect(675, 110, 775, 135), kTagSetDefaultZoom, "Set Default", kCenterText, 12);
defaultZoomButton_ = view__91;
view__49->addView(view__91);
auto* const view__92 = createPiano(CRect(0, 410, 800, 480), -1, "", kCenterText, 16);
piano_ = view__92;
view__0->addView(view__92);
auto* const view__93 = createLogicalGroup(CRect(5, 110, 795, 410), -1, "", kCenterText, 14);
subPanels_[kPanelGeneral] = view__93;
view__0->addView(view__93);
view__93->setVisible(false);
enterPalette(invertedPalette);
auto* const view__91 = createHoverBox(CRect(5, 105, 175, 130), -1, "", kCenterText, 14);
lblHover_ = view__91;
view__0->addView(view__91);
view__91->setVisible(false);
auto* const view__94 = createHoverBox(CRect(5, 105, 175, 130), -1, "", kCenterText, 14);
lblHover_ = view__94;
view__0->addView(view__94);
view__94->setVisible(false);
enterPalette(defaultPalette);

View file

@ -46,6 +46,11 @@
#include <lv2/patch/patch.h>
#include <lv2/urid/urid.h>
#include <lv2/instance-access/instance-access.h>
#ifndef LV2_UI__scaleFactor
#define LV2_UI__scaleFactor LV2_UI_PREFIX "scaleFactor"
#endif
#include <ghc/fs_std.hpp>
#include <string>
#include <memory>
@ -113,6 +118,10 @@ struct sfizz_ui_t : EditorController, VSTGUIEditorInterface {
LV2_URID patch_set_uri;
LV2_URID patch_property_uri;
LV2_URID patch_value_uri;
#if !defined(__APPLE__)
LV2_URID opt_scalefactor_uri;
float scale_factor = 0.0f;
#endif
LV2_URID sfizz_sfz_file_uri;
LV2_URID sfizz_scala_file_uri;
LV2_URID sfizz_osc_blob_uri;
@ -180,6 +189,7 @@ instantiate(const LV2UI_Descriptor *descriptor,
LV2_URID_Map *map = nullptr;
LV2_URID_Unmap *unmap = nullptr;
const LV2_Options_Option* options = nullptr;
for (const LV2_Feature *const *f = features; *f; f++)
{
@ -195,6 +205,8 @@ instantiate(const LV2UI_Descriptor *descriptor,
parentWindowId = (**f).data;
else if (!strcmp((**f).URI, LV2_INSTANCE_ACCESS_URI))
self->plugin = (sfizz_plugin_t *)(**f).data;
else if (!strcmp((**f).URI, LV2_OPTIONS__options))
options = (const LV2_Options_Option*)(**f).data; // scaleFactor only ATM
}
// The map feature is required
@ -213,6 +225,9 @@ instantiate(const LV2UI_Descriptor *descriptor,
self->atom_path_uri = map->map(map->handle, LV2_ATOM__Path);
self->atom_urid_uri = map->map(map->handle, LV2_ATOM__URID);
self->midi_event_uri = map->map(map->handle, LV2_MIDI__MidiEvent);
#if !defined(__APPLE__)
self->opt_scalefactor_uri = map->map(map->handle, LV2_UI__scaleFactor);
#endif
self->patch_get_uri = map->map(map->handle, LV2_PATCH__Get);
self->patch_set_uri = map->map(map->handle, LV2_PATCH__Set);
self->patch_property_uri = map->map(map->handle, LV2_PATCH__property);
@ -224,6 +239,22 @@ instantiate(const LV2UI_Descriptor *descriptor,
self->sfizz_audio_level_uri = map->map(map->handle, SFIZZ__AudioLevel);
self->ccmap.reset(sfizz_lv2_ccmap_create(map));
#if !defined(__APPLE__)
if (options != nullptr) {
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == self->opt_scalefactor_uri) {
if (options[i].type == self->atom_float_uri) {
self->scale_factor = *(const float*)options[i].value;
fprintf(stderr, "[sfizz] scale factor: %f\n", self->scale_factor);
} else {
fprintf(stderr, "[sfizz] Host provides UI scale factor but has wrong value type\n");
}
}
}
}
#endif
// set up the resource path
// * on Linux, this is determined by going 2 folders back from the SO path
// name, and appending "Contents/Resources" (not overridable)
@ -281,8 +312,19 @@ instantiate(const LV2UI_Descriptor *descriptor,
*widget = reinterpret_cast<LV2UI_Widget>(uiFrame->getPlatformFrame()->getPlatformRepresentation());
#if !defined (__APPLE__)
float scaleFactor = uiFrame->getZoom() * self->scale_factor;
uiFrame->setZoom(scaleFactor);
fprintf(stderr, "[sfizz] zoom factor: %f\n", scaleFactor);
int width = Editor::viewWidth * scaleFactor;
int height = Editor::viewHeight * scaleFactor;
#else
int width = Editor::viewWidth;
int height = Editor::viewHeight;
#endif
if (self->resize)
self->resize->ui_resize(self->resize->handle, Editor::viewWidth, Editor::viewHeight);
self->resize->ui_resize(self->resize->handle, width, height);
// send a request to receive all parameters
uint8_t buffer[256];

View file

@ -1,4 +1,5 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix opts: <http://lv2plug.in/ns/ext/options#> .
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@ -10,6 +11,7 @@
lv2:optionalFeature ui:resize ;
lv2:optionalFeature ui:parent ;
lv2:optionalFeature ui:touch ;
opts:supportedOption ui:scaleFactor ;
lv2:requiredFeature urid:map ;
lv2:requiredFeature urid:unmap ;
lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> .