GDK-Win32/4.0: Enable HiDPI support for Windows

This enables HiDPI support for GTK+ on Windows, so that the
fonts and window look better on HiDPI displays.  Notes for the current
work:

-The DPI awareness enabling can be disabled if and only if an application
 manifest is not embedded in the app to enable DPI awareness AND a user
 compatibility setting is not set to limit DPI awareness for the app, via
 the envvar GDK_WIN32_DISABLE_HIDPI.  The app manifest/user setting for
 DPI awareness will always win against the envvar, and so the HiDPI items
 will be always setup in such scenarios, unless DPI awareness is disabled.

-Both automatic detection for the scaling factor and setting the scale
 factor using the GDK_SCALE envvar are supported, where the envvar takes
 precedence, which will therefore disable automatic scaling when
 resolution changes.

-We now default to a per-system DPI awareness model, which means that we
 do not handle WM_DPICHANGED, unless one sets the
 GDK_WIN32_PER_MONITOR_HIDPI envvar, where notes for it are in the
 following point.

-Automatic scaling during WM_DISPLAYCHANGE is handled (DPI setting change of
 current monitor) is now supported.  WM_DPICHANGED is handled as well,
 except that the window positioning during the change of scaling still
 needs to be refined, a change in GDK itself may be required for this.

-I am unable to test the wintab items because I don't have such devices
 around.

https://bugzilla.gnome.org/show_bug.cgi?id=768081
This commit is contained in:
Chun-wei Fan 2016-06-27 13:16:43 +08:00
parent 3baa4a9741
commit 6abd65c83b
13 changed files with 1028 additions and 323 deletions

View File

