diff --git a/CMakeLists.txt b/CMakeLists.txt index fc2d6dc7..8628379f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -593,6 +593,7 @@ src/gui/piano.cpp src/gui/presets.cpp src/gui/regView.cpp src/gui/sampleEdit.cpp +src/gui/scaling.cpp src/gui/settings.cpp src/gui/songInfo.cpp src/gui/songNotes.cpp diff --git a/extern/imgui_patched/backends/imgui_impl_sdl.cpp b/extern/imgui_patched/backends/imgui_impl_sdl.cpp index 2424dd41..e7ae8d07 100644 --- a/extern/imgui_patched/backends/imgui_impl_sdl.cpp +++ b/extern/imgui_patched/backends/imgui_impl_sdl.cpp @@ -276,9 +276,6 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_MOUSEMOTION: { ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); -#ifdef __APPLE__ - -#endif if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { int window_x, window_y; @@ -286,16 +283,14 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) mouse_pos.x += window_x; mouse_pos.y += window_y; } -#ifdef __APPLE__ - // Fix for high DPI mac - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) - { - // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! - mouse_pos.x *= std::ceil(platform_io.Monitors[0].DpiScale); - mouse_pos.y *= std::ceil(platform_io.Monitors[0].DpiScale); - } -#endif + // Fix for high DPI mac/idevice/wayland + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) + { + // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! + mouse_pos.x *= std::ceil(platform_io.Monitors[0].DpiScale); + mouse_pos.y *= std::ceil(platform_io.Monitors[0].DpiScale); + } io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); return true; } @@ -551,16 +546,14 @@ static void ImGui_ImplSDL2_UpdateMouseData() mouse_x -= window_x; mouse_y -= window_y; } -#ifdef __APPLE__ - // Fix for high DPI mac - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) - { - // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! - mouse_x *= std::ceil(platform_io.Monitors[0].DpiScale); - mouse_y *= std::ceil(platform_io.Monitors[0].DpiScale); - } -#endif + // Fix for high DPI mac/idevice/wayland + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) + { + // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! + mouse_x *= std::ceil(platform_io.Monitors[0].DpiScale); + mouse_y *= std::ceil(platform_io.Monitors[0].DpiScale); + } io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } } @@ -669,13 +662,7 @@ static void ImGui_ImplSDL2_UpdateMonitors() monitor.WorkSize = ImVec2((float)r.w, (float)r.h); #endif #if SDL_HAS_PER_MONITOR_DPI -#ifdef __APPLE__ - monitor.DpiScale=getMacDPIScale(); -#else - float dpi = 0.0f; - if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL)) - monitor.DpiScale = dpi / 96.0f; -#endif + monitor.DpiScale = 1.0f; #endif platform_io.Monitors.push_back(monitor); } @@ -701,15 +688,14 @@ void ImGui_ImplSDL2_NewFrame() if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); -#if defined(__APPLE__) - // On Apple, The window size is reported in Low DPI, even when running in high DPI mode + // On Apple and Wayland, The window size is reported in Low DPI, even when running in high DPI mode ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f && display_h != h) + if (!platform_io.Monitors.empty() /*&& platform_io.Monitors[0].DpiScale > 1.0f*/ && display_h != h) { io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); io.DisplaySize = ImVec2((float)display_w, (float)display_h); + platform_io.Monitors[0].DpiScale=(float)display_w/(float)w; } -#endif // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) static Uint64 frequency = SDL_GetPerformanceFrequency(); diff --git a/src/engine/engine.h b/src/engine/engine.h index f4ed7cf5..b30f52b1 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -47,8 +47,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev121" -#define DIV_ENGINE_VERSION 121 +#define DIV_VERSION "dev122" +#define DIV_ENGINE_VERSION 122 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 99a27926..809cd1a3 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -23,18 +23,13 @@ const char* aboutLine[]={ "tildearrow", - "is not so happy to present", + "is proud to present", "", ("Furnace " DIV_VERSION), "", "the biggest multi-system chiptune tracker!", "featuring DefleMask song compatibility.", "", - "what a mess of a versioning scheme we have...", - "I mean it! these pre-releases are like normal releases", - "by now but only because I promised you to have SNES in", - "0.6pre2 I am doing this whole mess...", - "", "> CREDITS <", "", "-- program --", @@ -187,7 +182,7 @@ void FurnaceGUI::drawAbout() { // do stuff if (ImGui::Begin("About Furnace",NULL,ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoTitleBar)) { ImGui::SetWindowPos(ImVec2(0,0)); - ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetWindowSize(ImVec2(canvasW,canvasH)); ImGui::PushFont(bigFont); ImDrawList* dl=ImGui::GetWindowDrawList(); float r=0; @@ -195,47 +190,47 @@ void FurnaceGUI::drawAbout() { float b=0; float peakMix=settings.partyTime?((peak[0]+peak[1])*0.5):0.3; ImGui::ColorConvertHSVtoRGB(aboutHue,1.0,0.25+MIN(0.75f,peakMix*0.75f),r,g,b); - dl->AddRectFilled(ImVec2(0,0),ImVec2(scrW*dpiScale,scrH*dpiScale),0xff000000); + dl->AddRectFilled(ImVec2(0,0),ImVec2(canvasW,canvasH),0xff000000); bool skip=false; bool skip2=false; - for (int i=(-80-sin(double(aboutSin)*2*M_PI/120.0)*80.0)*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.25,g*0.25,b*0.25,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.25,g*0.25,b*0.25,1.0))); } } skip=false; skip2=false; - for (int i=(-80-cos(double(aboutSin)*2*M_PI/120.0)*80.0)*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.5,g*0.5,b*0.5,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.5,g*0.5,b*0.5,1.0))); } } skip=false; skip2=false; - for (int i=(-160+fmod(aboutSin*2,160))*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.75,g*0.75,b*0.75,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.75,g*0.75,b*0.75,1.0))); } } for (size_t i=0; iscrH*dpiScale) continue; + double posX=(canvasW/2.0)+(sin(double(i)*0.5+double(aboutScroll)/(90.0*dpiScale))*120*dpiScale)-(ImGui::CalcTextSize(aboutLine[i]).x*0.5); + double posY=(canvasH-aboutScroll+42*i*dpiScale); + if (posY<-80*dpiScale || posY>canvasH) continue; dl->AddText(bigFont,bigFont->FontSize, ImVec2(posX+dpiScale,posY+dpiScale), 0xff000000,aboutLine[i]); @@ -257,12 +252,12 @@ void FurnaceGUI::drawAbout() { float timeScale=60.0f*ImGui::GetIO().DeltaTime; aboutHue+=(0.001+peakMix*0.004)*timeScale; - aboutScroll+=(2+(peakMix>0.78)*3)*timeScale; + aboutScroll+=(2+(peakMix>0.78)*3)*timeScale*dpiScale; aboutSin+=(1+(peakMix>0.75)*2)*timeScale; while (aboutHue>1) aboutHue--; while (aboutSin>=2400) aboutSin-=2400; - if (aboutScroll>(42*aboutCount+scrH)) aboutScroll=-20; + if (aboutScroll>(42*dpiScale*aboutCount+canvasH)) aboutScroll=-20*dpiScale; WAKE_UP; } diff --git a/src/gui/chanOsc.cpp b/src/gui/chanOsc.cpp index 89b89801..851ca6ed 100644 --- a/src/gui/chanOsc.cpp +++ b/src/gui/chanOsc.cpp @@ -109,7 +109,7 @@ void FurnaceGUI::drawChanOsc() { nextWindow=GUI_WINDOW_NOTHING; } if (!chanOscOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Oscilloscope (per-channel)",&chanOscOpen,globalWinFlags|((chanOscOptions)?0:ImGuiWindowFlags_NoTitleBar))) { bool centerSettingReset=false; ImDrawList* dl=ImGui::GetWindowDrawList(); diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 38275c74..68130d9d 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -42,7 +42,7 @@ void FurnaceGUI::drawDebug() { nextWindow=GUI_WINDOW_NOTHING; } if (!debugOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Debug",&debugOpen,globalWinFlags|ImGuiWindowFlags_NoDocking)) { ImGui::Text("NOTE: use with caution."); if (ImGui::TreeNode("Debug Controls")) { diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index 1d0e2a25..e3e348c1 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -38,8 +38,8 @@ void FurnaceGUI::drawMobileControls() { mobileMenuPos=0.0f; } } - ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*scrH*dpiScale)-(0.16*scrW*dpiScale)):ImVec2(0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.16*scrW*dpiScale):ImVec2(0.16*scrH*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*canvasH)-(0.16*canvasW)):ImVec2(0.5*canvasW*mobileMenuPos,0.0f)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.16*canvasW):ImVec2(0.16*canvasH,canvasH)); if (ImGui::Begin("Mobile Controls",NULL,ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { float avail=portrait?ImGui::GetContentRegionAvail().y:ImGui::GetContentRegionAvail().x; ImVec2 buttonSize=ImVec2(avail,avail); @@ -101,8 +101,8 @@ void FurnaceGUI::drawMobileControls() { if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_EDIT_CONTROLS; ImGui::End(); - ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*scrH*dpiScale)):ImVec2(0.5*scrW*dpiScale*(mobileMenuPos-1.0),0.0f)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.65*scrH*dpiScale):ImVec2(0.5*scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*canvasH)):ImVec2(0.5*canvasW*(mobileMenuPos-1.0),0.0f)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.65*canvasH):ImVec2(0.5*canvasW,canvasH)); if (ImGui::Begin("Mobile Menu",NULL,ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { if (ImGui::BeginTable("SceneSel",5)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,1.0f); diff --git a/src/gui/effectList.cpp b/src/gui/effectList.cpp index 2c71b567..604204b8 100644 --- a/src/gui/effectList.cpp +++ b/src/gui/effectList.cpp @@ -9,7 +9,7 @@ void FurnaceGUI::drawEffectList() { nextWindow=GUI_WINDOW_NOTHING; } if (!effectListOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(60.0f*dpiScale,20.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(60.0f*dpiScale,20.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Effect List",&effectListOpen,globalWinFlags)) { ImGui::Text("Chip at cursor: %s",e->getSystemName(e->sysOfChan[cursor.xCoarse])); if (ImGui::BeginTable("effectList",2)) { diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 428fce5a..91b49421 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -494,7 +494,7 @@ void FurnaceGUI::drawFindReplace() { nextWindow=GUI_WINDOW_NOTHING; } if (!findOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Find/Replace",&findOpen,globalWinFlags)) { if (curQuery.empty()) { curQuery.push_back(FurnaceGUIFindQuery()); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a66567ed..45c4f018 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1,3 +1,5 @@ +#define _USE_MATH_DEFINES +// OK, sorry for inserting the define here but I'm so tired of this extension /** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2022 tildearrow and contributors @@ -20,7 +22,7 @@ // I hate you clangd extension! // how about you DON'T insert random headers before this freaking important // define!!!!!! -#define _USE_MATH_DEFINES + #include "gui.h" #include "util.h" #include "icon.h" @@ -36,17 +38,12 @@ #include "plot_nolerp.h" #include "guiConst.h" #include "intConst.h" +#include "scaling.h" #include #include #include #include -#ifdef __APPLE__ -extern "C" { -#include "macstuff.h" -} -#endif - #ifdef _WIN32 #include #include @@ -2754,12 +2751,8 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { TouchPoint* point=NULL; FIND_POINT(point,-1); if (point!=NULL) { - point->x=ev.motion.x; - point->y=ev.motion.y; -#ifdef __APPLE__ - point->x*=dpiScale; - point->y*=dpiScale; -#endif + point->x=(double)ev.motion.x*((double)canvasW/(double)scrW); + point->y=(double)ev.motion.y*((double)canvasH/(double)scrH); } break; } @@ -2800,8 +2793,8 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { if (point!=NULL) { float prevX=point->x; float prevY=point->y; - point->x=ev.tfinger.x*scrW*dpiScale; - point->y=ev.tfinger.y*scrH*dpiScale; + point->x=ev.tfinger.x*canvasW; + point->y=ev.tfinger.y*canvasH; point->z=ev.tfinger.pressure; if (point->id==0) { @@ -2820,7 +2813,7 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { break; } } - TouchPoint newPoint(ev.tfinger.fingerId,ev.tfinger.x*scrW*dpiScale,ev.tfinger.y*scrH*dpiScale,ev.tfinger.pressure); + TouchPoint newPoint(ev.tfinger.fingerId,ev.tfinger.x*canvasW,ev.tfinger.y*canvasH,ev.tfinger.pressure); activePoints.push_back(newPoint); pressedPoints.push_back(newPoint); @@ -2986,16 +2979,10 @@ bool FurnaceGUI::loop() { if (!doThreadedInput) processEvent(&ev); switch (ev.type) { case SDL_MOUSEMOTION: { - int motionX=ev.motion.x; - int motionY=ev.motion.y; - int motionXrel=ev.motion.xrel; - int motionYrel=ev.motion.yrel; -#ifdef __APPLE__ - motionX*=dpiScale; - motionY*=dpiScale; - motionXrel*=dpiScale; - motionYrel*=dpiScale; -#endif + int motionX=(double)ev.motion.x*((double)canvasW/(double)scrW); + int motionY=(double)ev.motion.y*((double)canvasH/(double)scrH); + int motionXrel=(double)ev.motion.xrel*((double)canvasW/(double)scrW); + int motionYrel=(double)ev.motion.yrel*((double)canvasH/(double)scrH); pointMotion(motionX,motionY,motionXrel,motionYrel); break; } @@ -3012,13 +2999,8 @@ bool FurnaceGUI::loop() { case SDL_WINDOWEVENT: switch (ev.window.event) { case SDL_WINDOWEVENT_RESIZED: -#ifdef __APPLE__ scrW=ev.window.data1; scrH=ev.window.data2; -#else - scrW=ev.window.data1/dpiScale; - scrH=ev.window.data2/dpiScale; -#endif portrait=(scrWAddRectFilled(ImVec2(0.0f,0.0f),ImVec2(scrW*dpiScale,scrH*dpiScale),ImGui::ColorConvertFloat4ToU32(uiColors[GUI_COLOR_MODAL_BACKDROP])); + dl->AddRectFilled(ImVec2(0.0f,0.0f),ImVec2(canvasW,canvasH),ImGui::ColorConvertFloat4ToU32(uiColors[GUI_COLOR_MODAL_BACKDROP])); ImGui::EndPopup(); } #endif - if (fileDialog->render(ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { + if (fileDialog->render(ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(canvasW,canvasH))) { bool openOpen=false; //ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard; if ((curFileDialog==GUI_FILE_INS_OPEN || curFileDialog==GUI_FILE_INS_OPEN_REPLACE) && prevIns!=-3) { @@ -4348,9 +4333,9 @@ bool FurnaceGUI::loop() { ImGui::EndPopup(); } - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::BeginPopupModal("New Song",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) { - ImGui::SetWindowPos(ImVec2(((scrW*dpiScale)-ImGui::GetWindowSize().x)*0.5,((scrH*dpiScale)-ImGui::GetWindowSize().y)*0.5)); + ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5)); drawNewSong(); ImGui::EndPopup(); } @@ -4718,8 +4703,8 @@ bool FurnaceGUI::loop() { } bool anySelected=false; float sizeY=ImGui::GetFrameHeightWithSpacing()*pendingIns.size(); - if (sizeY>(scrH-180.0)*dpiScale) { - sizeY=(scrH-180.0)*dpiScale; + if (sizeY>(canvasH-180.0*dpiScale)) { + sizeY=canvasH-180.0*dpiScale; if (sizeY<60.0*dpiScale) sizeY=60.0*dpiScale; } if (ImGui::BeginTable("PendingInsList",1,ImGuiTableFlags_ScrollY,ImVec2(0.0f,sizeY))) { @@ -4898,9 +4883,7 @@ bool FurnaceGUI::loop() { } bool FurnaceGUI::init() { -#ifndef __APPLE__ - float dpiScaleF; -#endif + logI("initializing GUI."); String homeDir=getHomeDir(); workingDir=e->getConfString("lastDir",homeDir); @@ -5004,15 +4987,49 @@ bool FurnaceGUI::init() { } } - if (settings.dpiScale>=0.5f) { - dpiScale=settings.dpiScale; - } - initSystemPresets(); e->setAutoNotePoly(noteInputPoly); + SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,"1"); + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS,"0"); + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS,"0"); + // don't disable compositing on KWin +#if SDL_VERSION_ATLEAST(2,0,22) + logV("setting window type to NORMAL."); + SDL_SetHint(SDL_HINT_X11_WINDOW_TYPE,"_NET_WM_WINDOW_TYPE_NORMAL"); +#endif + + // initialize SDL + SDL_Init(SDL_INIT_VIDEO); + + const char* videoBackend=SDL_GetCurrentVideoDriver(); + if (videoBackend!=NULL) { + logV("video backend: %s",videoBackend); + if (strcmp(videoBackend,"wayland")==0 || + strcmp(videoBackend,"cocoa")==0 || + strcmp(videoBackend,"uikit")==0) { + sysManagedScale=true; + logV("scaling managed by system."); + } else { + logV("scaling managed by application."); + } + } else { + logV("could not get video backend name!"); + } + + // get scale factor + if (settings.dpiScale>=0.5f) { + logD("setting UI scale factor from config (%f).",settings.dpiScale); + dpiScale=settings.dpiScale; + } else { + logD("auto-detecting UI scale factor."); + dpiScale=getScaleFactor(videoBackend); + logD("scale factor: %f",dpiScale); + } + #if !(defined(__APPLE__) || defined(_WIN32)) + // get the icon (on macOS and Windows the icon is bundled with the app) unsigned char* furIcon=getFurnaceIcon(); SDL_Surface* icon=SDL_CreateRGBSurfaceFrom(furIcon,256,256,32,256*4,0xff,0xff00,0xff0000,0xff000000); #endif @@ -5032,20 +5049,26 @@ bool FurnaceGUI::init() { portrait=(scrWgetConfInt("configVersion",0)<122 && !sysManagedScale) { + logD("scaling window size to scale factor because configVersion is not present."); + scrW*=dpiScale; + scrH*=dpiScale; + } + + // predict the canvas size + if (sysManagedScale) { + canvasW=scrW*dpiScale; + canvasH=scrH*dpiScale; + } else { + canvasW=scrW; + canvasH=scrH; + } + +#ifndef IS_MOBILE SDL_Rect displaySize; #endif - SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,"1"); - SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS,"0"); - SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS,"0"); - // don't disable compositing on KWin -#if SDL_VERSION_ATLEAST(2,0,22) - SDL_SetHint(SDL_HINT_X11_WINDOW_TYPE,"_NET_WM_WINDOW_TYPE_NORMAL"); -#endif - - SDL_Init(SDL_INIT_VIDEO); - #ifndef IS_MOBILE // if window would spawn out of bounds, force it to be get default position if (!detectOutOfBoundsWindow()) { @@ -5055,46 +5078,43 @@ bool FurnaceGUI::init() { } #endif - sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); + logV("window size: %dx%d",scrW,scrH); + + sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW,scrH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); if (sdlWin==NULL) { lastError=fmt::sprintf("could not open window! %s",SDL_GetError()); return false; } -#ifndef __APPLE__ - if (settings.dpiScale<0.5f) { - // TODO: replace with a function to actually detect the display scaling factor as it's unreliable. - SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWin),&dpiScaleF,NULL,NULL); - dpiScale=round(dpiScaleF/96.0f); - if (dpiScale<1) dpiScale=1; #ifndef IS_MOBILE - if (dpiScale!=1) { - if (!fullScreen) { - SDL_SetWindowSize(sdlWin,scrW*dpiScale,scrH*dpiScale); - } + if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) { + bool mustChange=false; + if (scrW>((displaySize.w)-48) && scrH>((displaySize.h)-64)) { + // maximize + SDL_MaximizeWindow(sdlWin); + logD("maximizing as it doesn't fit (%dx%d+%d+%d).",displaySize.w,displaySize.h,displaySize.x,displaySize.y); } - - if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) { - if (scrW>((displaySize.w/dpiScale)-48) && scrH>((displaySize.h/dpiScale)-64)) { - // maximize - SDL_MaximizeWindow(sdlWin); - } - if (scrW>displaySize.w/dpiScale) scrW=(displaySize.w/dpiScale)-32; - if (scrH>displaySize.h/dpiScale) scrH=(displaySize.h/dpiScale)-32; + if (scrW>displaySize.w) { + scrW=(displaySize.w)-32; + mustChange=true; + } + if (scrH>displaySize.h) { + scrH=(displaySize.h)-32; + mustChange=true; + } + if (mustChange) { portrait=(scrWsetConf("configVersion",(int)DIV_ENGINE_VERSION); + e->setConf("lastDir",workingDir); e->setConf("lastDirSong",workingDirSong); e->setConf("lastDirIns",workingDirIns); @@ -5353,11 +5385,14 @@ FurnaceGUI::FurnaceGUI(): scrH(800), scrConfW(1280), scrConfH(800), + canvasW(1280), + canvasH(800), scrX(SDL_WINDOWPOS_CENTERED), scrY(SDL_WINDOWPOS_CENTERED), scrConfX(SDL_WINDOWPOS_CENTERED), scrConfY(SDL_WINDOWPOS_CENTERED), scrMax(false), + sysManagedScale(false), dpiScale(1), aboutScroll(0), aboutSin(0), diff --git a/src/gui/gui.h b/src/gui/gui.h index fc47d6d8..dd3a02af 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1062,9 +1062,9 @@ class FurnaceGUI { FurnaceGUIFileDialog* fileDialog; - int scrW, scrH, scrConfW, scrConfH; + int scrW, scrH, scrConfW, scrConfH, canvasW, canvasH; int scrX, scrY, scrConfX, scrConfY; - bool scrMax; + bool scrMax, sysManagedScale; double dpiScale; diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 8cfbf9ec..2894f434 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1903,12 +1903,12 @@ void FurnaceGUI::drawInsEdit() { } if (!insEditOpen) return; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } else { - ImGui::SetNextWindowSizeConstraints(ImVec2(440.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(440.0f*dpiScale,400.0f*dpiScale),ImVec2(canvasW,canvasH)); } if (ImGui::Begin("Instrument Editor",&insEditOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { if (curIns<0 || curIns>=(int)e->song.ins.size()) { diff --git a/src/gui/mixer.cpp b/src/gui/mixer.cpp index 4897c64a..019336ae 100644 --- a/src/gui/mixer.cpp +++ b/src/gui/mixer.cpp @@ -27,7 +27,7 @@ void FurnaceGUI::drawMixer() { nextWindow=GUI_WINDOW_NOTHING; } if (!mixerOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Mixer",&mixerOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { char id[32]; if (ImGui::SliderFloat("Master Volume",&e->song.masterVol,0,3,"%.2fx")) { diff --git a/src/gui/osc.cpp b/src/gui/osc.cpp index 176d7d54..7791e8e5 100644 --- a/src/gui/osc.cpp +++ b/src/gui/osc.cpp @@ -84,7 +84,7 @@ void FurnaceGUI::drawOsc() { nextWindow=GUI_WINDOW_NOTHING; } if (!oscOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (settings.oscTakesEntireWindow) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0)); diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index 385441d4..00e9b510 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -376,8 +376,8 @@ void FurnaceGUI::drawPattern() { } ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0.0f,0.0f)); if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } diff --git a/src/gui/piano.cpp b/src/gui/piano.cpp index 082cc65e..c0664e98 100644 --- a/src/gui/piano.cpp +++ b/src/gui/piano.cpp @@ -54,7 +54,7 @@ void FurnaceGUI::drawPiano() { if (!pianoOpen) return; if (mobileUI) { ImGui::SetNextWindowPos(ImVec2(patWindowPos.x,patWindowPos.y+patWindowSize.y)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.4*scrW*dpiScale):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),0.3*scrH*dpiScale)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.4*canvasW):ImVec2(canvasW-(0.16*canvasH),0.3*canvasH)); } if (ImGui::Begin("Piano",&pianoOpen,((pianoOptions)?0:ImGuiWindowFlags_NoTitleBar)|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { bool oldPianoKeyPressed[180]; diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 1d1b4e97..2dc12ad5 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -39,8 +39,8 @@ void FurnaceGUI::drawSampleEdit() { } if (!sampleEditOpen) return; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } diff --git a/src/gui/scaling.cpp b/src/gui/scaling.cpp new file mode 100644 index 00000000..c1fd5bcc --- /dev/null +++ b/src/gui/scaling.cpp @@ -0,0 +1,207 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "scaling.h" +#include "../ta-log.h" +#include + +#ifdef _WIN32 +#include +typedef HRESULT (*GDFM)(HMONITOR,int,UINT*,UINT*); +#endif + +#ifdef __APPLE__ +extern "C" { +#include "macstuff.h" +} +#endif + +#if defined(__unix__) || defined(ANDROID) +#include +typedef void* (*XOD)(const char*); +typedef int (*XCD)(void*); +typedef int (*XDS)(void*); +typedef int (*XDW)(void*,int); +#endif + +double getScaleFactor(const char* driverHint) { + double ret=1.0; + + // Windows +#ifdef _WIN32 + POINT nullPoint; + nullPoint.x=-1; + nullPoint.y=-1; + HMONITOR disp=MonitorFromPoint(nullPoint,MONITOR_DEFAULTTOPRIMARY); + + if (disp==NULL) { + logW("could not find a monitor - no scaling detection available!"); + return 1.0; + } + + HMODULE shcore=LoadLibraryW(L"shcore.dll"); + if (shcore==NULL) { + logW("could not find shcore.dll (%.8x) - no scaling detection available!",GetLastError()); + return 1.0; + } + GDFM ta_GetDpiForMonitor=(GDFM)GetProcAddress(shcore,"GetDpiForMonitor"); + if (ta_GetDpiForMonitor==NULL) { + logW("GetDpiForMonitor not found (%.8x) - no scaling detection available!",GetLastError()); + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + return 1.0; + } + + unsigned int dpiX=96; + unsigned int dpiY=96; + HRESULT result=ta_GetDpiForMonitor(disp,0,&dpiX,&dpiY); + if (result!=S_OK) { + logW("GetDpiForMonitor failure (%.8x) - no scaling detection available!",result); + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + return 1.0; + } + + ret=(double)(dpiX+dpiY)/192.0; + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + + return ret; +#endif + + // macOS - backingScaleFactor +#ifdef __APPLE__ + if (driverHint==NULL) { + return getMacDPIScale(); + } else if (strcmp(driverHint,"cocoa")==0 || strcmp(driverHint,"uikit")==0) { + return getMacDPIScale(); + } +#endif + +#if defined(__unix__) || defined(ANDROID) + if (driverHint==NULL) { + return ret; + } + + // X11 + if (strcmp(driverHint,"x11")==0) { + void* libX11=dlopen("libX11.so",RTLD_LAZY|RTLD_LOCAL); + if (libX11==NULL) { + logW("could not load libX11.so (%s) - no scaling detection available!",dlerror()); + return 1.0; + } + + XOD ta_XOpenDisplay=(XOD)dlsym(libX11,"XOpenDisplay"); + if (ta_XOpenDisplay==NULL) { + logW("XOpenDisplay not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XCD ta_XCloseDisplay=(XCD)dlsym(libX11,"XCloseDisplay"); + if (ta_XCloseDisplay==NULL) { + logW("XCloseDisplay not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDS ta_XDefaultScreen=(XDS)dlsym(libX11,"XDefaultScreen"); + if (ta_XDefaultScreen==NULL) { + logW("XDefaultScreen not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDW ta_XDisplayWidth=(XDW)dlsym(libX11,"XDisplayWidth"); + if (ta_XDisplayWidth==NULL) { + logW("XDisplayWidth not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDW ta_XDisplayWidthMM=(XDW)dlsym(libX11,"XDisplayWidthMM"); + if (ta_XDisplayWidthMM==NULL) { + logW("XDisplayWidthMM not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + // dl mess + void* disp=NULL; + int screen=0; + int dpi=96; + + disp=ta_XOpenDisplay(NULL); + if (disp==NULL) { + logW("couldn't open X display - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + screen=ta_XDefaultScreen(disp); + + dpi=(int)(0.5+(25.4*(double)ta_XDisplayWidth(disp,screen)/(double)ta_XDisplayWidthMM(disp,screen))); + + ta_XCloseDisplay(disp); + + ret=round(dpi/96.0); + + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + + return ret; + } + + // Wayland + if (strcmp(driverHint,"wayland")==0) { + // give up (we handle scaling factor detection after window creation) + return 1.0; + } +#endif + + // SDL fallback + float dpiScaleF=96.0f; + if (SDL_GetDisplayDPI(0,&dpiScaleF,NULL,NULL)==0) { + ret=round(dpiScaleF/96.0f); + if (ret<1) ret=1; + } + + // couldn't detect scaling factor :< + return ret; +} diff --git a/src/gui/scaling.h b/src/gui/scaling.h new file mode 100644 index 00000000..ce1a364a --- /dev/null +++ b/src/gui/scaling.h @@ -0,0 +1,20 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +double getScaleFactor(const char* driverHint); \ No newline at end of file diff --git a/src/gui/subSongs.cpp b/src/gui/subSongs.cpp index f076298f..a6eb70f0 100644 --- a/src/gui/subSongs.cpp +++ b/src/gui/subSongs.cpp @@ -11,7 +11,7 @@ void FurnaceGUI::drawSubSongs() { nextWindow=GUI_WINDOW_NOTHING; } if (!subSongsOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Subsongs",&subSongsOpen,globalWinFlags)) { char id[1024]; ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-ImGui::GetFrameHeightWithSpacing()*2.0f-ImGui::GetStyle().ItemSpacing.x); diff --git a/src/gui/volMeter.cpp b/src/gui/volMeter.cpp index 7f68709c..d058e31f 100644 --- a/src/gui/volMeter.cpp +++ b/src/gui/volMeter.cpp @@ -28,7 +28,7 @@ void FurnaceGUI::drawVolMeter() { } if (!volMeterOpen) return; if (--isClipping<0) isClipping=0; - ImGui::SetNextWindowSizeConstraints(ImVec2(6.0f*dpiScale,6.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(6.0f*dpiScale,6.0f*dpiScale),ImVec2(canvasW,canvasH)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0)); diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 41ac5cbf..4054a66b 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -177,12 +177,12 @@ void FurnaceGUI::drawWaveEdit() { if (!waveEditOpen) return; float wavePreview[257]; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } else { - ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f*dpiScale,300.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f*dpiScale,300.0f*dpiScale),ImVec2(canvasW,canvasH)); } if (ImGui::Begin("Wavetable Editor",&waveEditOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { if (curWave<0 || curWave>=(int)e->song.wave.size()) { diff --git a/src/main.cpp b/src/main.cpp index e0a63dd7..8c3890f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -332,12 +332,6 @@ int main(int argc, char** argv) { if (coResult!=S_OK) { logE("CoInitializeEx failed!"); } -#endif -#if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID) || defined(__HAIKU__)) - // workaround for Wayland HiDPI issue - if (getenv("SDL_VIDEODRIVER")==NULL) { - setenv("SDL_VIDEODRIVER","x11",1); - } #endif outName=""; vgmOutName=""; diff --git a/src/winMain.cpp b/src/winMain.cpp index 69034b9f..853b1153 100644 --- a/src/winMain.cpp +++ b/src/winMain.cpp @@ -19,6 +19,8 @@ #include "utfutils.h" +typedef HRESULT (*SPDA)(int); + int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, PSTR args, int state) { int argc=0; wchar_t** argw=CommandLineToArgvW(GetCommandLineW(),&argc); @@ -29,5 +31,21 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, PSTR args, int state) { argv[i]=new char[str.size()+1]; strcpy(argv[i],str.c_str()); } + + // set DPI awareness + HMODULE shcore=LoadLibraryW(L"shcore.dll"); + if (shcore!=NULL) { + SPDA ta_SetProcessDpiAwareness=(SPDA)GetProcAddress(shcore,"SetProcessDpiAwareness"); + if (ta_SetProcessDpiAwareness!=NULL) { + HRESULT result=ta_SetProcessDpiAwareness(2); + if (result!=S_OK) { + // ??? + } + } + if (!FreeLibrary(shcore)) { + // ??? + } + } + return main(argc,argv); }