Commit 4add92a4 authored by Chun-wei Fan's avatar Chun-wei Fan

GDK-Win32: 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.

-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
parent a64a0bc6
......@@ -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)
{
window = gdk_get_default_root_window ();
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (win_x)
*win_x = screen_pt.x + _gdk_offset_x;
*win_x = (screen_pt.x + _gdk_offset_x) / impl->window_scale;
if (win_y)
*win_y = screen_pt.y + _gdk_offset_y;
*win_y = (screen_pt.y + _gdk_offset_y) / impl->window_scale;
return gdk_get_default_root_window ();
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));
}
......
......@@ -193,6 +193,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;
}
......@@ -793,6 +828,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);
}
......@@ -809,10 +853,213 @@ 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)
{
switch (display->shcore_funcs.setDpiAwareFunc (PROCESS_SYSTEM_DPI_AWARE))
{
case S_OK:
display->dpi_aware_type = PROCESS_SYSTEM_DPI_AWARE;
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);
}
......@@ -880,6 +1127,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,40 @@
#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 +83,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
......@@ -60,4 +103,8 @@ gboolean _gdk_win32_display_init_monitors (GdkWin32Display *display);
GPtrArray *_gdk_win32_display_get_monitor_list (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,15 +44,18 @@
#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"
#include "gdkdeviceprivate.h"
#include "gdkdevice-wintab.h"
#include "gdkwin32dnd.h"
#include "gdkdisplay-win32.h"
#include "gdkdndprivate.h"
#include <windowsx.h>
......@@ -1059,17 +1062,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 +1124,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 +1146,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 +1453,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 +1469,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 +1486,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 +1508,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 +1540,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 +1570,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 +1596,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 +1669,7 @@ handle_nchittest (HWND hwnd,
gint *ret_valp)
{
RECT rect;
GdkWindowImplWin32 *impl;
if (window == NULL || window->input_shape == NULL)
return FALSE;
......@@ -1673,11 +1683,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
......@@ -1695,6 +1708,7 @@ generate_button_event (GdkEventType type,
{
GdkEvent *event = gdk_event_new (type);