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.
pull/1310/head
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;