GDK W32: Correctly infer gtk-xft-antialias & gtk-xft-rgba

Instead of hardcoding gtk-xft-antialias, use SPI_GETFONTSMOOTHING to
determine whether antialiasing is enabled.

Make gtk-xft-rgba query more complex - try to determine display
orientation, then use that to rotate subpixel structure. This
won't help with monitors that have naturally vertical subpixels,
but should improve things for monitors that are rotated (as long
as Windows display settings are adjusted accordingly).

Partially fixes #1774
This commit is contained in:
Руслан Ижбулатов 2020-04-22 21:23:15 +00:00
parent 35b9677006
commit 217158995a
3 changed files with 130 additions and 18 deletions

View File

@ -559,6 +559,7 @@ enum_monitor (HMONITOR hmonitor,
DEVMODEW dm;
DWORD i_monitor;
DWORD frequency;
GdkWin32MonitorRotation orientation;
memset (&dd, 0, sizeof (dd));
dd.cb = sizeof (dd);
@ -577,12 +578,36 @@ enum_monitor (HMONITOR hmonitor,
continue;
dm.dmSize = sizeof (dm);
dm.dmDriverExtra = 0;
frequency = 0;
orientation = GDK_WIN32_MONITOR_ROTATION_UNKNOWN;
/* Grab refresh rate for this adapter while we're at it */
if (EnumDisplaySettingsW (dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm))
frequency = dm.dmDisplayFrequency;
else
frequency = 0;
if (EnumDisplaySettingsExW (dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm, 0))
{
if ((dm.dmFields & DM_DISPLAYORIENTATION) == DM_DISPLAYORIENTATION)
{
switch (dm.dmDisplayOrientation)
{
default:
case DMDO_DEFAULT:
orientation = GDK_WIN32_MONITOR_ROTATION_0;
break;
case DMDO_90:
orientation = GDK_WIN32_MONITOR_ROTATION_90;
break;
case DMDO_180:
orientation = GDK_WIN32_MONITOR_ROTATION_180;
break;
case DMDO_270:
orientation = GDK_WIN32_MONITOR_ROTATION_270;
break;
}
}
if ((dm.dmFields & DM_DISPLAYFREQUENCY) == DM_DISPLAYFREQUENCY)
frequency = dm.dmDisplayFrequency;
}
/* Enumerate monitors connected to this display adapter */
for (i_monitor = 0; TRUE; i_monitor++)
@ -744,6 +769,7 @@ enum_monitor (HMONITOR hmonitor,
* keep remove == TRUE and be removed further up the stack.
*/
w32mon->remove = FALSE;
w32mon->orientation = orientation;
/* One virtual monitor per display adapter */
if (w32mon->madeup)
@ -770,6 +796,58 @@ prune_monitors (EnumMonitorData *data)
}
}
const gchar *
_gdk_win32_monitor_get_pixel_structure (GdkMonitor *monitor)
{
GdkWin32Monitor *w32_m;
BOOL enabled = TRUE;
unsigned int smoothing_orientation = FE_FONTSMOOTHINGORIENTATIONRGB;
BOOL cleartype = TRUE;
g_return_val_if_fail (monitor != NULL, NULL);
w32_m = GDK_WIN32_MONITOR (monitor);
SystemParametersInfoW (SPI_GETFONTSMOOTHING, 0, &enabled, 0);
SystemParametersInfoW (SPI_GETCLEARTYPE, 0, &cleartype, 0);
if (!enabled ||
!cleartype ||
!SystemParametersInfoW (SPI_GETFONTSMOOTHINGORIENTATION, 0, &smoothing_orientation, 0))
return "none";
if (smoothing_orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
switch (w32_m->orientation)
{
default:
case GDK_WIN32_MONITOR_ROTATION_UNKNOWN:
return "none";
case GDK_WIN32_MONITOR_ROTATION_0:
return "bgr";
case GDK_WIN32_MONITOR_ROTATION_90:
return "vbgr";
case GDK_WIN32_MONITOR_ROTATION_180:
return "rgb";
case GDK_WIN32_MONITOR_ROTATION_270:
return "vrgb";
}
else
switch (w32_m->orientation)
{
default:
case GDK_WIN32_MONITOR_ROTATION_UNKNOWN:
return "none";
case GDK_WIN32_MONITOR_ROTATION_0:
return "rgb";
case GDK_WIN32_MONITOR_ROTATION_90:
return "vrgb";
case GDK_WIN32_MONITOR_ROTATION_180:
return "bgr";
case GDK_WIN32_MONITOR_ROTATION_270:
return "vbgr";
}
}
GPtrArray *
_gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
{

View File

@ -26,6 +26,36 @@
#include "gdkwin32monitor.h"
/*
* The number is the degrees the display is rotated clockwise
* from its natural position.
* I.e. most displays will have 0. A normal display
* that is rotated by 90 degrees will
* have 90. The same display rotated counter-clockwise
* will have 270. The same display
* rotated by 180 degrees (i.e. upside-down)
* will have 180.
* Accordingly, 0 mode
* fontsmoothing is used as-is - i.e. it is assumed that
* subpixel structure is horizontal (ClearType does not support
* vertical subpixels; if the display has naturally vertical
* subpixel structure, ClearType should be disabled altogether).
* In 90 subpixel structure has
* its verticality flipped (rgb -> vrgb; bgr -> vbgr).
* In 180 subpixel structure is
* horizontally flipped (rgb -> bgr; bgr -> rgb).
* In 270 subpixel structure is
* flipped both horizontally and vertically
* (rgb -> vbgr; bgr -> vrgb).
*/
typedef enum _GdkWin32MonitorRotation {
GDK_WIN32_MONITOR_ROTATION_UNKNOWN = 0,
GDK_WIN32_MONITOR_ROTATION_0 = 1,
GDK_WIN32_MONITOR_ROTATION_90 = 2,
GDK_WIN32_MONITOR_ROTATION_180 = 3,
GDK_WIN32_MONITOR_ROTATION_270 = 4,
} GdkWin32MonitorRotation;
struct _GdkWin32Monitor
{
GdkMonitor parent;
@ -36,6 +66,11 @@ struct _GdkWin32Monitor
/* Device instance path (used to match GdkWin32Monitor to monitor device) */
gchar *instance_path;
/* Indicates display rotation and its normal proportions.
* Used to determine pixel structure for subpixel smoothing.
*/
GdkWin32MonitorRotation orientation;
/* TRUE if monitor is made up by us
* (this happens when system has logical monitors, but no physical ones).
*/
@ -54,4 +89,6 @@ struct _GdkWin32MonitorClass {
int _gdk_win32_monitor_compare (GdkWin32Monitor *a, GdkWin32Monitor *b);
const gchar *_gdk_win32_monitor_get_pixel_structure (GdkMonitor *monitor);
#endif

View File

@ -33,6 +33,7 @@
#include "gdkproperty.h"
#include "gdkselection.h"
#include "gdkprivate-win32.h"
#include "gdkmonitor-win32.h"
#include "gdkwin32.h"
GdkAtom
@ -368,8 +369,11 @@ _gdk_win32_screen_get_setting (GdkScreen *screen,
}
else if (strcmp ("gtk-xft-antialias", name) == 0)
{
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : 1\n", name));
g_value_set_int (value, 1);
BOOL val = TRUE;
SystemParametersInfoW (SPI_GETFONTSMOOTHING, 0, &val, 0);
g_value_set_int (value, val ? 1 : 0);
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %u\n", name, val));
return TRUE;
}
else if (strcmp ("gtk-xft-hintstyle", name) == 0)
@ -380,18 +384,11 @@ _gdk_win32_screen_get_setting (GdkScreen *screen,
}
else if (strcmp ("gtk-xft-rgba", name) == 0)
{
unsigned int orientation = 0;
if (SystemParametersInfoW (SPI_GETFONTSMOOTHINGORIENTATION, 0, &orientation, 0))
{
if (orientation == FE_FONTSMOOTHINGORIENTATIONRGB)
g_value_set_static_string (value, "rgb");
else if (orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
g_value_set_static_string (value, "bgr");
else
g_value_set_static_string (value, "none");
}
else
g_value_set_static_string (value, "none");
const gchar *rgb_value;
GdkMonitor *monitor;
monitor = gdk_display_get_monitor (gdk_display_get_default (), 0);
rgb_value = _gdk_win32_monitor_get_pixel_structure (monitor);
g_value_set_static_string (value, rgb_value);
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %s\n", name, g_value_get_string (value)));
return TRUE;