forked from AuroraMiddleware/gtk
Merge branch 'fix-dnd-coordinates-on-windows' into 'master'
Fix DND coordinates on Windows See merge request GNOME/gtk!3930
This commit is contained in:
commit
cf7ee82755
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user