forked from AuroraMiddleware/gtk
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:
parent
3baa4a9741
commit
6abd65c83b
@ -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;
|
||||
|
@ -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 ())
|
||||
{
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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__ */
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user