Platform: Fix GUI scaling on devices with non-integer pixel ratio

The fuction GetDevicePixelRatio now returns a `double` instead of an `int`.
This should allow the scaling of the GUI on devices where the pixel ratio
is non integer to work properly. For example a monitor on Windows where the
DPI is not a multiple of 96. It may help with the Web Emscripten port on
tablets and phones as well.

In addition on Windows the mouse wheel delta calculation is fixed.
This commit is contained in:
ruevs 2022-11-06 01:50:44 +02:00
parent 31ac8083ae
commit c53c592dbe
5 changed files with 29 additions and 29 deletions

View File

@ -230,7 +230,7 @@ public:
virtual double GetPixelDensity() = 0; virtual double GetPixelDensity() = 0;
// Returns raster graphics and coordinate scale (already applied on the platform side), // Returns raster graphics and coordinate scale (already applied on the platform side),
// i.e. size of logical pixel in physical pixels, or device pixel ratio. // i.e. size of logical pixel in physical pixels, or device pixel ratio.
virtual int GetDevicePixelRatio() = 0; virtual double GetDevicePixelRatio() = 0;
// Returns (fractional) font scale, to be applied on top of (integral) device pixel ratio. // Returns (fractional) font scale, to be applied on top of (integral) device pixel ratio.
virtual double GetDeviceFontScale() { virtual double GetDeviceFontScale() {
return GetPixelDensity() / GetDevicePixelRatio() / 96.0; return GetPixelDensity() / GetDevicePixelRatio() / 96.0;

View File

@ -889,7 +889,7 @@ public:
return gtkWindow.get_screen()->get_resolution(); return gtkWindow.get_screen()->get_resolution();
} }
int GetDevicePixelRatio() override { double GetDevicePixelRatio() override {
return gtkWindow.get_scale_factor(); return gtkWindow.get_scale_factor();
} }

View File

