GdkWin32: Make OLE2 DND work in monitors with different OS scales

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3734
This commit is contained in:
Luca Bacci
2021-11-13 19:38:11 +01:00
parent a174568ef9
commit 4d40300d8a
2 changed files with 28 additions and 0 deletions

View File

@ -774,6 +774,7 @@ send_change_events (GdkDragContext *context,
GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
POINT pt;
POINT pt_client;
HMONITOR monitor = NULL;
gboolean changed = FALSE;
HWND hwnd = GDK_WINDOW_HWND (context->source_window);
LPARAM lparam;
@ -784,6 +785,24 @@ send_change_events (GdkDragContext *context,
if (!API_CALL (GetCursorPos, (&pt)))
return FALSE;
/* Move the DND IPC window to the monitor the cursor is currently on.
This esures that OLE2 DND works correctly even if the DPI awareness
isn't per-monitor.
*/
monitor = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
if (monitor != context_win32->last_monitor)
{
MONITORINFO mi;
mi.cbSize = sizeof(mi);
if (GetMonitorInfoW (monitor, &mi))
{
MoveWindow (hwnd, mi.rcWork.left, mi.rcWork.top, 1, 1, FALSE);
}
context_win32->last_monitor = monitor;
}
pt_client = pt;
if (!API_CALL (ScreenToClient, (hwnd, &pt_client)))

View File

@ -55,6 +55,15 @@ struct _GdkWin32DragContext
gint start_x; /* Coordinates of the drag start, in GDK space */
gint start_y;
DWORD last_key_state; /* Key state from last event */
HMONITOR last_monitor; /* While dragging we keep track of the monitor the cursor
is currently on. As the cursor moves between monitors,
we move the invisible dnd ipc window to the top-left
corner of the current monitor, because OLE2 does not
work correctly if the source window and the dest window
are on monitors with different scales (say one is 125%
and the other 100%) and the drag-initiating application
(effectively driving the DND) is not per-monitor DPI aware
*/
/* Just like context->targets, but an array, and with format IDs
* stored inside.