display: Add a way to query system DPI scaling

See #426
This commit is contained in:
rdb 2020-12-26 16:17:01 +01:00
parent d5c2dc6447
commit 2b0a6b995a
7 changed files with 86 additions and 0 deletions

View File

@ -10,6 +10,7 @@ Recommended maintenance release.
* Fix sounds resuming on reactivation if stop() was called while inactive (#559)
* Collision traverser now releases GIL during traversal (#1033)
* Fix crash caused by some gamepad drivers on Linux (#1066)
* Add GraphicsPipe::get_display_zoom() for querying system DPI scaling
* Skinning-enabled shaders can now properly render unskinned models as well
* BitMask, SparseArray, BitArray types can now be pickled (#886)
* VFSImporter now properly detects source file encodings in Python 3

View File

@ -478,6 +478,14 @@ ConfigVariableBool sync_video
"cheesy estimate of scene complexity. Some drivers may ignore "
"this request."));
ConfigVariableDouble display_zoom
("display-zoom", 0.0,
PRC_DESC("If this is set to a value other than 0.0, it overrides the detected "
"system DPI scaling. GraphicsPipe::get_display_zoom() will instead "
"return whatever was passed in here. You should generally only "
"change this based on a user preference change or to test how the UI "
"will look on monitors with different pixel densities."));
/**
* Initializes the library. This must be called at least once before any of
* the functions or classes in this library can be used. Normally it will be

View File

@ -108,6 +108,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableDouble pixel_zoom;
extern EXPCL_PANDA_DISPLAY ConfigVariableColor background_color;
extern EXPCL_PANDA_DISPLAY ConfigVariableBool sync_video;
extern EXPCL_PANDA_DISPLAY ConfigVariableDouble display_zoom;
extern EXPCL_PANDA_DISPLAY void init_libdisplay();

View File

@ -99,6 +99,9 @@ static void update_memory_info(DisplayInformation *info) {
}
#endif
// Temporarily declared as global float.
static PN_stdfloat detected_display_zoom = 1.0;
TypeHandle GraphicsPipe::_type_handle;
/**
@ -268,6 +271,35 @@ make_output(const std::string &name,
return nullptr;
}
/**
* Returns the display zoom factor configured in the operating system. If the
* operating system automatically scales windows to match the DPI (such as when
* dpi-aware is set to false), this will be 1.0. Otherwise, this will be set to
* a value approximating the density of the monitor divided by the standard
* density of the operating system (usually 96), yielding a value like 1.5 or
* 2.0.
*
* @since 1.10.8
*/
PN_stdfloat GraphicsPipe::
get_display_zoom() const {
if (display_zoom.get_num_words() > 0) {
double override = display_zoom.get_value();
if (override != 0.0) {
return override;
}
}
return detected_display_zoom;
}
/**
* Called by derived class to set the display zoom factor.
*/
void GraphicsPipe::
set_detected_display_zoom(PN_stdfloat zoom) {
detected_display_zoom = zoom;
}
/**
* Gets the pipe's DisplayInformation.
*/

View File

@ -91,8 +91,10 @@ PUBLISHED:
INLINE int get_display_width() const;
INLINE int get_display_height() const;
PN_stdfloat get_display_zoom() const;
MAKE_PROPERTY(display_width, get_display_width);
MAKE_PROPERTY(display_height, get_display_height);
MAKE_PROPERTY(display_zoom, get_display_zoom);
DisplayInformation *get_display_information();
MAKE_PROPERTY(display_information, get_display_information);
@ -115,6 +117,8 @@ public:
virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine);
protected:
void set_detected_display_zoom(PN_stdfloat zoom);
virtual void close_gsg(GraphicsStateGuardian *gsg);
virtual PT(GraphicsOutput) make_output(const std::string &name,

View File

@ -239,6 +239,22 @@ WinGraphicsPipe() {
windisplay_cat.debug() << "Calling SetProcessDpiAwareness().\n";
}
pfnSetProcessDpiAwareness(Process_Per_Monitor_DPI_Aware);
HDC dc = GetDC(nullptr);
if (dc) {
int dpi = GetDeviceCaps(dc, LOGPIXELSX);
if (dpi > 0) {
PN_stdfloat zoom = (double)dpi / 96.0;
set_detected_display_zoom(zoom);
if (windisplay_cat.is_debug()) {
windisplay_cat.debug()
<< "Determined display zoom to be " << zoom
<< " based on LOGPIXELSX " << dpi << "\n";
}
}
ReleaseDC(nullptr, dc);
}
}
}
}

View File

@ -16,6 +16,7 @@
#include "config_x11display.h"
#include "frameBufferProperties.h"
#include "displayInformation.h"
#include "pstrtod.h"
#include <dlfcn.h>
@ -300,6 +301,29 @@ x11GraphicsPipe(const std::string &display) :
XFree(im_supported_styles);
*/
const char *dpi = XGetDefault(_display, "Xft", "dpi");
if (dpi != nullptr) {
char *endptr = nullptr;
double result = pstrtod(dpi, &endptr);
if (result != 0 && !cnan(result) && endptr[0] == '\0') {
result /= 96;
set_detected_display_zoom(result);
if (x11display_cat.is_debug()) {
x11display_cat.debug()
<< "Determined display zoom to be " << result
<< " based on specified Xft.dpi " << dpi << "\n";
}
} else {
x11display_cat.warning()
<< "Unable to determine display zoom because Xft.dpi is invalid: "
<< dpi << "\n";
}
} else if (x11display_cat.is_debug()) {
x11display_cat.debug()
<< "Unable to determine display zoom because Xft.dpi was not set.\n";
}
// Get some X atom numbers.
_wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
_net_wm_pid = XInternAtom(_display, "_NET_WM_PID", false);