@ -970,8 +970,8 @@ public:
return 96.0 * emscripten_get_device_pixel_ratio(); return 96.0 * emscripten_get_device_pixel_ratio();
} }
int GetDevicePixelRatio() override { double GetDevicePixelRatio() override {
return (int)emscripten_get_device_pixel_ratio(); return emscripten_get_device_pixel_ratio();
} }
bool IsVisible() override { bool IsVisible() override {

View File

@ -987,10 +987,10 @@ public:
return (displayPixelSize.width / displayPhysicalSize.width) * 25.4f; return (displayPixelSize.width / displayPhysicalSize.width) * 25.4f;
} }
int GetDevicePixelRatio() override { double GetDevicePixelRatio() override {
NSSize unitSize = { 1.0f, 0.0f }; NSSize unitSize = { 1.0f, 0.0f };
unitSize = [ssView convertSizeToBacking:unitSize]; unitSize = [ssView convertSizeToBacking:unitSize];
return (int)unitSize.width; return unitSize.width;
} }
bool IsVisible() override { bool IsVisible() override {

View File

@ -793,7 +793,7 @@ public:
break; break;
case WM_SIZING: { case WM_SIZING: {
int pixelRatio = window->GetDevicePixelRatio(); double pixelRatio = window->GetDevicePixelRatio();
RECT rcw, rcc; RECT rcw, rcc;
sscheck(GetWindowRect(window->hWindow, &rcw)); sscheck(GetWindowRect(window->hWindow, &rcw));
@ -806,10 +806,10 @@ public:
int adjHeight = rc->bottom - rc->top; int adjHeight = rc->bottom - rc->top;
adjWidth -= nonClientWidth; adjWidth -= nonClientWidth;
adjWidth = max(window->minWidth * pixelRatio, adjWidth); adjWidth = max((int)(window->minWidth * pixelRatio), adjWidth);
adjWidth += nonClientWidth; adjWidth += nonClientWidth;
adjHeight -= nonClientHeight; adjHeight -= nonClientHeight;
adjHeight = max(window->minHeight * pixelRatio, adjHeight); adjHeight = max((int)(window->minHeight * pixelRatio), adjHeight);
adjHeight += nonClientHeight; adjHeight += nonClientHeight;
switch(wParam) { switch(wParam) {
case WMSZ_RIGHT: case WMSZ_RIGHT:
@ -868,7 +868,7 @@ public:
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
case WM_MOUSELEAVE: { case WM_MOUSELEAVE: {
int pixelRatio = window->GetDevicePixelRatio(); double pixelRatio = window->GetDevicePixelRatio();
MouseEvent event = {}; MouseEvent event = {};
event.x = GET_X_LPARAM(lParam) / pixelRatio; event.x = GET_X_LPARAM(lParam) / pixelRatio;
@ -941,7 +941,7 @@ public:
event.y = pt.y / pixelRatio; event.y = pt.y / pixelRatio;
event.type = MouseEvent::Type::SCROLL_VERT; event.type = MouseEvent::Type::SCROLL_VERT;
event.scrollDelta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA; event.scrollDelta = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA;
break; break;
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
@ -1109,10 +1109,10 @@ public:
return (double)dpi; return (double)dpi;
} }
int GetDevicePixelRatio() override { double GetDevicePixelRatio() override {
UINT dpi; UINT dpi;
sscheck(dpi = ssGetDpiForWindow(hWindow)); sscheck(dpi = ssGetDpiForWindow(hWindow));
return dpi / USER_DEFAULT_SCREEN_DPI; return (double)dpi / USER_DEFAULT_SCREEN_DPI;
} }
bool IsVisible() override { bool IsVisible() override {
@ -1177,27 +1177,27 @@ public:
} }
void GetContentSize(double *width, double *height) override { void GetContentSize(double *width, double *height) override {
int pixelRatio = GetDevicePixelRatio(); double pixelRatio = GetDevicePixelRatio();
RECT rc; RECT rc;
sscheck(GetClientRect(hWindow, &rc)); sscheck(GetClientRect(hWindow, &rc));
*width = (rc.right - rc.left) / pixelRatio; *width = (rc.right - rc.left) / pixelRatio;
*height = (rc.bottom - rc.top) / pixelRatio; *height = (rc.bottom - rc.top) / pixelRatio;
} }
void SetMinContentSize(double width, double height) { void SetMinContentSize(double width, double height) {
minWidth = (int)width; minWidth = (int)width;
minHeight = (int)height; minHeight = (int)height;
int pixelRatio = GetDevicePixelRatio(); double pixelRatio = GetDevicePixelRatio();
RECT rc; RECT rc;
sscheck(GetClientRect(hWindow, &rc)); sscheck(GetClientRect(hWindow, &rc));
if(rc.right - rc.left < minWidth * pixelRatio) { if(rc.right - rc.left < minWidth * pixelRatio) {
rc.right = rc.left + minWidth * pixelRatio; rc.right = rc.left + (LONG)(minWidth * pixelRatio);
} }
if(rc.bottom - rc.top < minHeight * pixelRatio) { if(rc.bottom - rc.top < minHeight * pixelRatio) {
rc.bottom = rc.top + minHeight * pixelRatio; rc.bottom = rc.top + (LONG)(minHeight * pixelRatio);
} }
} }
@ -1270,7 +1270,7 @@ public:
tooltipText = newText; tooltipText = newText;
if(!newText.empty()) { if(!newText.empty()) {
int pixelRatio = GetDevicePixelRatio(); double pixelRatio = GetDevicePixelRatio();
RECT toolRect; RECT toolRect;
toolRect.left = (int)(x * pixelRatio); toolRect.left = (int)(x * pixelRatio);
toolRect.top = (int)(y * pixelRatio); toolRect.top = (int)(y * pixelRatio);
@ -1301,9 +1301,9 @@ public:
bool isMonospace, const std::string &text) override { bool isMonospace, const std::string &text) override {
if(IsEditorVisible()) return; if(IsEditorVisible()) return;
int pixelRatio = GetDevicePixelRatio(); double pixelRatio = GetDevicePixelRatio();
HFONT hFont = CreateFontW(-(LONG)fontHeight * GetDevicePixelRatio(), 0, 0, 0, HFONT hFont = CreateFontW(-(int)(fontHeight * GetDevicePixelRatio()), 0, 0, 0,
FW_REGULAR, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FW_REGULAR, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_DONTCARE, isMonospace ? L"Lucida Console" : L"Arial"); DEFAULT_QUALITY, FF_DONTCARE, isMonospace ? L"Lucida Console" : L"Arial");
if(hFont == NULL) { if(hFont == NULL) {
@ -1324,12 +1324,12 @@ public:
sscheck(ReleaseDC(hEditor, hDc)); sscheck(ReleaseDC(hEditor, hDc));
RECT rc; RECT rc;
rc.left = (LONG)x * pixelRatio; rc.left = (LONG)(x * pixelRatio);
rc.top = (LONG)y * pixelRatio - tm.tmAscent; rc.top = (LONG)(y * pixelRatio) - tm.tmAscent;
// Add one extra char width to avoid scrolling. // Add one extra char width to avoid scrolling.
rc.right = (LONG)x * pixelRatio + rc.right = (LONG)(x * pixelRatio) +
std::max((LONG)minWidth * pixelRatio, ts.cx + tm.tmAveCharWidth); std::max((LONG)(minWidth * pixelRatio), ts.cx + tm.tmAveCharWidth);
rc.bottom = (LONG)y * pixelRatio + tm.tmDescent; rc.bottom = (LONG)(y * pixelRatio) + tm.tmDescent;
sscheck(ssAdjustWindowRectExForDpi(&rc, 0, /*bMenu=*/FALSE, WS_EX_CLIENTEDGE, sscheck(ssAdjustWindowRectExForDpi(&rc, 0, /*bMenu=*/FALSE, WS_EX_CLIENTEDGE,
ssGetDpiForWindow(hWindow))); ssGetDpiForWindow(hWindow)));
@ -1608,7 +1608,7 @@ public:
void AddFilter(std::string name, std::vector<std::string> extensions) override { void AddFilter(std::string name, std::vector<std::string> extensions) override {
std::string desc, patterns; std::string desc, patterns;
for(auto extension : extensions) { for(auto &extension : extensions) {
std::string pattern = "*." + extension; std::string pattern = "*." + extension;
if(!desc.empty()) desc += ", "; if(!desc.empty()) desc += ", ";
desc += pattern; desc += pattern;