@ -111,25 +111,27 @@ gdk_device_win32_query_state (GdkDevice *device,
GdkScreen *screen;
POINT point;
HWND hwnd, hwndc;
GdkWindowImplWin32 *impl;
screen = gdk_window_get_screen (window);
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
hwnd = GDK_WINDOW_HWND (window);
GetCursorPos (&point);
if (root_x)
*root_x = point.x;
*root_x = point.x / impl->window_scale;
if (root_y)
*root_y = point.y;
*root_y = point.y / impl->window_scale;
ScreenToClient (hwnd, &point);
if (win_x)
*win_x = point.x;
*win_x = point.x / impl->window_scale;
if (win_y)
*win_y = point.y;
*win_y = point.y / impl->window_scale;
if (window == gdk_screen_get_root_window (screen))
{
@ -197,6 +199,7 @@ _gdk_device_win32_window_at_position (GdkDevice *device,
gboolean get_toplevel)
{
GdkWindow *window = NULL;
GdkWindowImplWin32 *impl = NULL;
POINT screen_pt, client_pt;
HWND hwnd, hwndc;
RECT rect;
@ -249,12 +252,15 @@ _gdk_device_win32_window_at_position (GdkDevice *device,
/* If we didn't hit any window at that point, return the desktop */
if (hwnd == NULL)
{
if (win_x)
*win_x = screen_pt.x + _gdk_offset_x;
if (win_y)
*win_y = screen_pt.y + _gdk_offset_y;
window = gdk_get_default_root_window ();
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
return gdk_get_default_root_window ();
if (win_x)
*win_x = (screen_pt.x + _gdk_offset_x) / impl->window_scale;
if (win_y)
*win_y = (screen_pt.y + _gdk_offset_y) / impl->window_scale;
return window;
}
window = gdk_win32_handle_table_lookup (hwnd);
@ -262,10 +268,12 @@ _gdk_device_win32_window_at_position (GdkDevice *device,
if (window && (win_x || win_y))
{
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (win_x)
*win_x = client_pt.x;
*win_x = client_pt.x / impl->window_scale;
if (win_y)
*win_y = client_pt.y;
*win_y = client_pt.y / impl->window_scale;
}
return window;

View File

@ -121,26 +121,28 @@ gdk_device_wintab_query_state (GdkDevice *device,
GdkScreen *screen;
POINT point;
HWND hwnd, hwndc;
GdkWindowImplWin32 *impl;
device_wintab = GDK_DEVICE_WINTAB (device);
screen = gdk_window_get_screen (window);
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
hwnd = GDK_WINDOW_HWND (window);
GetCursorPos (&point);
if (root_x)
*root_x = point.x;
*root_x = point.x / impl->window_scale;
if (root_y)
*root_y = point.y;
*root_y = point.y / impl->window_scale;
ScreenToClient (hwnd, &point);
if (win_x)
*win_x = point.x;
*win_x = point.x / impl->window_scale;
if (win_y)
*win_y = point.y;
*win_y = point.y / impl->window_scale;
if (window == gdk_get_default_root_window ())
{

View File

@ -889,6 +889,7 @@ gdk_input_other_event (GdkDisplay *display,
GdkEventMask masktest;
guint key_state;
POINT pt;
GdkWindowImplWin32 *impl;
PACKET packet;
gint root_x, root_y;
@ -1034,15 +1035,17 @@ G_GNUC_END_IGNORE_DEPRECATIONS;
if (window->parent == gdk_get_default_root_window () || window->parent == NULL)
return FALSE;
pt.x = x;
pt.y = y;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
pt.x = x * impl->window_scale;
pt.y = y * impl->window_scale;
ClientToScreen (GDK_WINDOW_HWND (window), &pt);
g_object_unref (window);
window = window->parent;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
g_object_ref (window);
ScreenToClient (GDK_WINDOW_HWND (window), &pt);
x = pt.x;
y = pt.y;
x = pt.x / impl->window_scale;
y = pt.y / impl->window_scale;
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n",
GDK_WINDOW_HWND (window), x, y));
}

View File

@ -195,6 +195,41 @@ _gdk_win32_display_init_monitors (GdkWin32Display *win32_display)
changed = TRUE;
}
for (i = 0; i < win32_display->monitors->len; i++)
{
GdkMonitor *monitor;
GdkWin32Monitor *win32_monitor;
monitor = GDK_MONITOR (g_ptr_array_index (win32_display->monitors, i));
if (win32_display->has_fixed_scale)
gdk_monitor_set_scale_factor (monitor, win32_display->window_scale);
else
{
/* First acquire the scale using the current screen */
GdkRectangle workarea;
POINT pt;
guint scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
gdk_monitor_get_workarea (monitor, &workarea);
workarea.x -= _gdk_offset_x;
workarea.y -= _gdk_offset_y;
workarea.x += workarea.width / scale;
workarea.y += workarea.height / scale;
pt.x = workarea.x;
pt.y = workarea.y;
/* acquire the scale using the monitor which the window is nearest on Windows 8.1+ */
if (win32_display->have_at_least_win81)
{
HMONITOR hmonitor = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, hmonitor, NULL, NULL);
}
gdk_monitor_set_scale_factor (monitor, scale);
}
}
return changed;
}
@ -789,6 +824,15 @@ gdk_win32_display_dispose (GObject *object)
_hwnd_next_viewer = NULL;
}
if (display_win32->have_at_least_win81)
{
if (display_win32->shcore_funcs.hshcore != NULL)
{
FreeLibrary (display_win32->shcore_funcs.hshcore);
display_win32->shcore_funcs.hshcore = NULL;
}
}
G_OBJECT_CLASS (gdk_win32_display_parent_class)->dispose (object);
}
@ -805,10 +849,221 @@ gdk_win32_display_finalize (GObject *object)
G_OBJECT_CLASS (gdk_win32_display_parent_class)->finalize (object);
}
static void
_gdk_win32_enable_hidpi (GdkWin32Display *display)
{
gboolean check_for_dpi_awareness = FALSE;
gboolean have_hpi_disable_envvar = FALSE;
enum dpi_aware_status {
DPI_STATUS_PENDING,
DPI_STATUS_SUCCESS,
DPI_STATUS_DISABLED,
DPI_STATUS_FAILED
} status = DPI_STATUS_PENDING;
if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_ANY))
{
/* If we are on Windows 8.1 or later, cache up functions from shcore.dll, by all means */
display->have_at_least_win81 = TRUE;
display->shcore_funcs.hshcore = LoadLibraryW (L"shcore.dll");
if (display->shcore_funcs.hshcore != NULL)
{
display->shcore_funcs.setDpiAwareFunc =
(funcSetProcessDpiAwareness) GetProcAddress (display->shcore_funcs.hshcore,
"SetProcessDpiAwareness");
display->shcore_funcs.getDpiAwareFunc =
(funcGetProcessDpiAwareness) GetProcAddress (display->shcore_funcs.hshcore,
"GetProcessDpiAwareness");
display->shcore_funcs.getDpiForMonitorFunc =
(funcGetDpiForMonitor) GetProcAddress (display->shcore_funcs.hshcore,
"GetDpiForMonitor");
}
}
else
{
/* Windows Vista through 8: use functions from user32.dll directly */
HMODULE user32;
display->have_at_least_win81 = FALSE;
user32 = GetModuleHandleW (L"user32.dll");
if (user32 != NULL)
{
display->user32_dpi_funcs.setDpiAwareFunc =
(funcSetProcessDPIAware) GetProcAddress (user32, "SetProcessDPIAware");
display->user32_dpi_funcs.isDpiAwareFunc =
(funcIsProcessDPIAware) GetProcAddress (user32, "IsProcessDPIAware");
}
}
if (g_getenv ("GDK_WIN32_DISABLE_HIDPI") == NULL)
{
/* For Windows 8.1 and later, use SetProcessDPIAwareness() */
if (display->have_at_least_win81)
{
/* then make the GDK-using app DPI-aware */
if (display->shcore_funcs.setDpiAwareFunc != NULL)
{
GdkWin32ProcessDpiAwareness hidpi_mode;
/* TODO: See how per-monitor DPI awareness is done by the Wayland backend */
if (g_getenv ("GDK_WIN32_PER_MONITOR_HIDPI") != NULL)
hidpi_mode = PROCESS_PER_MONITOR_DPI_AWARE;
else
hidpi_mode = PROCESS_SYSTEM_DPI_AWARE;
switch (display->shcore_funcs.setDpiAwareFunc (hidpi_mode))
{
case S_OK:
display->dpi_aware_type = hidpi_mode;
status = DPI_STATUS_SUCCESS;
break;
case E_ACCESSDENIED:
/* This means the app used a manifest to set DPI awareness, or a
DPI compatibility setting is used.
The manifest is the trump card in this game of bridge here. The
same applies if one uses the control panel or program properties to
force system DPI awareness */
check_for_dpi_awareness = TRUE;
break;
default:
display->dpi_aware_type = PROCESS_DPI_UNAWARE;
status = DPI_STATUS_FAILED;
break;
}
}
/* Should not get here! */
if (status == DPI_STATUS_PENDING)
{
g_assert_not_reached ();
display->dpi_aware_type = PROCESS_DPI_UNAWARE;
status = DPI_STATUS_FAILED;
}
}
else
{
/* For Windows Vista through 8, use SetProcessDPIAware() */
display->have_at_least_win81 = FALSE;
if (display->user32_dpi_funcs.setDpiAwareFunc != NULL)
{
if (display->user32_dpi_funcs.setDpiAwareFunc () != 0)
{
display->dpi_aware_type = PROCESS_SYSTEM_DPI_AWARE;
status = DPI_STATUS_SUCCESS;
}
else
{
check_for_dpi_awareness = TRUE;
}
}
else
{
display->dpi_aware_type = PROCESS_DPI_UNAWARE;
status = DPI_STATUS_FAILED;
}
}
}
else
{
/* if GDK_WIN32_DISABLE_HIDPI is set, check for any DPI
* awareness settings done via manifests or user settings
*/
check_for_dpi_awareness = TRUE;
have_hpi_disable_envvar = TRUE;
}
if (check_for_dpi_awareness)
{
if (display->have_at_least_win81)
{
if (display->shcore_funcs.getDpiAwareFunc != NULL)
{
display->shcore_funcs.getDpiAwareFunc (NULL, &display->dpi_aware_type);
if (display->dpi_aware_type != PROCESS_DPI_UNAWARE)
status = DPI_STATUS_SUCCESS;
else
/* This means the DPI awareness setting was forcefully disabled */
status = DPI_STATUS_DISABLED;
}
else
{
display->dpi_aware_type = PROCESS_DPI_UNAWARE;
status = DPI_STATUS_FAILED;
}
}
else
{
if (display->user32_dpi_funcs.isDpiAwareFunc != NULL)
{
/* This most probably means DPI awareness is set through
the manifest, or a DPI compatibility setting is used. */
display->dpi_aware_type = display->user32_dpi_funcs.isDpiAwareFunc () ?
PROCESS_SYSTEM_DPI_AWARE :
PROCESS_DPI_UNAWARE;
if (display->dpi_aware_type == PROCESS_SYSTEM_DPI_AWARE)
status = DPI_STATUS_SUCCESS;
else
status = DPI_STATUS_DISABLED;
}
else
{
display->dpi_aware_type = PROCESS_DPI_UNAWARE;
status = DPI_STATUS_FAILED;
}
}
if (have_hpi_disable_envvar &&
status == DPI_STATUS_SUCCESS)
{
/* The user setting or application manifest trumps over GDK_WIN32_DISABLE_HIDPI */
g_print ("Note: GDK_WIN32_DISABLE_HIDPI is ignored due to preset\n"
" DPI awareness settings in user settings or application\n"
" manifest, DPI awareness is still enabled.");
}
}
switch (status)
{
case DPI_STATUS_SUCCESS:
GDK_NOTE (MISC, g_message ("HiDPI support enabled, type: %s",
display->dpi_aware_type == PROCESS_PER_MONITOR_DPI_AWARE ? "per-monitor" : "system"));
break;
case DPI_STATUS_DISABLED:
GDK_NOTE (MISC, g_message ("HiDPI support disabled via manifest"));
break;
case DPI_STATUS_FAILED:
g_warning ("Failed to enable HiDPI support.");
}
}
static void
gdk_win32_display_init (GdkWin32Display *display)
{
const gchar *scale_str = g_getenv ("GDK_SCALE");
display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
_gdk_win32_enable_hidpi (display);
/* if we have DPI awareness, set up fixed scale if set */
if (display->dpi_aware_type != PROCESS_DPI_UNAWARE &&
scale_str != NULL)
{
display->window_scale = atol (scale_str);
if (display->window_scale == 0)
display->window_scale = 1;
display->has_fixed_scale = TRUE;
}
else
display->window_scale = 1;
_gdk_win32_display_init_cursors (display);
gdk_win32_display_check_composited (display);
}
@ -896,6 +1151,89 @@ gdk_win32_display_get_primary_monitor (GdkDisplay *display)
return NULL;
}
guint
_gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *win32_display,
HMONITOR hmonitor,
HWND hwnd,
gint *dpi)
{
gboolean is_scale_acquired = FALSE;
gboolean use_dpi_for_monitor = FALSE;
guint dpix, dpiy;
if (win32_display->have_at_least_win81)
{
if (hmonitor != NULL)
use_dpi_for_monitor = TRUE;
else
{
if (hwnd != NULL)
{
hmonitor = MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST);
use_dpi_for_monitor = TRUE;
}
}
}
if (use_dpi_for_monitor)
{
/* Use GetDpiForMonitor() for Windows 8.1+, when we have a HMONITOR */
if (win32_display->shcore_funcs.hshcore != NULL &&
win32_display->shcore_funcs.getDpiForMonitorFunc != NULL)
{
if (win32_display->shcore_funcs.getDpiForMonitorFunc (hmonitor,
MDT_EFFECTIVE_DPI,
&dpix,
&dpiy) == S_OK)
{
is_scale_acquired = TRUE;
}
}
}
else
{
/* Go back to GetDeviceCaps() for Windows 8 and earler, or when we don't
* have a HMONITOR nor a HWND
*/
HDC hdc = GetDC (hwnd);
/* in case we can't get the DC for the window, return 1 for the scale */
if (hdc == NULL)
{
if (dpi != NULL)
*dpi = USER_DEFAULT_SCREEN_DPI;
return 1;
}
dpix = GetDeviceCaps (hdc, LOGPIXELSX);
dpiy = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (hwnd, hdc);
is_scale_acquired = TRUE;
}
if (is_scale_acquired)
/* USER_DEFAULT_SCREEN_DPI = 96, in winuser.h */
{
if (dpi != NULL)
*dpi = dpix;
if (win32_display->has_fixed_scale)
return win32_display->window_scale;
else
return dpix / USER_DEFAULT_SCREEN_DPI > 1 ? dpix / USER_DEFAULT_SCREEN_DPI : 1;
}
else
{
if (dpi != NULL)
*dpi = USER_DEFAULT_SCREEN_DPI;
return 1;
}
}
static void
gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
{

View File

@ -22,6 +22,39 @@
#ifndef __GDK_DISPLAY__WIN32_H__
#define __GDK_DISPLAY__WIN32_H__
/* Define values used to set DPI-awareness */
typedef enum _GdkWin32ProcessDpiAwareness {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} GdkWin32ProcessDpiAwareness;
/* APIs from shcore.dll */
typedef HRESULT (WINAPI *funcSetProcessDpiAwareness) (GdkWin32ProcessDpiAwareness value);
typedef HRESULT (WINAPI *funcGetProcessDpiAwareness) (HANDLE handle, GdkWin32ProcessDpiAwareness *awareness);
typedef HRESULT (WINAPI *funcGetDpiForMonitor) (HMONITOR monitor,
GdkWin32MonitorDpiType dpi_type,
UINT *dpi_x,
UINT *dpi_y);
typedef struct _GdkWin32ShcoreFuncs
{
HMODULE hshcore;
funcSetProcessDpiAwareness setDpiAwareFunc;
funcGetProcessDpiAwareness getDpiAwareFunc;
funcGetDpiForMonitor getDpiForMonitorFunc;
} GdkWin32ShcoreFuncs;
/* DPI awareness APIs from user32.dll */
typedef BOOL (WINAPI *funcSetProcessDPIAware) (void);
typedef BOOL (WINAPI *funcIsProcessDPIAware) (void);
typedef struct _GdkWin32User32DPIFuncs
{
funcSetProcessDPIAware setDpiAwareFunc;
funcIsProcessDPIAware isDpiAwareFunc;
} GdkWin32User32DPIFuncs;
struct _GdkWin32Display
{
GdkDisplay display;
@ -49,6 +82,15 @@ struct _GdkWin32Display
guint hasWglOMLSyncControl : 1;
guint hasWglARBPixelFormat : 1;
guint hasWglARBmultisample : 1;
/* HiDPI Items */
guint have_at_least_win81 : 1;
GdkWin32ProcessDpiAwareness dpi_aware_type;
guint has_fixed_scale : 1;
guint window_scale;
GdkWin32ShcoreFuncs shcore_funcs;
GdkWin32User32DPIFuncs user32_dpi_funcs;
};
struct _GdkWin32DisplayClass
@ -62,4 +104,9 @@ GPtrArray *_gdk_win32_display_get_monitor_list (GdkWin32Display *display);
void gdk_win32_display_check_composited (GdkWin32Display *display);
guint _gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *win32_display,
HMONITOR hmonitor,
HWND hwnd,
gint *dpi);
#endif /* __GDK_DISPLAY__WIN32_H__ */

