diff --git a/gdk/win32/gdkdrag-win32.c b/gdk/win32/gdkdrag-win32.c index f1c56c9558..22d0d936ea 100644 --- a/gdk/win32/gdkdrag-win32.c +++ b/gdk/win32/gdkdrag-win32.c @@ -2082,8 +2082,8 @@ gdk_dnd_handle_motion_event (GdkDrag *drag, API_CALL (PostThreadMessage, (clipdrop->dnd_thread_id, WM_MOUSEMOVE, key_state, - MAKELPARAM (x * drag_win32->scale, - y * drag_win32->scale))); + MAKELPARAM (x_root * drag_win32->scale - _gdk_offset_x, + y_root * drag_win32->scale - _gdk_offset_y))); return TRUE; } diff --git a/gdk/win32/gdkdrop-win32.c b/gdk/win32/gdkdrop-win32.c index 4bfc2dc372..63ab3a420e 100644 --- a/gdk/win32/gdkdrop-win32.c +++ b/gdk/win32/gdkdrop-win32.c @@ -425,6 +425,31 @@ set_source_actions_helper (GdkDrop *drop, return actions; } +/* Utility function to translate win32 screen coordinates to + * client coordinates (i.e. relative to the surface origin) + * + * Note that input is expected to be: + * a) NOT scaled by dpi_scale + * b) NOT translated by the GDK screen offset (gdk_offset_x / y) + * + * This utility function preserves subpixel precision + */ +static void +unscaled_screen_to_client (GdkSurface* surface, + double screen_x, + double screen_y, + double *client_x, + double *client_y) +{ + POINT client_origin; + + client_origin.x = 0; + client_origin.y = 0; + ClientToScreen (GDK_SURFACE_HWND (surface), &client_origin); + *client_x = screen_x - client_origin.x; + *client_y = screen_y - client_origin.y; +} + /* The pdwEffect here initially points * to a DWORD that contains the value of dwOKEffects argument in DoDragDrop, * i.e. the drag action that the drag source deems acceptable. @@ -445,6 +470,8 @@ idroptarget_dragenter (LPDROPTARGET This, GdkDisplay *display; int pt_x; int pt_y; + double x = 0.0; + double y = 0.0; GdkDrag *drag; GdkDragAction source_actions; GdkDragAction dest_actions; @@ -489,7 +516,12 @@ idroptarget_dragenter (LPDROPTARGET This, set_data_object (&ctx->data_object, pDataObj); pt_x = pt.x / drop_win32->scale + _gdk_offset_x; pt_y = pt.y / drop_win32->scale + _gdk_offset_y; - gdk_drop_emit_enter_event (drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME); + + unscaled_screen_to_client (ctx->surface, pt.x, pt.y, &x, &y); + x /= drop_win32->scale; + y /= drop_win32->scale; + + gdk_drop_emit_enter_event (drop, TRUE, x, y, GDK_CURRENT_TIME); drop_win32->last_key_state = grfKeyState; drop_win32->last_x = pt_x; drop_win32->last_y = pt_y; @@ -544,7 +576,14 @@ idroptarget_dragover (LPDROPTARGET This, pt_y != drop_win32->last_y || grfKeyState != drop_win32->last_key_state) { - gdk_drop_emit_motion_event (ctx->drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME); + double x = 0.0; + double y = 0.0; + + unscaled_screen_to_client (ctx->surface, pt.x, pt.y, &x, &y); + x /= drop_win32->scale; + y /= drop_win32->scale; + + gdk_drop_emit_motion_event (ctx->drop, TRUE, x, y, GDK_CURRENT_TIME); drop_win32->last_key_state = grfKeyState; drop_win32->last_x = pt_x; drop_win32->last_y = pt_y; @@ -587,6 +626,8 @@ idroptarget_drop (LPDROPTARGET This, GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (ctx->drop); int pt_x = pt.x / drop_win32->scale + _gdk_offset_x; int pt_y = pt.y / drop_win32->scale + _gdk_offset_y; + double x = 0.0; + double y = 0.0; GdkDragAction dest_action; GDK_NOTE (DND, g_print ("idroptarget_drop %p ", This)); @@ -606,7 +647,12 @@ idroptarget_drop (LPDROPTARGET This, grfKeyState); drop_win32->drop_finished = FALSE; - gdk_drop_emit_drop_event (ctx->drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME); + + unscaled_screen_to_client (ctx->surface, pt.x, pt.y, &x, &y); + x /= drop_win32->scale; + y /= drop_win32->scale; + + gdk_drop_emit_drop_event (ctx->drop, TRUE, x, y, GDK_CURRENT_TIME); while (!drop_win32->drop_finished) g_main_context_iteration (NULL, FALSE); diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index c26ac5e9f3..2095402725 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -584,12 +584,6 @@ _gdk_win32_display_create_surface (GdkDisplay *display, if (!title || !*title) title = ""; - /* WS_EX_TRANSPARENT means "try draw this window last, and ignore input". - * It's the last part we're after. We don't want DND indicator to accept - * input, because that will make it a potential drop target, and if it's - * under the mouse cursor, this will kill any DND. - */ - klass = RegisterGdkClass (surface_type); wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL); @@ -652,6 +646,7 @@ _gdk_win32_display_create_surface (GdkDisplay *display, _gdk_win32_surface_enable_transparency (surface); _gdk_win32_surface_register_dnd (surface); + _gdk_win32_surface_update_style_bits (surface); g_signal_connect (frame_clock, "after-paint", @@ -1838,6 +1833,8 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window) RECT rect, before, after; gboolean was_topmost; gboolean will_be_topmost; + gboolean was_layered; + gboolean will_be_layered; HWND insert_after; UINT flags; @@ -1852,7 +1849,9 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window) AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle); was_topmost = (old_exstyle & WS_EX_TOPMOST) ? TRUE : FALSE; + was_layered = (old_exstyle & WS_EX_LAYERED) ? TRUE : FALSE; will_be_topmost = was_topmost; + will_be_layered = was_layered; old_exstyle &= ~WS_EX_TOPMOST; @@ -1862,7 +1861,14 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window) if (GDK_IS_DRAG_SURFACE (window)) { new_exstyle |= WS_EX_TOOLWINDOW; + + /* WS_EX_LAYERED | WS_EX_TRANSPARENT makes the drag surface behave + * in pointer input passthrough mode, so it doesn't interfere with + * the drag and drop operation. + */ + new_exstyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT; will_be_topmost = TRUE; + will_be_layered = TRUE; } else { @@ -1907,6 +1913,14 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window) _gdk_win32_surface_exstyle_to_string (new_exstyle))); SetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE, new_exstyle); + + if (!was_layered && will_be_layered) + { + /* We have to call SetLayeredWindowAttributes when setting the + * WS_EX_LAYERED style anew, otherwise the window won't show up + */ + API_CALL (SetLayeredWindowAttributes, (GDK_SURFACE_HWND (window), 0, 255, LWA_ALPHA)); + } } AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);