summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2016-06-27 13:16:43 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2016-11-04 18:14:48 +0800
commit6abd65c83be6ba4656c5f014bc940c2eea21dfd0 (patch)
tree00fb8a98cb9e43877f73ec897826fb7798351368
parent3baa4a9741835fda4b858a88d48de2bb21620b42 (diff)
downloadgtk+-6abd65c83be6ba4656c5f014bc940c2eea21dfd0.tar.gz
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
-rw-r--r--gdk/win32/gdkdevice-win32.c26
-rw-r--r--gdk/win32/gdkdevice-wintab.c10
-rw-r--r--gdk/win32/gdkdevicemanager-win32.c11
-rw-r--r--gdk/win32/gdkdisplay-win32.c338
-rw-r--r--gdk/win32/gdkdisplay-win32.h47
-rw-r--r--gdk/win32/gdkevents-win32.c191
-rw-r--r--gdk/win32/gdkgeometry-win32.c33
-rw-r--r--gdk/win32/gdkmain-win32.c1
-rw-r--r--gdk/win32/gdkmonitor-win32.c18
-rw-r--r--gdk/win32/gdkprivate-win32.h12
-rw-r--r--gdk/win32/gdkscreen-win32.c72
-rw-r--r--gdk/win32/gdkwindow-win32.c575
-rw-r--r--gdk/win32/gdkwindow-win32.h15
13 files changed, 1027 insertions, 322 deletions
diff --git a/gdk/win32/gdkdevice-win32.c b/gdk/win32/gdkdevice-win32.c
index 94da520de5..190372de2d 100644
--- a/gdk/win32/gdkdevice-win32.c
+++ b/gdk/win32/gdkdevice-win32.c
@@ -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;
diff --git a/gdk/win32/gdkdevice-wintab.c b/gdk/win32/gdkdevice-wintab.c
index 18279a8862..06037d87c5 100644
--- a/gdk/win32/gdkdevice-wintab.c
+++ b/gdk/win32/gdkdevice-wintab.c
@@ -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 ())
{
diff --git a/gdk/win32/gdkdevicemanager-win32.c b/gdk/win32/gdkdevicemanager-win32.c
index e64c02d5df..62c164d355 100644
--- a/gdk/win32/gdkdevicemanager-win32.c
+++ b/gdk/win32/gdkdevicemanager-win32.c
@@ -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));
}
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index 0d626c46f2..8cb0aa094a 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -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);
}
@@ -806,9 +850,220 @@ gdk_win32_display_finalize (GObject *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)
{
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index e36d8c47be..c468a0e8e3 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -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__ */
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 411bd0fb99..3a253487ec 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -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
@@ -1688,6 +1700,67 @@ handle_nchittest (HWND hwnd,
}
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,
GdkWindow *window,
@@ -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))
diff --git a/gdk/win32/gdkgeometry-win32.c b/gdk/win32/gdkgeometry-win32.c
index 7d955f3267..02d61ef436 100644
--- a/gdk/win32/gdkgeometry-win32.c
+++ b/gdk/win32/gdkgeometry-win32.c
@@ -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)
- {
- g_warning ("Native children wider or taller than 65535 pixels are not supported.");
+ 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);
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index 79dc35f198..2c45cb3b78 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -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)
diff --git a/gdk/win32/gdkmonitor-win32.c b/gdk/win32/gdkmonitor-win32.c
index b78309841d..1686eb59be 100644
--- a/gdk/win32/gdkmonitor-win32.c
+++ b/gdk/win32/gdkmonitor-win32.c
@@ -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)
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index 2966074a6a..27c0663a6f 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -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,8 +548,10 @@ gboolean _gdk_win32_window_fill_min_max_info (GdkWindow *window,
gboolean _gdk_win32_window_lacks_wm_decorations (GdkWindow *window);
-BOOL WINAPI GtkShowWindow (HWND hwnd,
- int cmd_show);
+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);
diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c
index cd1c9ffc95..20390382f4 100644
--- a/gdk/win32/gdkscreen-win32.c
+++ b/gdk/win32/gdkscreen-win32.c
@@ -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)
{
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index a68e863b91..9069b4c306 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -37,8 +37,10 @@
#include "gdkwin32.h"
#include "gdkdisplayprivate.h"
#include "gdkvisualprivate.h"
+#include "gdkmonitorprivate.h"
#include "gdkwin32window.h"
#include "gdkglcontext-win32.h"
+#include "gdkdisplay-win32.h"
#include <cairo-win32.h>
#include <dwmapi.h>
@@ -206,6 +208,7 @@ gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
impl->transient_children = NULL;
impl->num_transients = 0;
impl->changing_state = FALSE;
+ impl->window_scale = 1;
if (display != NULL)
/* Replace WM-defined default cursor with the default cursor
@@ -261,21 +264,22 @@ gdk_win32_window_get_queued_window_rect (GdkWindow *window,
{
gint x, y;
RECT window_rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
gdk_window_get_position (window, &x, &y);
window_rect.left = x;
window_rect.top = y;
- window_rect.right = window_rect.left + gdk_window_get_width (window);
- window_rect.bottom = window_rect.top + gdk_window_get_height (window);
+ window_rect.right = window_rect.left + gdk_window_get_width (window) * impl->window_scale;
+ window_rect.bottom = window_rect.top + gdk_window_get_height (window) * impl->window_scale;
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (window, &window_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
- window_rect.left -= _gdk_offset_x;
- window_rect.right -= _gdk_offset_x;
- window_rect.top -= _gdk_offset_y;
- window_rect.bottom -= _gdk_offset_y;
+ window_rect.left -= _gdk_offset_x * impl->window_scale;
+ window_rect.right -= _gdk_offset_x * impl->window_scale;
+ window_rect.top -= _gdk_offset_y * impl->window_scale;
+ window_rect.bottom -= _gdk_offset_y * impl->window_scale;
*return_window_rect = window_rect;
}
@@ -286,6 +290,7 @@ gdk_win32_window_apply_queued_move_resize (GdkWindow *window,
{
if (!IsIconic (GDK_WINDOW_HWND (window)))
{
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
@@ -389,6 +394,7 @@ gdk_win32_window_end_paint (GdkWindow *window)
window_position.x = window_rect.left;
window_position.y = window_rect.top;
+
window_size.cx = window_rect.right - window_rect.left;
window_size.cy = window_rect.bottom - window_rect.top;
@@ -693,6 +699,7 @@ _gdk_win32_display_create_window_impl (GdkDisplay *display,
DWORD dwStyle = 0, dwExStyle;
RECT rect;
GdkWindowImplWin32 *impl;
+ GdkWin32Display *display_win32;
const gchar *title;
wchar_t *wtitle;
gboolean override_redirect;
@@ -746,6 +753,11 @@ _gdk_win32_display_create_window_impl (GdkDisplay *display,
impl->layered = FALSE;
impl->layered_opacity = 1.0;
+ display_win32 = GDK_WIN32_DISPLAY (display);
+ impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
+ impl->unscaled_width = window->width * impl->window_scale;
+ impl->unscaled_height = window->height * impl->window_scale;
+
if (!window->input_only)
{
dwExStyle = 0;
@@ -805,15 +817,15 @@ _gdk_win32_display_create_window_impl (GdkDisplay *display,
if (window->window_type != GDK_WINDOW_CHILD)
{
- rect.left = window->x;
- rect.top = window->y;
- rect.right = window->width + window->x;
- rect.bottom = window->height + window->y;
+ rect.left = window->x * impl->window_scale;
+ rect.top = window->y * impl->window_scale;
+ rect.right = rect.left + window->width * impl->window_scale;
+ rect.bottom = rect.top + window->height * impl->window_scale;
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
- real_x = window->x - offset_x;
- real_y = window->y - offset_y;
+ real_x = (window->x - offset_x) * impl->window_scale;
+ real_y = (window->y - offset_y) * impl->window_scale;
if (window->window_type == GDK_WINDOW_TOPLEVEL)
{
@@ -834,11 +846,11 @@ _gdk_win32_display_create_window_impl (GdkDisplay *display,
else
{
/* adjust position relative to real_parent */
- window_width = window->width;
- window_height = window->height;
+ window_width = impl->unscaled_width;
+ window_height = impl->unscaled_height;
/* use given position for initial placement, native coordinates */
- x = window->x + window->parent->abs_x - offset_x;
- y = window->y + window->parent->abs_y - offset_y;
+ x = (window->x + window->parent->abs_x - offset_x) * impl->window_scale;
+ y = (window->y + window->parent->abs_y - offset_y) * impl->window_scale;
}
if (attributes_mask & GDK_WA_TITLE)
@@ -975,8 +987,10 @@ gdk_win32_window_foreign_new_for_display (GdkDisplay *display,
ScreenToClient (parent, &point);
window->x = point.x;
window->y = point.y;
- window->width = rect.right - rect.left;
- window->height = rect.bottom - rect.top;
+ 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->window_type = GDK_WINDOW_FOREIGN;
window->destroyed = FALSE;
window->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
@@ -1089,9 +1103,11 @@ get_outer_rect (GdkWindow *window,
gint height,
RECT *rect)
{
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
rect->left = rect->top = 0;
- rect->right = width;
- rect->bottom = height;
+ rect->right = width * impl->window_scale;
+ rect->bottom = height * impl->window_scale;
_gdk_win32_adjust_client_rect (window, rect);
}
@@ -1102,9 +1118,7 @@ adjust_for_gravity_hints (GdkWindow *window,
gint *x,
gint *y)
{
- GdkWindowImplWin32 *impl;
-
- impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
{
@@ -1117,19 +1131,19 @@ adjust_for_gravity_hints (GdkWindow *window,
case GDK_GRAVITY_NORTH:
case GDK_GRAVITY_CENTER:
case GDK_GRAVITY_SOUTH:
- *x -= (outer_rect->right - outer_rect->left) / 2;
+ *x -= (outer_rect->right - outer_rect->left / 2) / impl->window_scale;
*x += window->width / 2;
break;
case GDK_GRAVITY_SOUTH_EAST:
case GDK_GRAVITY_EAST:
case GDK_GRAVITY_NORTH_EAST:
- *x -= outer_rect->right - outer_rect->left;
+ *x -= (outer_rect->right - outer_rect->left) / impl->window_scale;
*x += window->width;
break;
case GDK_GRAVITY_STATIC:
- *x += outer_rect->left;
+ *x += outer_rect->left / impl->window_scale;
break;
default:
@@ -1141,19 +1155,19 @@ adjust_for_gravity_hints (GdkWindow *window,
case GDK_GRAVITY_WEST:
case GDK_GRAVITY_CENTER:
case GDK_GRAVITY_EAST:
- *y -= (outer_rect->bottom - outer_rect->top) / 2;
+ *y -= ((outer_rect->bottom - outer_rect->top) / 2) / impl->window_scale;
*y += window->height / 2;
break;
case GDK_GRAVITY_SOUTH_WEST:
case GDK_GRAVITY_SOUTH:
case GDK_GRAVITY_SOUTH_EAST:
- *y -= outer_rect->bottom - outer_rect->top;
+ *y -= (outer_rect->bottom - outer_rect->top) / impl->window_scale;
*y += window->height;
break;
case GDK_GRAVITY_STATIC:
- *y += outer_rect->top;
+ *y += outer_rect->top * impl->window_scale;
break;
default:
@@ -1191,7 +1205,7 @@ show_window_internal (GdkWindow *window,
!already_mapped &&
(window->state & GDK_WINDOW_STATE_ICONIFIED))
{
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMINNOACTIVE);
+ GtkShowWindow (window, SW_SHOWMINNOACTIVE);
return;
}
@@ -1280,10 +1294,11 @@ show_window_internal (GdkWindow *window,
{
GdkWindow *owner = window_impl->transient_owner;
/* Center on transient parent */
- center_on_rect.left = owner->x - _gdk_offset_x;
- center_on_rect.top = owner->y - _gdk_offset_y;
- center_on_rect.right = center_on_rect.left + owner->width;
- center_on_rect.bottom = center_on_rect.top + owner->height;
+ center_on_rect.left = (owner->x - _gdk_offset_x) * window_impl->window_scale;
+ center_on_rect.top = (owner->y - _gdk_offset_y) * window_impl->window_scale;
+ center_on_rect.right = center_on_rect.left + owner->width * window_impl->window_scale;
+ center_on_rect.bottom = center_on_rect.top + owner->height * window_impl->window_scale;
+
_gdk_win32_adjust_client_rect (GDK_WINDOW (owner), &center_on_rect);
center = TRUE;
}
@@ -1292,8 +1307,8 @@ show_window_internal (GdkWindow *window,
{
window_rect.left = 0;
window_rect.top = 0;
- window_rect.right = window->width;
- window_rect.bottom = window->height;
+ window_rect.right = window->width * window_impl->window_scale;
+ window_rect.bottom = window->height * window_impl->window_scale;
_gdk_win32_adjust_client_rect (window, &window_rect);
x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
@@ -1364,29 +1379,29 @@ show_window_internal (GdkWindow *window,
}
else if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
{
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
+ GtkShowWindow (window, SW_MAXIMIZE);
}
else if (window->state & GDK_WINDOW_STATE_ICONIFIED)
{
if (focus_on_map)
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
+ GtkShowWindow (window, SW_RESTORE);
else
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
+ GtkShowWindow (window, SW_SHOWNOACTIVATE);
}
else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
{
if (!IsWindowVisible (GDK_WINDOW_HWND (window)))
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
+ GtkShowWindow (window, SW_SHOWNOACTIVATE);
else
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
+ GtkShowWindow (window, SW_SHOWNA);
}
else if (!IsWindowVisible (GDK_WINDOW_HWND (window)))
{
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
+ GtkShowWindow (window, SW_SHOWNORMAL);
}
else
{
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOW);
+ GtkShowWindow (window, SW_SHOW);
}
/* Sync STATE_ABOVE to TOPMOST */
@@ -1441,7 +1456,7 @@ gdk_win32_window_hide (GdkWindow *window)
}
else
{
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
+ GtkShowWindow (window, SW_HIDE);
}
}
@@ -1484,6 +1499,7 @@ gdk_win32_window_move (GdkWindow *window,
else
{
RECT outer_rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
get_outer_rect (window, window->width, window->height, &outer_rect);
@@ -1492,11 +1508,14 @@ gdk_win32_window_move (GdkWindow *window,
GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
"NOACTIVATE|NOSIZE|NOZORDER)\n",
GDK_WINDOW_HWND (window),
- x - _gdk_offset_x, y - _gdk_offset_y));
+ (x - _gdk_offset_x) * impl->window_scale,
+ (y - _gdk_offset_y) * impl->window_scale));
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
SWP_NOZORDER_SPECIFIED,
- x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
+ (x - _gdk_offset_x) * impl->window_scale,
+ (y - _gdk_offset_y) * impl->window_scale,
+ 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
}
}
@@ -1528,6 +1547,7 @@ gdk_win32_window_resize (GdkWindow *window,
else
{
RECT outer_rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
get_outer_rect (window, width, height, &outer_rect);
@@ -1578,6 +1598,7 @@ gdk_win32_window_move_resize_internal (GdkWindow *window,
else
{
RECT outer_rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
get_outer_rect (window, width, height, &outer_rect);
@@ -1586,13 +1607,15 @@ gdk_win32_window_move_resize_internal (GdkWindow *window,
GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
"NOACTIVATE|NOZORDER)\n",
GDK_WINDOW_HWND (window),
- x - _gdk_offset_x, y - _gdk_offset_y,
+ (x - _gdk_offset_x) * impl->window_scale,
+ (y - _gdk_offset_y) * impl->window_scale,
outer_rect.right - outer_rect.left,
outer_rect.bottom - outer_rect.top));
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
SWP_NOZORDER_SPECIFIED,
- x - _gdk_offset_x, y - _gdk_offset_y,
+ (x - _gdk_offset_x) * impl->window_scale,
+ (y - _gdk_offset_y) * impl->window_scale,
outer_rect.right - outer_rect.left,
outer_rect.bottom - outer_rect.top,
SWP_NOACTIVATE | SWP_NOZORDER));
@@ -2220,6 +2243,7 @@ gdk_win32_window_get_geometry (GdkWindow *window,
if (!GDK_WINDOW_DESTROYED (window))
{
RECT rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
@@ -2244,25 +2268,26 @@ gdk_win32_window_get_geometry (GdkWindow *window,
if (gdk_screen_get_root_window (screen) == parent)
{
- rect.left += _gdk_offset_x;
- rect.top += _gdk_offset_y;
- rect.right += _gdk_offset_x;
- rect.bottom += _gdk_offset_y;
+ rect.left += _gdk_offset_x * impl->window_scale;
+ rect.top += _gdk_offset_y * impl->window_scale;
+ rect.right += _gdk_offset_x * impl->window_scale;
+ rect.bottom += _gdk_offset_y * impl->window_scale;
}
}
if (x)
- *x = rect.left;
+ *x = rect.left / impl->window_scale;
if (y)
- *y = rect.top;
+ *y = rect.top / impl->window_scale;
if (width)
- *width = rect.right - rect.left;
+ *width = (rect.right - rect.left) / impl->window_scale;
if (height)
- *height = rect.bottom - rect.top;
+ *height = (rect.bottom - rect.top) / impl->window_scale;
- GDK_NOTE (MISC, g_print ("gdk_win32_window_get_geometry: %p: %ldx%ld@%+ld%+ld\n",
+ GDK_NOTE (MISC, g_print ("gdk_win32_window_get_geometry: %p: %ldx%ld@%+ld%\n",
GDK_WINDOW_HWND (window),
- rect.right - rect.left, rect.bottom - rect.top,
+ (rect.right - rect.left) / impl->window_scale,
+ (rect.bottom - rect.top) / impl->window_scale,
rect.left, rect.top));
}
}
@@ -2277,22 +2302,25 @@ gdk_win32_window_get_root_coords (GdkWindow *window,
gint tx;
gint ty;
POINT pt;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
- pt.x = x;
- pt.y = y;
+ pt.x = x * impl->window_scale;
+ pt.y = y * impl->window_scale;
ClientToScreen (GDK_WINDOW_HWND (window), &pt);
tx = pt.x;
ty = pt.y;
if (root_x)
- *root_x = tx + _gdk_offset_x;
+ *root_x = (tx + _gdk_offset_x) / impl->window_scale;
if (root_y)
- *root_y = ty + _gdk_offset_y;
+ *root_y = (ty + _gdk_offset_y) / impl->window_scale;
GDK_NOTE (MISC, g_print ("gdk_win32_window_get_root_coords: %p: %+d%+d %+d%+d\n",
GDK_WINDOW_HWND (window),
- x, y,
- tx + _gdk_offset_x, ty + _gdk_offset_y));
+ x * impl->window_scale,
+ y * impl->window_scale,
+ (tx + _gdk_offset_x) / impl->window_scale,
+ (ty + _gdk_offset_y) / impl->window_scale));
}
static void
@@ -2316,6 +2344,7 @@ gdk_win32_window_get_frame_extents (GdkWindow *window,
{
HWND hwnd;
RECT r;
+ GdkWindowImplWin32 *impl;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (rect != NULL);
@@ -2334,17 +2363,19 @@ gdk_win32_window_get_frame_extents (GdkWindow *window,
while (window->parent && window->parent->parent)
window = window->parent;
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
hwnd = GDK_WINDOW_HWND (window);
API_CALL (GetWindowRect, (hwnd, &r));
rect->x = r.left + _gdk_offset_x;
rect->y = r.top + _gdk_offset_y;
- rect->width = r.right - r.left;
- rect->height = r.bottom - r.top;
+ rect->width = (r.right - r.left) / impl->window_scale;
+ rect->height = (r.bottom - r.top) / impl->window_scale;
GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
GDK_WINDOW_HWND (window),
- r.right - r.left, r.bottom - r.top,
+ (r.right - r.left) / impl->window_scale,
+ (r.bottom - r.top) / impl->window_scale,
r.left, r.top));
}
@@ -2415,8 +2446,10 @@ do_shape_combine_region (GdkWindow *window,
gint x, gint y)
{
RECT rect;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GetClientRect (GDK_WINDOW_HWND (window), &rect);
+
_gdk_win32_adjust_client_rect (window, &rect);
OffsetRgn (hrgn, -rect.left, -rect.top);
@@ -2973,6 +3006,7 @@ calculate_aerosnap_regions (GdkW32DragMoveResizeContext *context)
{
GdkDisplay *display;
gint n_monitors, monitor_idx, other_monitor_idx;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (context->window->impl);
#if defined(MORE_AEROSNAP_DEBUGGING)
gint i;
#endif
@@ -3041,10 +3075,8 @@ calculate_aerosnap_regions (GdkW32DragMoveResizeContext *context)
}
}
- /* TODO: scale it for Hi-DPI displays? */
- thickness = AEROSNAP_REGION_THICKNESS;
- /* TODO: scale it for Hi-DPI displays? */
- trigger_thickness = AEROSNAP_REGION_TRIGGER_THICKNESS;
+ thickness = AEROSNAP_REGION_THICKNESS * impl->window_scale;
+ trigger_thickness = AEROSNAP_REGION_TRIGGER_THICKNESS * impl->window_scale;
snap_region.edge = wa;
snap_region.trigger = wa;
@@ -3257,18 +3289,18 @@ stash_window (GdkWindow *window,
impl->snap_stash_int = g_new0 (GdkRectangle, 1);
GDK_NOTE (MISC, g_print ("monitor work area %ld x %ld @ %ld : %ld\n",
- hmonitor_info.rcWork.right - hmonitor_info.rcWork.left,
- hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top,
+ (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left) / impl->window_scale,
+ (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top) / impl->window_scale,
hmonitor_info.rcWork.left,
hmonitor_info.rcWork.top));
GDK_NOTE (MISC, g_print ("monitor area %ld x %ld @ %ld : %ld\n",
- hmonitor_info.rcMonitor.right - hmonitor_info.rcMonitor.left,
- hmonitor_info.rcMonitor.bottom - hmonitor_info.rcMonitor.top,
+ (hmonitor_info.rcMonitor.right - hmonitor_info.rcMonitor.left) / impl->window_scale,
+ (hmonitor_info.rcMonitor.bottom - hmonitor_info.rcMonitor.top) / impl->window_scale,
hmonitor_info.rcMonitor.left,
hmonitor_info.rcMonitor.top));
GDK_NOTE (MISC, g_print ("window work place %ld x %ld @ %ld : %ld\n",
- placement.rcNormalPosition.right - placement.rcNormalPosition.left,
- placement.rcNormalPosition.bottom - placement.rcNormalPosition.top,
+ (placement.rcNormalPosition.right - placement.rcNormalPosition.left) / impl->window_scale,
+ (placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) / impl->window_scale,
placement.rcNormalPosition.left,
placement.rcNormalPosition.top));
@@ -3277,15 +3309,15 @@ stash_window (GdkWindow *window,
x = placement.rcNormalPosition.left - hmonitor_info.rcMonitor.left;
y = placement.rcNormalPosition.top - hmonitor_info.rcMonitor.top;
- impl->snap_stash->x = (gdouble) (x) / (gdouble) (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left);
- impl->snap_stash->y = (gdouble) (y) / (gdouble) (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top);
- impl->snap_stash->width = (gdouble) width / (gdouble) (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left);
- impl->snap_stash->height = (gdouble) height / (gdouble) (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top);
+ impl->snap_stash->x = ((gdouble) (x) / (gdouble) (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left)) / impl->window_scale;
+ impl->snap_stash->y = ((gdouble) (y) / (gdouble) (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top)) / impl->window_scale;
+ impl->snap_stash->width = ((gdouble) width / (gdouble) (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left)) / impl->window_scale;
+ impl->snap_stash->height = ((gdouble) height / (gdouble) (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top)) / impl->window_scale;
- impl->snap_stash_int->x = x;
- impl->snap_stash_int->y = y;
- impl->snap_stash_int->width = width;
- impl->snap_stash_int->height = height;
+ impl->snap_stash_int->x = x / impl->window_scale;
+ impl->snap_stash_int->y = y / impl->window_scale;
+ impl->snap_stash_int->width = width / impl->window_scale;
+ impl->snap_stash_int->height = height / impl->window_scale;
GDK_NOTE (MISC, g_print ("Stashed window %d x %d @ %d : %d as %f x %f @ %f : %f\n",
width, height, x, y,
@@ -3306,15 +3338,15 @@ snap_up (GdkWindow *window)
stash_window (window, impl);
- maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+ maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
gdk_window_get_position (window, &x, &y);
width = gdk_window_get_width (window);
y = 0;
height = maxysize;
- x -= impl->margins.left;
- y -= impl->margins.top;
+ x = (x - impl->margins.left) / impl->window_scale;
+ y = (y - impl->margins.top) / impl->window_scale;
width += impl->margins_x;
height += impl->margins_y;
@@ -3337,12 +3369,12 @@ snap_left (GdkWindow *window,
stash_window (window, impl);
- rect.width = rect.width / 2;
+ rect.width = rect.width / 2 / impl->window_scale;
- rect.x -= impl->margins.left;
- rect.y -= impl->margins.top;
- rect.width += impl->margins_x;
- rect.height += impl->margins_y;
+ rect.x = rect.x - impl->margins.left / impl->window_scale;
+ rect.y = rect.y - impl->margins.top / impl->window_scale;
+ rect.width = rect.width + impl->margins_x;
+ rect.height = rect.height + impl->margins_y;
gdk_window_move_resize (window, rect.x, rect.y, rect.width, rect.height);
}
@@ -3363,13 +3395,13 @@ snap_right (GdkWindow *window,
stash_window (window, impl);
- rect.width /= 2;
+ rect.width = rect.width / 2 / impl->window_scale;;
rect.x += rect.width;
- rect.x -= impl->margins.left;
- rect.y -= impl->margins.top;
- rect.width += impl->margins_x;
- rect.height += impl->margins_y;
+ rect.x = rect.x - impl->margins.left / impl->window_scale;
+ rect.y = rect.y - impl->margins.top / impl->window_scale;
+ rect.width = rect.width + impl->margins_x / impl->window_scale;
+ rect.height = rect.height + impl->margins_y / impl->window_scale;
gdk_window_move_resize (window, rect.x, rect.y, rect.width, rect.height);
}
@@ -3598,7 +3630,8 @@ ensure_snap_indicator_exists (GdkW32DragMoveResizeContext *context)
static gboolean
ensure_snap_indicator_surface (GdkW32DragMoveResizeContext *context,
gint width,
- gint height)
+ gint height,
+ guint scale)
{
if (context->indicator_surface != NULL &&
(context->indicator_surface_width < width ||
@@ -3609,7 +3642,9 @@ ensure_snap_indicator_surface (GdkW32DragMoveResizeContext *context,
}
if (context->indicator_surface == NULL)
- context->indicator_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+ context->indicator_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+ width * scale,
+ height * scale);
if (cairo_surface_status (context->indicator_surface) != CAIRO_STATUS_SUCCESS)
{
@@ -3627,10 +3662,11 @@ ensure_snap_indicator_surface (GdkW32DragMoveResizeContext *context,
*/
static void
adjust_indicator_rectangle (GdkRectangle *rect,
- gboolean inward)
+ gboolean inward,
+ guint scale)
{
gdouble inverter;
- gint gap;
+ const gint gap = AEROSNAP_INDICATOR_EDGE_GAP;
#if defined(MORE_AEROSNAP_DEBUGGING)
GdkRectangle cache = *rect;
#endif
@@ -3640,13 +3676,10 @@ adjust_indicator_rectangle (GdkRectangle *rect,
else
inverter = -1.0;
- /* TODO: Adjust for HiDPI? */
- gap = AEROSNAP_INDICATOR_EDGE_GAP;
-
- rect->x += gap * inverter;
- rect->y += gap * inverter;
- rect->width -= gap * 2 * inverter;
- rect->height -= gap * 2 * inverter;
+ rect->x += (gap * inverter);
+ rect->y += (gap * inverter);
+ rect->width -= (gap * 2 * inverter) * scale;
+ rect->height -= (gap * 2 * inverter) * scale;
#if defined(MORE_AEROSNAP_DEBUGGING)
GDK_NOTE (MISC, g_print ("Adjusted %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
@@ -3664,7 +3697,8 @@ rounded_rectangle (cairo_t *cr,
gdouble radius,
gdouble line_width,
GdkRGBA *fill,
- GdkRGBA *outline)
+ GdkRGBA *outline,
+ guint scale)
{
gdouble degrees = M_PI / 180.0;
@@ -3673,10 +3707,10 @@ rounded_rectangle (cairo_t *cr,
cairo_save (cr);
cairo_new_sub_path (cr);
- cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
- cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
- cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
- cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
+ cairo_arc (cr, x * scale + width - radius * scale, y * scale + radius * scale, radius * scale, -90 * degrees, 0 * degrees);
+ cairo_arc (cr, x * scale + width - radius * scale, y * scale + height - radius * scale, radius * scale, 0 * degrees, 90 * degrees);
+ cairo_arc (cr, (x + radius) * scale, y * scale + height - radius * scale, radius * scale, 90 * degrees, 180 * degrees);
+ cairo_arc (cr, (x + radius) * scale, (y + radius) * scale, radius * scale, 180 * degrees, 270 * degrees);
cairo_close_path (cr);
if (fill)
@@ -3721,10 +3755,9 @@ draw_indicator (GdkW32DragMoveResizeContext *context,
gdouble line_width;
gdouble corner_radius;
gint64 animation_duration;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (context->window->impl);
- /* TODO: Adjust for HiDPI? */
line_width = AEROSNAP_INDICATOR_LINE_WIDTH;
- /* TODO: Adjust for HiDPI? */
corner_radius = AEROSNAP_INDICATOR_CORNER_RADIUS;
animation_duration = AEROSNAP_INDICATOR_ANIMATION_DURATION;
last_draw = FALSE;
@@ -3794,10 +3827,11 @@ draw_indicator (GdkW32DragMoveResizeContext *context,
rounded_rectangle (cr,
current_rect.x - context->indicator_window_rect.x,
current_rect.y - context->indicator_window_rect.y,
- current_rect.width, current_rect.height,
+ current_rect.width,
+ current_rect.height,
corner_radius,
line_width,
- &fill, &outline);
+ &fill, &outline, impl->window_scale);
cairo_destroy (cr);
#if defined(MORE_AEROSNAP_DEBUGGING)
@@ -3822,14 +3856,28 @@ redraw_indicator (gpointer user_data)
POINT source_point = { 0, 0 };
gboolean last_draw;
gdouble indicator_opacity;
+ GdkWindowImplWin32 *impl;
+ gboolean do_source_remove = FALSE;
indicator_opacity = AEROSNAP_INDICATOR_OPACITY;
if (GDK_WINDOW_DESTROYED (context->window) ||
- !ensure_snap_indicator_exists (context) ||
- !ensure_snap_indicator_surface (context,
- context->indicator_window_rect.width,
- context->indicator_window_rect.height))
+ !ensure_snap_indicator_exists (context))
+ {
+ do_source_remove = TRUE;
+ }
+
+ impl = GDK_WINDOW_IMPL_WIN32 (context->window->impl);
+
+ if (!ensure_snap_indicator_surface (context,
+ context->indicator_window_rect.width,
+ context->indicator_window_rect.height,
+ impl->window_scale))
+ {
+ do_source_remove = TRUE;
+ }
+
+ if (do_source_remove)
{
context->timer = 0;
return G_SOURCE_REMOVE;
@@ -3837,10 +3885,10 @@ redraw_indicator (gpointer user_data)
last_draw = draw_indicator (context, context->draw_timestamp);
- window_position.x = context->indicator_window_rect.x - _gdk_offset_x;
- window_position.y = context->indicator_window_rect.y - _gdk_offset_y;
- window_size.cx = context->indicator_window_rect.width;
- window_size.cy = context->indicator_window_rect.height;
+ window_position.x = (context->indicator_window_rect.x - _gdk_offset_x) * impl->window_scale;
+ window_position.y = (context->indicator_window_rect.y - _gdk_offset_y) * impl->window_scale;
+ window_size.cx = context->indicator_window_rect.width * impl->window_scale;
+ window_size.cy = context->indicator_window_rect.height * impl->window_scale;
blender.BlendOp = AC_SRC_OVER;
blender.BlendFlags = 0;
@@ -3906,13 +3954,14 @@ unity_of_rects (GdkRectangle a,
static void
start_indicator_drawing (GdkW32DragMoveResizeContext *context,
GdkRectangle from,
- GdkRectangle to)
+ GdkRectangle to,
+ guint scale)
{
GdkRectangle to_adjusted, from_adjusted, from_or_to;
gint64 indicator_animation_tick = AEROSNAP_INDICATOR_ANIMATION_TICK;
GDK_NOTE (MISC, g_print ("Start drawing snap indicator %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
- from.width, from.height, from.x, from.y, to.width, to.height, to.x, to.y));
+ from.width * scale, from.height * scale, from.x, from.y, to.width * scale, to.height * scale, to.x, to.y));
if (GDK_WINDOW_DESTROYED (context->window))
return;
@@ -3922,13 +3971,14 @@ start_indicator_drawing (GdkW32DragMoveResizeContext *context,
from_or_to = unity_of_rects (from, to);
- if (!ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height))
+ if (!ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, scale))
return;
to_adjusted = to;
- adjust_indicator_rectangle (&to_adjusted, TRUE);
+ adjust_indicator_rectangle (&to_adjusted, TRUE, scale);
+
from_adjusted = from;
- adjust_indicator_rectangle (&from_adjusted, TRUE);
+ adjust_indicator_rectangle (&from_adjusted, TRUE, scale);
context->draw_timestamp = 0;
context->indicator_start = from_adjusted;
@@ -3956,6 +4006,7 @@ update_fullup_indicator (GdkWindow *window,
SHORT maxysize;
GdkRectangle from, to;
GdkRectangle to_adjusted, from_adjusted, from_or_to;
+ GdkWindowImplWin32 *impl;
GDK_NOTE (MISC, g_print ("Update fullup indicator\n"));
@@ -3965,10 +4016,13 @@ update_fullup_indicator (GdkWindow *window,
if (context->shape_indicator == NULL)
return;
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN);
gdk_window_get_position (window, &to.x, &to.y);
- to.width = gdk_window_get_width (window);
- to.height = gdk_window_get_height (window);
+ to.x /= impl->window_scale;
+ to.y /= impl->window_scale;
+ to.width = gdk_window_get_width (window) * impl->window_scale;
+ to.height = gdk_window_get_height (window) * impl->window_scale;
to.y = 0;
to.height = maxysize;
@@ -3977,13 +4031,13 @@ update_fullup_indicator (GdkWindow *window,
if (context->timer == 0)
{
from_adjusted = from;
- adjust_indicator_rectangle (&from_adjusted, FALSE);
+ adjust_indicator_rectangle (&from_adjusted, FALSE, impl->window_scale);
GDK_NOTE (MISC, g_print ("Restart fullup animation from %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
context->indicator_target.width, context->indicator_target.height,
context->indicator_target.x, context->indicator_target.y,
to.width, to.height, to.x, to.y));
- start_indicator_drawing (context, from_adjusted, to);
+ start_indicator_drawing (context, from_adjusted, to, impl->window_scale);
return;
}
@@ -3991,7 +4045,7 @@ update_fullup_indicator (GdkWindow *window,
from_or_to = unity_of_rects (from, to);
to_adjusted = to;
- adjust_indicator_rectangle (&to_adjusted, TRUE);
+ adjust_indicator_rectangle (&to_adjusted, TRUE, impl->window_scale);
GDK_NOTE (MISC, g_print ("Retarget fullup animation %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
context->indicator_target.width, context->indicator_target.height,
@@ -4001,7 +4055,7 @@ update_fullup_indicator (GdkWindow *window,
context->indicator_target = to_adjusted;
context->indicator_window_rect = from_or_to;
- ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height);
+ ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, impl->window_scale);
}
static void
@@ -4016,12 +4070,13 @@ start_indicator (GdkWindow *window,
SHORT maxysize;
GdkRectangle start_size, end_size;
GdkDisplay *display;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
display = gdk_window_get_display (window);
monitor = gdk_display_get_monitor_at_point (display, x, y);
gdk_monitor_get_workarea (monitor, &workarea);
- maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+ maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
gdk_window_get_position (window, &start_size.x, &start_size.y);
start_size.width = gdk_window_get_width (window);
start_size.height = gdk_window_get_height (window);
@@ -4045,7 +4100,7 @@ start_indicator (GdkWindow *window,
end_size.height = workarea.height;
break;
case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
- end_size.x = workarea.x + workarea.width / 2;
+ end_size.x = (workarea.x + workarea.width / 2) / impl->window_scale;
end_size.y = workarea.y;
end_size.width = workarea.width / 2;
end_size.height = workarea.height;
@@ -4056,7 +4111,7 @@ start_indicator (GdkWindow *window,
break;
}
- start_indicator_drawing (context, start_size, end_size);
+ start_indicator_drawing (context, start_size, end_size, impl->window_scale);
}
static void
@@ -4079,18 +4134,23 @@ stop_indicator (GdkWindow *window,
}
static gint
-point_in_aerosnap_region (gint x, gint y, AeroSnapEdgeRegion *region)
+point_in_aerosnap_region (gint x,
+ gint y,
+ AeroSnapEdgeRegion *region,
+ guint scale)
{
gint edge, trigger;
-
- edge = (x >= region->edge.x &&
- y >= region->edge.y &&
- x <= region->edge.x + region->edge.width &&
- y <= region->edge.y + region->edge.height) ? 1 : 0;
- trigger = (x >= region->trigger.x &&
- y >= region->trigger.y &&
- x <= region->trigger.x + region->trigger.width &&
- y <= region->trigger.y + region->trigger.height) ? 1 : 0;
+ gint x_scaled = x * scale;
+ gint y_scaled = y * scale;
+
+ edge = (x_scaled >= region->edge.x &&
+ y_scaled >= region->edge.y &&
+ x_scaled <= region->edge.x + region->edge.width &&
+ y_scaled <= region->edge.y + region->edge.height) ? 1 : 0;
+ trigger = (x_scaled >= region->trigger.x &&
+ y_scaled >= region->trigger.y &&
+ x_scaled <= region->trigger.x + region->trigger.width &&
+ y_scaled <= region->trigger.y + region->trigger.height) ? 1 : 0;
return edge + trigger;
}
@@ -4107,6 +4167,7 @@ handle_aerosnap_move_resize (GdkWindow *window,
gint halfright = 0;
gint fullup = 0;
gboolean fullup_edge = FALSE;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (context->op == GDK_WIN32_DRAGOP_RESIZE)
switch (context->edge)
@@ -4127,25 +4188,25 @@ handle_aerosnap_move_resize (GdkWindow *window,
for (i = 0; i < context->maximize_regions->len && maximize == 0; i++)
{
reg = &g_array_index (context->maximize_regions, AeroSnapEdgeRegion, i);
- maximize = point_in_aerosnap_region (x, y, reg);
+ maximize = point_in_aerosnap_region (x, y, reg, impl->window_scale);
}
for (i = 0; i < context->halfleft_regions->len && halfleft == 0; i++)
{
reg = &g_array_index (context->halfleft_regions, AeroSnapEdgeRegion, i);
- halfleft = point_in_aerosnap_region (x, y, reg);
+ halfleft = point_in_aerosnap_region (x, y, reg, impl->window_scale);
}
for (i = 0; i < context->halfright_regions->len && halfright == 0; i++)
{
reg = &g_array_index (context->halfright_regions, AeroSnapEdgeRegion, i);
- halfright = point_in_aerosnap_region (x, y, reg);
+ halfright = point_in_aerosnap_region (x, y, reg, impl->window_scale);
}
for (i = 0; i < context->fullup_regions->len && fullup == 0; i++)
{
reg = &g_array_index (context->fullup_regions, AeroSnapEdgeRegion, i);
- fullup = point_in_aerosnap_region (x, y, reg);
+ fullup = point_in_aerosnap_region (x, y, reg, impl->window_scale);
}
#if defined(MORE_AEROSNAP_DEBUGGING)
@@ -4442,8 +4503,8 @@ setup_drag_move_resize_context (GdkWindow *window,
*/
if (op == GDK_WIN32_DRAGOP_MOVE && !maximized)
{
- swx += impl->margins.left;
- swy += impl->margins.top;
+ swx += impl->margins.left / impl->window_scale;
+ swy += impl->margins.top / impl->window_scale;
swwidth -= impl->margins_x;
swheight -= impl->margins_y;
}
@@ -4489,47 +4550,52 @@ setup_drag_move_resize_context (GdkWindow *window,
GDK_NOTE (MISC, g_print ("W32 WM unmaximized window placement is %ld x %ld @ %ld : %ld\n",
placement.rcNormalPosition.right - placement.rcNormalPosition.left,
placement.rcNormalPosition.bottom - placement.rcNormalPosition.top,
- placement.rcNormalPosition.left + _gdk_offset_x,
- placement.rcNormalPosition.top + _gdk_offset_y));
+ placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
+ placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
unmax_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left;
unmax_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top;
- shadow_unmax_width = unmax_width - impl->margins_x;
- shadow_unmax_height = unmax_height - impl->margins_y;
+ shadow_unmax_width = unmax_width - impl->margins_x * impl->window_scale;
+ shadow_unmax_height = unmax_height - impl->margins_y * impl->window_scale;
- if (offsetx < (shadow_unmax_width / 2) && offsety < (shadow_unmax_height / 2))
+ if (offsetx * impl->window_scale < (shadow_unmax_width / 2) &&
+ offsety * impl->window_scale < (shadow_unmax_height / 2))
{
- placement.rcNormalPosition.top = root_y - (offsety + impl->margins.top) - _gdk_offset_y;
+ placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
if (left_half)
{
- placement.rcNormalPosition.left = root_x - (offsetx + impl->margins.left) - _gdk_offset_x;
+ placement.rcNormalPosition.left = (root_x - offsetx + impl->margins.left - _gdk_offset_x) * impl->window_scale;
placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
}
else
{
- placement.rcNormalPosition.right = root_x + (offsetx + impl->margins.right) - _gdk_offset_x;
+ placement.rcNormalPosition.right = (root_x + offsetx + impl->margins.right - _gdk_offset_x) * impl->window_scale;
placement.rcNormalPosition.left = placement.rcNormalPosition.right - unmax_width;
}
}
else
{
- placement.rcNormalPosition.left = root_x - unmax_width / 2 - _gdk_offset_x;
+ placement.rcNormalPosition.left = (root_x * impl->window_scale) -
+ (unmax_width / 2) -
+ (_gdk_offset_x * impl->window_scale);
- if (offsety < shadow_unmax_height / 2)
- placement.rcNormalPosition.top = root_y - (offsety + impl->margins.top) - _gdk_offset_y;
+ if (offsety * impl->window_scale < shadow_unmax_height / 2)
+ placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
else
- placement.rcNormalPosition.top = root_y - unmax_height / 2 - _gdk_offset_y;
+ placement.rcNormalPosition.top = (root_y * impl->window_scale) -
+ (unmax_height / 2) -
+ (_gdk_offset_y * impl->window_scale);
placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
}
GDK_NOTE (MISC, g_print ("Unmaximized window will be at %ld : %ld\n",
- placement.rcNormalPosition.left + _gdk_offset_x,
- placement.rcNormalPosition.top + _gdk_offset_y));
+ placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
+ placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
API_CALL (SetWindowPlacement, (GDK_WINDOW_HWND (window), &placement));
}
@@ -4550,12 +4616,12 @@ setup_drag_move_resize_context (GdkWindow *window,
if (offsetx < snew_pos.width / 2 && offsety < snew_pos.height / 2)
{
- new_pos.y = root_y - (offsety + impl->margins.top);
+ new_pos.y = root_y - offsety + impl->margins.top / impl->window_scale;
if (left_half)
- new_pos.x = root_x - (offsetx + impl->margins.left);
+ new_pos.x = root_x - offsetx + impl->margins.left / impl->window_scale;
else
- new_pos.x = root_x + (offsetx + impl->margins.left) - new_pos.width;
+ new_pos.x = root_x + offsetx + impl->margins.left / impl->window_scale - new_pos.width;
}
else
{
@@ -4716,12 +4782,13 @@ gdk_win32_window_do_move_resize_drag (GdkWindow *window,
return;
new_rect = context->start_rect;
- diffx = x - context->start_root_x;
- diffy = y - context->start_root_y;
+ diffx = (x - context->start_root_x) * impl->window_scale;
+ diffy = (y - context->start_root_y) * impl->window_scale;
switch (context->op)
{
case GDK_WIN32_DRAGOP_RESIZE:
+
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
@@ -4886,10 +4953,10 @@ gdk_win32_window_do_move_resize_drag (GdkWindow *window,
_gdk_win32_adjust_client_rect (window, &new_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
- new_rect.left -= _gdk_offset_x;
- new_rect.right -= _gdk_offset_x;
- new_rect.top -= _gdk_offset_y;
- new_rect.bottom -= _gdk_offset_y;
+ new_rect.left -= _gdk_offset_x * impl->window_scale;
+ new_rect.right -= _gdk_offset_x * impl->window_scale;
+ new_rect.top -= _gdk_offset_y * impl->window_scale;
+ new_rect.bottom -= _gdk_offset_y * impl->window_scale;
window_position.x = new_rect.left;
window_position.y = new_rect.top;
@@ -4968,6 +5035,7 @@ gdk_win32_window_begin_resize_drag (GdkWindow *window,
* will only work with button 1 (left), since Windows only allows window
* dragging using the left mouse button.
*/
+
if (button != 1)
return;
@@ -5038,7 +5106,7 @@ gdk_win32_window_iconify (GdkWindow *window)
if (GDK_WINDOW_IS_MAPPED (window))
{
old_active_window = GetActiveWindow ();
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
+ GtkShowWindow (window, SW_MINIMIZE);
if (old_active_window != GDK_WINDOW_HWND (window))
SetActiveWindow (old_active_window);
}
@@ -5099,6 +5167,7 @@ gdk_win32_window_unstick (GdkWindow *window)
static void
gdk_win32_window_maximize (GdkWindow *window)
{
+
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
@@ -5109,7 +5178,7 @@ gdk_win32_window_maximize (GdkWindow *window)
_gdk_win32_window_state_to_string (window->state)));
if (GDK_WINDOW_IS_MAPPED (window))
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
+ GtkShowWindow (window, SW_MAXIMIZE);
else
gdk_synthesize_window_state (window,
0,
@@ -5129,7 +5198,7 @@ gdk_win32_window_unmaximize (GdkWindow *window)
_gdk_win32_window_state_to_string (window->state)));
if (GDK_WINDOW_IS_MAPPED (window))
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
+ GtkShowWindow (window, SW_RESTORE);
else
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_MAXIMIZED,
@@ -5183,8 +5252,8 @@ gdk_win32_window_fullscreen (GdkWindow *window)
(fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
- x, y, width, height,
- SWP_NOCOPYBITS | SWP_SHOWWINDOW));
+ x, y, width, height,
+ SWP_NOCOPYBITS | SWP_SHOWWINDOW));
}
}
@@ -5281,13 +5350,13 @@ gdk_win32_window_focus (GdkWindow *window,
_gdk_win32_window_state_to_string (window->state)));
if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
+ GtkShowWindow (window, SW_SHOWMAXIMIZED);
else if (window->state & GDK_WINDOW_STATE_ICONIFIED)
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
+ GtkShowWindow (window, SW_RESTORE);
else if (!IsWindowVisible (GDK_WINDOW_HWND (window)))
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
+ GtkShowWindow (window, SW_SHOWNORMAL);
else
- GtkShowWindow (GDK_WINDOW_HWND (window), SW_SHOW);
+ GtkShowWindow (window, SW_SHOW);
SetFocus (GDK_WINDOW_HWND (window));
}
@@ -5428,7 +5497,8 @@ gdk_win32_window_get_type_hint (GdkWindow *window)
static HRGN
cairo_region_to_hrgn (const cairo_region_t *region,
gint x_origin,
- gint y_origin)
+ gint y_origin,
+ guint scale)
{
HRGN hrgn;
RGNDATA *rgndata;
@@ -5451,10 +5521,10 @@ cairo_region_to_hrgn (const cairo_region_t *region,
rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
cairo_region_get_rectangle (region, i, &r);
- rect->left = r.x + x_origin;
- rect->right = rect->left + r.width;
- rect->top = r.y + y_origin;
- rect->bottom = rect->top + r.height;
+ rect->left = (r.x + x_origin) * scale;
+ rect->right = (rect->left + r.width) * scale;
+ rect->top = (r.y + y_origin) * scale;
+ rect->bottom = (rect->top + r.height) * scale;
if (rect->left < rgndata->rdh.rcBound.left)
rgndata->rdh.rcBound.left = rect->left;
@@ -5479,6 +5549,8 @@ gdk_win32_window_shape_combine_region (GdkWindow *window,
gint offset_x,
gint offset_y)
{
+ GdkWindowImplWin32 *impl;
+
if (GDK_WINDOW_DESTROYED (window))
return;
@@ -5491,8 +5563,9 @@ gdk_win32_window_shape_combine_region (GdkWindow *window,
else
{
HRGN hrgn;
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
- hrgn = cairo_region_to_hrgn (shape_region, 0, 0);
+ hrgn = cairo_region_to_hrgn (shape_region, 0, 0, impl->window_scale);
GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: %p\n",
GDK_WINDOW_HWND (window),
@@ -5562,10 +5635,11 @@ gdk_win32_window_get_shape (GdkWindow *window)
{
HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
int type = GetWindowRgn (GDK_WINDOW_HWND (window), hrgn);
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (type == SIMPLEREGION || type == COMPLEXREGION)
{
- cairo_region_t *region = _gdk_win32_hrgn_to_region (hrgn);
+ cairo_region_t *region = _gdk_win32_hrgn_to_region (hrgn, impl->window_scale);
DeleteObject (hrgn);
return region;
@@ -5597,6 +5671,7 @@ gdk_win32_window_show_window_menu (GdkWindow *window,
{
double event_x, event_y;
gint x, y;
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
switch (event->type)
{
@@ -5613,7 +5688,10 @@ gdk_win32_window_show_window_menu (GdkWindow *window,
x = event_x - _gdk_offset_x;
y = event_y - _gdk_offset_y;
- SendMessage (GDK_WINDOW_HWND (window), WM_SYSMENU, 0, MAKELPARAM (x, y));
+ SendMessage (GDK_WINDOW_HWND (window),
+ WM_SYSMENU,
+ 0,
+ MAKELPARAM (x * impl->window_scale, y * impl->window_scale));
return TRUE;
}
@@ -5719,8 +5797,8 @@ gdk_win32_ref_cairo_surface_layered (GdkWindow *window,
gdk_window_get_position (window, &x, &y);
window_rect.left = x;
window_rect.top = y;
- window_rect.right = window_rect.left + gdk_window_get_width (window);
- window_rect.bottom = window_rect.top + gdk_window_get_height (window);
+ window_rect.right = window_rect.left + gdk_window_get_width (window) * impl->window_scale;
+ window_rect.bottom = window_rect.top + gdk_window_get_height (window) * impl->window_scale;
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (window, &window_rect);
@@ -5735,7 +5813,9 @@ gdk_win32_ref_cairo_surface_layered (GdkWindow *window,
cairo_t *cr;
/* Create larger cache surface, copy old cache surface over it */
- new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+ new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+ width,
+ height);
if (impl->cache_surface)
{
@@ -5751,6 +5831,10 @@ gdk_win32_ref_cairo_surface_layered (GdkWindow *window,
impl->cache_surface = new_cache;
+ cairo_surface_set_device_scale (impl->cache_surface,
+ impl->window_scale,
+ impl->window_scale);
+
if (impl->cairo_surface)
cairo_surface_destroy (impl->cairo_surface);
@@ -5763,10 +5847,16 @@ gdk_win32_ref_cairo_surface_layered (GdkWindow *window,
*/
if (!impl->cairo_surface)
{
- impl->cairo_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+ impl->cairo_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+ width,
+ height);
impl->dib_width = width;
impl->dib_height = height;
+ cairo_surface_set_device_scale (impl->cairo_surface,
+ impl->window_scale,
+ impl->window_scale);
+
cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
impl, gdk_win32_cairo_surface_destroy);
}
@@ -5797,6 +5887,9 @@ gdk_win32_ref_cairo_surface (GdkWindow *window)
return NULL;
impl->cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
+ cairo_surface_set_device_scale (impl->cairo_surface,
+ impl->window_scale,
+ impl->window_scale);
cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
impl, gdk_win32_cairo_surface_destroy);
@@ -5808,8 +5901,8 @@ gdk_win32_ref_cairo_surface (GdkWindow *window)
}
BOOL WINAPI
-GtkShowWindow (HWND hwnd,
- int cmd_show)
+GtkShowWindow (GdkWindow *window,
+ int cmd_show)
{
cairo_t *cr;
cairo_surface_t *surface;
@@ -5820,6 +5913,9 @@ GtkShowWindow (HWND hwnd,
POINT source_point;
BLENDFUNCTION blender;
+ HWND hwnd = GDK_WINDOW_HWND (window);
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
switch (cmd_show)
{
case SW_FORCEMINIMIZE:
@@ -5859,7 +5955,10 @@ GtkShowWindow (HWND hwnd,
blender.SourceConstantAlpha = 255;
/* Create a surface of appropriate size and clear it */
- surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, window_size.cx, window_size.cy);
+ surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+ window_size.cx,
+ window_size.cy);
+ cairo_surface_set_device_scale (surface, impl->window_scale, impl->window_scale);
cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
@@ -5904,13 +6003,77 @@ gdk_win32_window_set_shadow_width (GdkWindow *window,
return;
impl->margins.left = left;
- impl->margins.right = right;
+ impl->margins.right = right * impl->window_scale;
impl->margins.top = top;
- impl->margins.bottom = bottom;
+ impl->margins.bottom = bottom * impl->window_scale;
impl->margins_x = left + right;
impl->margins_y = top + bottom;
}
+
+gint
+_gdk_win32_window_get_scale_factor (GdkWindow *window)
+{
+ GdkDisplay *display;
+ GdkWindowImplWin32 *impl;
+
+ GdkWin32Display *win32_display;
+ UINT dpix, dpiy;
+ gboolean is_scale_acquired;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return 1;
+
+ g_return_val_if_fail (window != NULL, 1);
+
+ display = gdk_window_get_display (window);
+ impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+ win32_display = GDK_WIN32_DISPLAY (display);
+
+ if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
+ {
+ if (win32_display->has_fixed_scale)
+ impl->window_scale = win32_display->window_scale;
+ else
+ impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
+ NULL,
+ GDK_WINDOW_HWND (window),
+ NULL);
+
+ return impl->window_scale;
+ }
+ else
+ {
+ if (win32_display->has_fixed_scale)
+ {
+ static gsize hidpi_msg_displayed = 0;
+
+ if (g_once_init_enter (&hidpi_msg_displayed))
+ {
+ g_message ("Note: GDK_SCALE is ignored as HiDPI awareness is disabled.");
+ g_once_init_leave (&hidpi_msg_displayed, 1);
+ }
+ }
+
+ /* Application is not DPI aware, don't bother */
+ return 1;
+ }
+}
+
+void
+_gdk_win32_window_get_unscaled_size (GdkWindow *window,
+ gint *unscaled_width,
+ gint *unscaled_height)
+{
+ GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+ if (unscaled_width)
+ *unscaled_width = impl->unscaled_width;
+ if (unscaled_height)
+ *unscaled_height = impl->unscaled_height;
+}
+
static void
gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
{
@@ -6002,6 +6165,8 @@ gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
impl_class->delete_property = _gdk_win32_window_delete_property;
impl_class->create_gl_context = _gdk_win32_window_create_gl_context;
impl_class->invalidate_for_new_frame = _gdk_win32_window_invalidate_for_new_frame;
+ impl_class->get_scale_factor = _gdk_win32_window_get_scale_factor;
+ impl_class->get_unscaled_size = _gdk_win32_window_get_unscaled_size;
}
HGDIOBJ
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
index 508087beb9..de18c45141 100644
--- a/gdk/win32/gdkwindow-win32.h
+++ b/gdk/win32/gdkwindow-win32.h
@@ -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__ */