View File

@ -44,9 +44,11 @@
#include "gdkprivate-win32.h"
#include <glib/gprintf.h>
#include <cairo-win32.h>
#include "gdk.h"
#include "gdkdisplayprivate.h"
#include "gdkmonitorprivate.h"
#include "gdkwin32.h"
#include "gdkkeysyms.h"
#include "gdkdevicemanager-win32.h"
@ -1059,17 +1061,17 @@ show_window_recurse (GdkWindow *window, gboolean hide_window)
{
if (gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED)
{
GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
GtkShowWindow (window, SW_SHOWMAXIMIZED);
}
else
{
GtkShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
GtkShowWindow (window, SW_RESTORE);
}
}
}
else
{
GtkShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
GtkShowWindow (window, SW_MINIMIZE);
}
}
@ -1121,6 +1123,7 @@ send_crossing_event (GdkDisplay *display,
GdkDeviceGrabInfo *grab;
GdkDeviceManagerWin32 *device_manager;
POINT pt;
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display));
@ -1142,10 +1145,10 @@ send_crossing_event (GdkDisplay *display,
event->crossing.window = window;
event->crossing.subwindow = subwindow;
event->crossing.time = _gdk_win32_get_next_tick (time_);
event->crossing.x = pt.x;
event->crossing.y = pt.y;
event->crossing.x_root = screen_pt->x + _gdk_offset_x;
event->crossing.y_root = screen_pt->y + _gdk_offset_y;
event->crossing.x = pt.x / impl->window_scale;
event->crossing.y = pt.y / impl->window_scale;
event->crossing.x_root = (screen_pt->x + _gdk_offset_x) / impl->window_scale;
event->crossing.y_root = (screen_pt->y + _gdk_offset_y) / impl->window_scale;
event->crossing.mode = mode;
event->crossing.detail = notify_type;
event->crossing.mode = mode;
@ -1449,8 +1452,8 @@ _gdk_win32_get_window_rect (GdkWindow *window,
if (gdk_window_get_parent (window) == gdk_get_default_root_window ())
{
ClientToScreen (hwnd, &point);
point.x += _gdk_offset_x;
point.y += _gdk_offset_y;
point.x += _gdk_offset_x * window_impl->window_scale;
point.y += _gdk_offset_y * window_impl->window_scale;
}
rect->left = point.x;
@ -1465,9 +1468,12 @@ void
_gdk_win32_do_emit_configure_event (GdkWindow *window,
RECT rect)
{
window->width = rect.right - rect.left;
window->height = rect.bottom - rect.top;
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
impl->unscaled_width = rect.right - rect.left;
impl->unscaled_height = rect.bottom - rect.top;
window->width = (impl->unscaled_width + impl->window_scale - 1) / impl->window_scale;
window->height = (impl->unscaled_height + impl->window_scale - 1) / impl->window_scale;
window->x = rect.left;
window->y = rect.top;
@ -1479,11 +1485,11 @@ _gdk_win32_do_emit_configure_event (GdkWindow *window,
event->configure.window = window;
event->configure.width = rect.right - rect.left;
event->configure.height = rect.bottom - rect.top;
event->configure.width = window->width;
event->configure.height = window->height;
event->configure.x = rect.left;
event->configure.y = rect.top;
event->configure.x = window->x;
event->configure.y = window->y;
_gdk_win32_append_event (event);
}
@ -1501,7 +1507,8 @@ _gdk_win32_emit_configure_event (GdkWindow *window)
}
cairo_region_t *
_gdk_win32_hrgn_to_region (HRGN hrgn)
_gdk_win32_hrgn_to_region (HRGN hrgn,
guint scale)
{
RGNDATA *rgndata;
RECT *rects;
@ -1532,8 +1539,8 @@ _gdk_win32_hrgn_to_region (HRGN hrgn)
r.x = rects[i].left;
r.y = rects[i].top;
r.width = rects[i].right - r.x;
r.height = rects[i].bottom - r.y;
r.width = (rects[i].right - r.x) / scale;
r.height = (rects[i].bottom - r.y) / scale;
cairo_region_union_rectangle (result, &r);
}
@ -1562,6 +1569,7 @@ handle_wm_paint (MSG *msg,
HDC hdc;
PAINTSTRUCT paintstruct;
cairo_region_t *update_region;
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (GetUpdateRgn (msg->hwnd, hrgn, FALSE) == ERROR)
{
@ -1587,7 +1595,7 @@ handle_wm_paint (MSG *msg,
return;
}
update_region = _gdk_win32_hrgn_to_region (hrgn);
update_region = _gdk_win32_hrgn_to_region (hrgn, impl->window_scale);
if (!cairo_region_is_empty (update_region))
_gdk_window_invalidate_for_expose (window, update_region);
cairo_region_destroy (update_region);
@ -1660,6 +1668,7 @@ handle_nchittest (HWND hwnd,
gint *ret_valp)
{
RECT rect;
GdkWindowImplWin32 *impl;
if (window == NULL || window->input_shape == NULL)
return FALSE;
@ -1673,11 +1682,14 @@ handle_nchittest (HWND hwnd,
if (!GetWindowRect (hwnd, &rect))
return FALSE;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
rect.left = screen_x - rect.left;
rect.top = screen_y - rect.top;
/* If it's inside the rect, return FALSE and let DefWindowProc() handle it */
if (cairo_region_contains_point (window->input_shape, rect.left, rect.top))
if (cairo_region_contains_point (window->input_shape,
rect.left / impl->window_scale,
rect.top / impl->window_scale))
return FALSE;
/* Otherwise override DefWindowProc() and tell WM that the point is not
@ -1687,6 +1699,67 @@ handle_nchittest (HWND hwnd,
return TRUE;
}
static void
handle_dpi_changed (GdkWindow *window,
MSG *msg)
{
HWND hwnd = GDK_WINDOW_HWND (window);
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GdkDisplay *display = gdk_display_get_default ();
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
GdkScreen *screen = gdk_window_get_screen (window);
GdkDevice *device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
RECT *rect = (RECT *)msg->lParam;
GdkEvent *event;
guint old_scale = impl->window_scale;
/* MSDN for WM_DPICHANGED: dpi_x == dpi_y here, so LOWORD (msg->wParam) == HIWORD (msg->wParam) */
guint dpi = LOWORD (msg->wParam);
/* Don't bother if we use a fixed scale */
if (win32_display->has_fixed_scale)
return;
impl->window_scale = dpi / USER_DEFAULT_SCREEN_DPI;
/* Don't bother if scales did not change in the end */
if (old_scale == impl->window_scale)
return;
_gdk_screen_set_resolution (screen,
impl->window_scale >= 2 ? USER_DEFAULT_SCREEN_DPI : dpi);
if (!IsIconic (msg->hwnd) &&
!GDK_WINDOW_DESTROYED (window))
{
GdkMonitor *monitor;
monitor = gdk_display_get_monitor_at_window (display, window);
gdk_monitor_set_scale_factor (monitor, impl->window_scale);
if (impl->layered)
{
/* We only need to set the cairo surface device scale here ourselves for layered windows */
if (impl->cache_surface != NULL)
cairo_surface_set_device_scale (impl->cache_surface,
impl->window_scale,
impl->window_scale);
if (impl->cairo_surface != NULL)
cairo_surface_set_device_scale (impl->cairo_surface,
impl->window_scale,
impl->window_scale);
}
}
_gdk_win32_adjust_client_rect (window, rect);
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
gdk_window_move_resize (window, window->x, window->y, window->width, window->height);
else
gdk_window_resize (window, window->width, window->height);
}
static void
generate_button_event (GdkEventType type,
gint button,
@ -1695,6 +1768,7 @@ generate_button_event (GdkEventType type,
{
GdkEvent *event = gdk_event_new (type);
GdkDeviceManagerWin32 *device_manager;
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (_gdk_input_ignore_core)
return;
@ -1703,10 +1777,10 @@ generate_button_event (GdkEventType type,
event->button.window = window;
event->button.time = _gdk_win32_get_next_tick (msg->time);
event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
event->button.x_root = msg->pt.x + _gdk_offset_x;
event->button.y_root = msg->pt.y + _gdk_offset_y;
event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->window_scale;
event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->window_scale;
event->button.x_root = (msg->pt.x + _gdk_offset_x) / impl->window_scale;
event->button.y_root = (msg->pt.y + _gdk_offset_y) / impl->window_scale;
event->button.axes = NULL;
event->button.state = build_pointer_event_state (msg);
event->button.button = button;
@ -1999,8 +2073,8 @@ _gdk_win32_window_fill_min_max_info (GdkWindow *window,
if (impl->hint_flags & GDK_HINT_MIN_SIZE)
{
rect.left = rect.top = 0;
rect.right = impl->hints.min_width;
rect.bottom = impl->hints.min_height;
rect.right = impl->hints.min_width * impl->window_scale;
rect.bottom = impl->hints.min_height * impl->window_scale;
_gdk_win32_adjust_client_rect (window, &rect);
@ -2013,8 +2087,8 @@ _gdk_win32_window_fill_min_max_info (GdkWindow *window,
int maxw, maxh;
rect.left = rect.top = 0;
rect.right = impl->hints.max_width;
rect.bottom = impl->hints.max_height;
rect.right = impl->hints.max_width * impl->window_scale;
rect.bottom = impl->hints.max_height * impl->window_scale;
_gdk_win32_adjust_client_rect (window, &rect);
@ -2047,8 +2121,8 @@ _gdk_win32_window_fill_min_max_info (GdkWindow *window,
mmi->ptMaxSize.y = nearest_info.rcWork.bottom - nearest_info.rcWork.top;
}
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->margins_x;
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->margins_y;
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->margins_x * impl->window_scale;
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->margins_y * impl->window_scale;
}
return TRUE;
@ -2737,19 +2811,19 @@ gdk_event_translate (MSG *msg,
}
g_set_object (&window, find_window_for_mouse_event (window, msg));
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
/* If we haven't moved, don't create any GDK event. Windows
* sends WM_MOUSEMOVE messages after a new window is shows under
* the mouse, even if the mouse hasn't moved. This disturbs gtk.
*/
if (msg->pt.x + _gdk_offset_x == current_root_x &&
msg->pt.y + _gdk_offset_y == current_root_y)
if ((msg->pt.x + _gdk_offset_x) / impl->window_scale == current_root_x &&
(msg->pt.y + _gdk_offset_y) / impl->window_scale == current_root_y)
break;
current_root_x = msg->pt.x + _gdk_offset_x;
current_root_y = msg->pt.y + _gdk_offset_y;
current_root_x = (msg->pt.x + _gdk_offset_x) / impl->window_scale;
current_root_y = (msg->pt.y + _gdk_offset_y) / impl->window_scale;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
{
@ -2760,8 +2834,8 @@ gdk_event_translate (MSG *msg,
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
event->motion.time = _gdk_win32_get_next_tick (msg->time);
event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->window_scale;
event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam) / impl->window_scale;
event->motion.x_root = current_root_x;
event->motion.y_root = current_root_y;
event->motion.axes = NULL;
@ -2873,6 +2947,7 @@ gdk_event_translate (MSG *msg,
g_set_object (&window, new_window);
}
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
ScreenToClient (msg->hwnd, &point);
event = gdk_event_new (GDK_SCROLL);
@ -2885,10 +2960,10 @@ gdk_event_translate (MSG *msg,
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT;
event->scroll.time = _gdk_win32_get_next_tick (msg->time);
event->scroll.x = (gint16) point.x;
event->scroll.y = (gint16) point.y;
event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x;
event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y;
event->scroll.x = (gint16) point.x / impl->window_scale;
event->scroll.y = (gint16) point.y / impl->window_scale;
event->scroll.x_root = ((gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x) / impl->window_scale;
event->scroll.y_root = ((gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y) / impl->window_scale;
event->scroll.state = build_pointer_event_state (msg);
gdk_event_set_device (event, device_manager_win32->core_pointer);
gdk_event_set_source_device (event, device_manager_win32->system_pointer);
@ -3254,8 +3329,8 @@ gdk_event_translate (MSG *msg,
{
/* Resize in increments relative to the base size */
rect.left = rect.top = 0;
rect.right = impl->hints.base_width;
rect.bottom = impl->hints.base_height;
rect.right = impl->hints.base_width * impl->window_scale;
rect.bottom = impl->hints.base_height * impl->window_scale;
_gdk_win32_adjust_client_rect (window, &rect);
point.x = rect.left;
point.y = rect.top;
@ -3277,53 +3352,53 @@ gdk_event_translate (MSG *msg,
case WMSZ_BOTTOM:
if (drag->bottom == rect.bottom)
break;
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc);
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc * impl->window_scale);
break;
case WMSZ_BOTTOMLEFT:
if (drag->bottom == rect.bottom && drag->left == rect.left)
break;
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc);
adjust_drag (&drag->left, rect.left, impl->hints.width_inc);
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc * impl->window_scale);
adjust_drag (&drag->left, rect.left, impl->hints.width_inc * impl->window_scale);
break;
case WMSZ_LEFT:
if (drag->left == rect.left)
break;
adjust_drag (&drag->left, rect.left, impl->hints.width_inc);
adjust_drag (&drag->left, rect.left, impl->hints.width_inc * impl->window_scale);
break;
case WMSZ_TOPLEFT:
if (drag->top == rect.top && drag->left == rect.left)
break;
adjust_drag (&drag->top, rect.top, impl->hints.height_inc);
adjust_drag (&drag->left, rect.left, impl->hints.width_inc);
adjust_drag (&drag->top, rect.top, impl->hints.height_inc * impl->window_scale);
adjust_drag (&drag->left, rect.left, impl->hints.width_inc * impl->window_scale);
break;
case WMSZ_TOP:
if (drag->top == rect.top)
break;
adjust_drag (&drag->top, rect.top, impl->hints.height_inc);
adjust_drag (&drag->top, rect.top, impl->hints.height_inc * impl->window_scale);
break;
case WMSZ_TOPRIGHT:
if (drag->top == rect.top && drag->right == rect.right)
break;
adjust_drag (&drag->top, rect.top, impl->hints.height_inc);
adjust_drag (&drag->right, rect.right, impl->hints.width_inc);
adjust_drag (&drag->top, rect.top, impl->hints.height_inc * impl->window_scale);
adjust_drag (&drag->right, rect.right, impl->hints.width_inc * impl->window_scale);
break;
case WMSZ_RIGHT:
if (drag->right == rect.right)
break;
adjust_drag (&drag->right, rect.right, impl->hints.width_inc);
adjust_drag (&drag->right, rect.right, impl->hints.width_inc * impl->window_scale);
break;
case WMSZ_BOTTOMRIGHT:
if (drag->bottom == rect.bottom && drag->right == rect.right)
break;
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc);
adjust_drag (&drag->right, rect.right, impl->hints.width_inc);
adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc * impl->window_scale);
adjust_drag (&drag->right, rect.right, impl->hints.width_inc * impl->window_scale);
break;
}
@ -3489,6 +3564,12 @@ gdk_event_translate (MSG *msg,
return_val = TRUE;
break;
case WM_DPICHANGED:
handle_dpi_changed (window, msg);
return_val = FALSE;
*ret_valp = 0;
break;
case WM_NCDESTROY:
if ((pointer_grab != NULL && pointer_grab -> window == window) ||
(keyboard_grab && keyboard_grab -> window == window))

View File

@ -73,27 +73,32 @@ _gdk_window_move_resize_child (GdkWindow *window,
gint width,
gint height)
{
GdkWindowImplWin32 *impl;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s@%+d%+d %dx%d@%+d%+d\n",
_gdk_win32_window_description (window),
window->x, window->y, width, height, x, y));
if (width > 65535 || height > 65535)
if (width * impl->window_scale > 65535 || height * impl->window_scale > 65535)
{
g_warning ("Native children wider or taller than 65535 pixels are not supported.");
if (width > 65535)
width = 65535;
if (height > 65535)
height = 65535;
if (width * impl->window_scale > 65535)
width = 65535 / impl->window_scale;
if (height * impl->window_scale > 65535)
height = 65535 /impl->window_scale;
}
window->x = x;
window->y = y;
window->width = width;
window->height = height;
impl->unscaled_width = width * impl->window_scale;
impl->unscaled_height = height * impl->window_scale;
_gdk_win32_window_tmp_unset_parent_bg (window);
_gdk_win32_window_tmp_unset_bg (window, TRUE);
@ -101,12 +106,16 @@ _gdk_window_move_resize_child (GdkWindow *window,
GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
"NOACTIVATE|NOZORDER)\n",
GDK_WINDOW_HWND (window),
window->x + window->parent->abs_x, window->y + window->parent->abs_y,
width, height));
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale,
impl->unscaled_width,
impl->unscaled_height));
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
window->x + window->parent->abs_x, window->y + window->parent->abs_y,
width, height,
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale,
impl->unscaled_width,
impl->unscaled_height,
SWP_NOACTIVATE | SWP_NOZORDER));
_gdk_win32_window_tmp_reset_bg (window, TRUE);

View File

@ -821,6 +821,7 @@ _gdk_win32_message_to_string (UINT msg)
CASE (WT_PACKET);
CASE (WT_CSRCHANGE);
CASE (WT_PROXIMITY);
CASE (WM_DPICHANGED);
#undef CASE
default:
if (msg >= WM_HANDHELDFIRST && msg <= WM_HANDHELDLAST)

View File

@ -591,6 +591,7 @@ enum_monitor (HMONITOR hmonitor,
GdkWin32Monitor *w32mon;
GdkMonitor *mon;
GdkRectangle rect;
guint scale;
memset (&dd_monitor, 0, sizeof (dd_monitor));
dd_monitor.cb = sizeof (dd_monitor);
@ -680,17 +681,18 @@ enum_monitor (HMONITOR hmonitor,
/* This is the reason this function exists. This data is not available
* via other functions.
*/
rect.x = monitor_info.rcMonitor.left;
rect.y = monitor_info.rcMonitor.top;
rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
scale = gdk_monitor_get_scale_factor (mon);
rect.x = monitor_info.rcMonitor.left / scale;
rect.y = monitor_info.rcMonitor.top / scale;
rect.width = (monitor_info.rcMonitor.right - monitor_info.rcMonitor.left) / scale;
rect.height = (monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top) / scale;
gdk_monitor_set_position (mon, rect.x, rect.y);
gdk_monitor_set_size (mon, rect.width, rect.height);
rect.x = monitor_info.rcWork.left;
rect.y = monitor_info.rcWork.top;
rect.width = monitor_info.rcWork.right - monitor_info.rcWork.left;
rect.height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
rect.x = monitor_info.rcWork.left / scale;
rect.y = monitor_info.rcWork.top / scale;
rect.width = (monitor_info.rcWork.right - monitor_info.rcWork.left) / scale;
rect.height = (monitor_info.rcWork.bottom - monitor_info.rcWork.top) / scale;
w32mon->work_rect = rect;
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY && i != 0)

View File

@ -97,6 +97,9 @@
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x20E
#endif
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
#endif
/* According to
* http://blog.airesoft.co.uk/2009/11/wm_messages/
@ -185,7 +188,8 @@ HRGN _gdk_win32_cairo_region_to_hrgn (const cairo_region_t *region,
gint x_origin,
gint y_origin);
cairo_region_t *_gdk_win32_hrgn_to_region (HRGN hrgn);
cairo_region_t *_gdk_win32_hrgn_to_region (HRGN hrgn,
guint scale);
void _gdk_win32_adjust_client_rect (GdkWindow *window,
RECT *RECT);
@ -544,9 +548,11 @@ gboolean _gdk_win32_window_fill_min_max_info (GdkWindow *window,
gboolean _gdk_win32_window_lacks_wm_decorations (GdkWindow *window);
BOOL WINAPI GtkShowWindow (HWND hwnd,
BOOL WINAPI GtkShowWindow (GdkWindow *window,
int cmd_show);
void _gdk_win32_screen_set_font_resolution (GdkWin32Screen *win32_screen);
/* Initialization */
void _gdk_win32_windowing_init (void);
void _gdk_dnd_init (void);

View File

@ -50,6 +50,7 @@ init_root_window_size (GdkWin32Screen *screen)
int monitor_count;
GdkMonitor *monitor;
gboolean changed;
GdkWindowImplWin32 *root_impl;
monitor_count = gdk_display_get_n_monitors (display);
monitor = gdk_display_get_monitor (display, 0);
@ -68,6 +69,10 @@ init_root_window_size (GdkWin32Screen *screen)
screen->root_window->height != result.height;
screen->root_window->width = result.width;
screen->root_window->height = result.height;
root_impl = GDK_WINDOW_IMPL_WIN32 (screen->root_window->impl);
root_impl->unscaled_width = result.width * root_impl->window_scale;
root_impl->unscaled_height = result.height * root_impl->window_scale;
return changed;
}
@ -79,6 +84,7 @@ init_root_window (GdkWin32Screen *screen_win32)
GdkWindow *window;
GdkWindowImplWin32 *impl_win32;
gboolean changed;
GdkWin32Display *win32_display;
screen = GDK_SCREEN (screen_win32);
@ -103,6 +109,18 @@ init_root_window (GdkWin32Screen *screen_win32)
window->abs_y = 0;
/* width and height already initialised in init_root_window_size() */
window->viewable = TRUE;
win32_display = GDK_WIN32_DISPLAY (_gdk_display);
if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
impl_win32->window_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
NULL,
impl_win32->handle,
NULL);
else
impl_win32->window_scale = 1;
impl_win32->unscaled_width = window->width * impl_win32->window_scale;
impl_win32->unscaled_height = window->height * impl_win32->window_scale;
gdk_win32_handle_table_insert ((HANDLE *) &impl_win32->handle, window);
@ -115,28 +133,7 @@ static void
gdk_win32_screen_init (GdkWin32Screen *win32_screen)
{
GdkScreen *screen = GDK_SCREEN (win32_screen);
HDC screen_dc;
int logpixelsx = -1;
const gchar *font_resolution;
screen_dc = GetDC (NULL);
if (screen_dc)
{
logpixelsx = GetDeviceCaps(screen_dc, LOGPIXELSX);
ReleaseDC (NULL, screen_dc);
}
font_resolution = g_getenv ("GDK_WIN32_FONT_RESOLUTION");
if (font_resolution)
{
int env_logpixelsx = atol (font_resolution);
if (env_logpixelsx > 0)
logpixelsx = env_logpixelsx;
}
if (logpixelsx > 0)
_gdk_screen_set_resolution (screen, logpixelsx);
_gdk_win32_screen_set_font_resolution (win32_screen);
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
init_root_window (win32_screen);
@ -156,6 +153,37 @@ _gdk_win32_screen_on_displaychange_event (GdkWin32Screen *screen)
g_signal_emit_by_name (screen, "monitors-changed");
}
void
_gdk_win32_screen_set_font_resolution (GdkWin32Screen *win32_screen)
{
GdkScreen *screen = GDK_SCREEN (win32_screen);
int logpixelsx = -1;
const gchar *font_resolution;
font_resolution = g_getenv ("GDK_WIN32_FONT_RESOLUTION");
if (font_resolution)
{
int env_logpixelsx = atol (font_resolution);
if (env_logpixelsx > 0)
logpixelsx = env_logpixelsx;
}
else
{
gint dpi = -1;
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (gdk_screen_get_display (screen));
guint scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, &dpi);
/* If we have a scale that is at least 2, don't scale up the fonts */
if (scale >= 2)
logpixelsx = USER_DEFAULT_SCREEN_DPI;
else
logpixelsx = dpi;
}
if (logpixelsx > 0)
_gdk_screen_set_resolution (screen, logpixelsx);
}
static GdkDisplay *
gdk_win32_screen_get_display (GdkScreen *screen)
{

File diff suppressed because it is too large Load Diff

View File

@ -96,6 +96,14 @@ enum _GdkW32WindowDragOp
typedef enum _GdkW32WindowDragOp GdkW32WindowDragOp;
typedef enum _GdkWin32MonitorDpiType
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} GdkWin32MonitorDpiType;
struct _GdkW32DragMoveResizeContext
{
/* The window that is being moved/resized */
@ -333,6 +341,11 @@ struct _GdkWindowImplWin32
* They are removed at the first opportunity (usually WM_INITMENU).
*/
LONG_PTR temp_styles;
/* scale of window on HiDPI */
gint window_scale;
gint unscaled_width;
gint unscaled_height;
};
struct _GdkWindowImplWin32Class
@ -352,6 +365,8 @@ void _gdk_win32_window_tmp_reset_parent_bg (GdkWindow *window);
void _gdk_win32_window_update_style_bits (GdkWindow *window);
gint _gdk_win32_window_get_scale_factor (GdkWindow *window);
G_END_DECLS
#endif /* __GDK_WINDOW_WIN32_H__ */