Merge branch 'gtk3-dnd-find-dest-window-fix' into 'gtk-3-24'
GdkWin32: Fix DND destination window search See merge request GNOME/gtk!3885
This commit is contained in:
		@ -2204,43 +2204,6 @@ _gdk_win32_window_get_drag_protocol (GdkWindow *window,
 | 
			
		||||
  return protocol;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  gint x;
 | 
			
		||||
  gint y;
 | 
			
		||||
  HWND ignore;
 | 
			
		||||
  HWND result;
 | 
			
		||||
} find_window_enum_arg;
 | 
			
		||||
 | 
			
		||||
static BOOL CALLBACK
 | 
			
		||||
find_window_enum_proc (HWND   hwnd,
 | 
			
		||||
                       LPARAM lparam)
 | 
			
		||||
{
 | 
			
		||||
  RECT rect;
 | 
			
		||||
  POINT tl, br;
 | 
			
		||||
  find_window_enum_arg *a = (find_window_enum_arg *) lparam;
 | 
			
		||||
 | 
			
		||||
  if (hwnd == a->ignore)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  if (!IsWindowVisible (hwnd))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  tl.x = tl.y = 0;
 | 
			
		||||
  ClientToScreen (hwnd, &tl);
 | 
			
		||||
  GetClientRect (hwnd, &rect);
 | 
			
		||||
  br.x = rect.right;
 | 
			
		||||
  br.y = rect.bottom;
 | 
			
		||||
  ClientToScreen (hwnd, &br);
 | 
			
		||||
 | 
			
		||||
  if (a->x >= tl.x && a->y >= tl.y && a->x < br.x && a->y < br.y)
 | 
			
		||||
    {
 | 
			
		||||
      a->result = hwnd;
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkWindow *
 | 
			
		||||
gdk_win32_drag_context_find_window (GdkDragContext  *context,
 | 
			
		||||
				    GdkWindow       *drag_window,
 | 
			
		||||
@ -2250,51 +2213,47 @@ gdk_win32_drag_context_find_window (GdkDragContext  *context,
 | 
			
		||||
				    GdkDragProtocol *protocol)
 | 
			
		||||
{
 | 
			
		||||
  GdkWin32DragContext *context_win32 = GDK_WIN32_DRAG_CONTEXT (context);
 | 
			
		||||
  GdkWindow *dest_window, *dw;
 | 
			
		||||
  find_window_enum_arg a;
 | 
			
		||||
  GdkWindow *toplevel = NULL;
 | 
			
		||||
  HWND hwnd = NULL;
 | 
			
		||||
  POINT pt;
 | 
			
		||||
 | 
			
		||||
  a.x = x_root * context_win32->scale - _gdk_offset_x;
 | 
			
		||||
  a.y = y_root * context_win32->scale - _gdk_offset_y;
 | 
			
		||||
  a.ignore = drag_window ? GDK_WINDOW_HWND (drag_window) : NULL;
 | 
			
		||||
  a.result = NULL;
 | 
			
		||||
  pt.x = x_root * context_win32->scale - _gdk_offset_x;
 | 
			
		||||
  pt.y = y_root * context_win32->scale - _gdk_offset_y;
 | 
			
		||||
 | 
			
		||||
  GDK_NOTE (DND,
 | 
			
		||||
	    g_print ("gdk_drag_find_window_real: %p %+d%+d\n",
 | 
			
		||||
		     (drag_window ? GDK_WINDOW_HWND (drag_window) : NULL),
 | 
			
		||||
		     a.x, a.y));
 | 
			
		||||
            g_print ("gdk_drag_find_window_real: %+d%+d\n",
 | 
			
		||||
            (int) pt.x, (int) pt.y));
 | 
			
		||||
 | 
			
		||||
  EnumWindows (find_window_enum_proc, (LPARAM) &a);
 | 
			
		||||
  hwnd = WindowFromPoint (pt);
 | 
			
		||||
 | 
			
		||||
  if (a.result == NULL)
 | 
			
		||||
    dest_window = NULL;
 | 
			
		||||
  else
 | 
			
		||||
  if (hwnd)
 | 
			
		||||
    {
 | 
			
		||||
      dw = gdk_win32_handle_table_lookup (a.result);
 | 
			
		||||
      if (dw)
 | 
			
		||||
      GdkWindow *window = gdk_win32_handle_table_lookup (hwnd);
 | 
			
		||||
 | 
			
		||||
      if (window)
 | 
			
		||||
        {
 | 
			
		||||
          dest_window = gdk_window_get_toplevel (dw);
 | 
			
		||||
          g_object_ref (dest_window);
 | 
			
		||||
          toplevel = gdk_window_get_toplevel (window);
 | 
			
		||||
          g_object_ref (toplevel);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        dest_window = gdk_win32_window_foreign_new_for_display (gdk_screen_get_display (screen), a.result);
 | 
			
		||||
 | 
			
		||||
      if (use_ole2_dnd)
 | 
			
		||||
        *protocol = GDK_DRAG_PROTO_OLE2;
 | 
			
		||||
      else if (context->source_window)
 | 
			
		||||
        *protocol = GDK_DRAG_PROTO_LOCAL;
 | 
			
		||||
      else
 | 
			
		||||
        *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
 | 
			
		||||
        toplevel = gdk_win32_window_foreign_new_for_display (gdk_screen_get_display (screen), hwnd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  GDK_NOTE (DND,
 | 
			
		||||
	    g_print ("gdk_drag_find_window: %p %+d%+d: %p: %p %s\n",
 | 
			
		||||
		     (drag_window ? GDK_WINDOW_HWND (drag_window) : NULL),
 | 
			
		||||
		     x_root, y_root,
 | 
			
		||||
		     a.result,
 | 
			
		||||
		     (dest_window ? GDK_WINDOW_HWND (dest_window) : NULL),
 | 
			
		||||
		     _gdk_win32_drag_protocol_to_string (*protocol)));
 | 
			
		||||
  if (use_ole2_dnd)
 | 
			
		||||
    *protocol = GDK_DRAG_PROTO_OLE2;
 | 
			
		||||
  else if (context->source_window)
 | 
			
		||||
    *protocol = GDK_DRAG_PROTO_LOCAL;
 | 
			
		||||
  else
 | 
			
		||||
    *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
 | 
			
		||||
 | 
			
		||||
  return dest_window;
 | 
			
		||||
  GDK_NOTE (DND,
 | 
			
		||||
            g_print ("gdk_drag_find_window: %+d%+d: %p: %p %s\n",
 | 
			
		||||
                     x_root, y_root,
 | 
			
		||||
                     hwnd,
 | 
			
		||||
                     (toplevel ? GDK_WINDOW_HWND (toplevel) : NULL),
 | 
			
		||||
                     _gdk_win32_drag_protocol_to_string (*protocol)));
 | 
			
		||||
 | 
			
		||||
  return toplevel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 | 
			
		||||
@ -885,13 +885,13 @@ _gdk_win32_display_create_window_impl (GdkDisplay    *display,
 | 
			
		||||
  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
 | 
			
		||||
    dwExStyle |= WS_EX_TOOLWINDOW;
 | 
			
		||||
 | 
			
		||||
  /* 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.
 | 
			
		||||
  /* WS_EX_LAYERED | WS_EX_TRANSPARENT makes the window transparent w.r.t.
 | 
			
		||||
   * pointer input: the system will direct all pointer input to the window
 | 
			
		||||
   * below. We don't want a DND indicator to accept pointer input, because
 | 
			
		||||
   * that will make it a potential drop target.
 | 
			
		||||
   */
 | 
			
		||||
  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DND)
 | 
			
		||||
    dwExStyle |= WS_EX_TRANSPARENT;
 | 
			
		||||
    dwExStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
 | 
			
		||||
 | 
			
		||||
  klass = RegisterGdkClass (window->window_type, impl->type_hint);
 | 
			
		||||
 | 
			
		||||
@ -1277,10 +1277,10 @@ show_window_internal (GdkWindow *window,
 | 
			
		||||
 | 
			
		||||
  exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
 | 
			
		||||
 | 
			
		||||
  /* Use SetWindowPos to show transparent windows so automatic redraws
 | 
			
		||||
   * in other windows can be suppressed.
 | 
			
		||||
  /* If we have to show an input-only window,
 | 
			
		||||
   * redraws can be safely skipped.
 | 
			
		||||
   */
 | 
			
		||||
  if (exstyle & WS_EX_TRANSPARENT)
 | 
			
		||||
  if (window->input_only)
 | 
			
		||||
    {
 | 
			
		||||
      UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
 | 
			
		||||
 | 
			
		||||
@ -1416,7 +1416,6 @@ show_window_internal (GdkWindow *window,
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
 | 
			
		||||
    {
 | 
			
		||||
      gdk_window_fullscreen (window);
 | 
			
		||||
@ -1489,10 +1488,10 @@ gdk_win32_window_hide (GdkWindow *window)
 | 
			
		||||
  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
 | 
			
		||||
    ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
 | 
			
		||||
 | 
			
		||||
  /* Use SetWindowPos to hide transparent windows so automatic redraws
 | 
			
		||||
   * in other windows can be suppressed.
 | 
			
		||||
  /* If we have to hide an input-only window,
 | 
			
		||||
   * readraws can be safely skipped.
 | 
			
		||||
   */
 | 
			
		||||
  if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
 | 
			
		||||
  if (window->input_only)
 | 
			
		||||
    {
 | 
			
		||||
      SetWindowPos (GDK_WINDOW_HWND (window), SWP_NOZORDER_SPECIFIED,
 | 
			
		||||
		    0, 0, 0, 0,
 | 
			
		||||
@ -2787,6 +2786,7 @@ _gdk_win32_window_update_style_bits (GdkWindow *window)
 | 
			
		||||
  GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)window->impl;
 | 
			
		||||
  GdkWMDecoration decorations;
 | 
			
		||||
  LONG old_style, new_style, old_exstyle, new_exstyle;
 | 
			
		||||
  gboolean needs_basic_layering = FALSE;
 | 
			
		||||
  gboolean all;
 | 
			
		||||
  RECT rect, before, after;
 | 
			
		||||
  gboolean was_topmost;
 | 
			
		||||
@ -2842,7 +2842,18 @@ _gdk_win32_window_update_style_bits (GdkWindow *window)
 | 
			
		||||
  else
 | 
			
		||||
    impl->layered = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (impl->layered)
 | 
			
		||||
  /* DND windows need to have the WS_EX_TRANSPARENT | WS_EX_LAYERED styles
 | 
			
		||||
   * set so to behave in input passthrough mode. That's essential for DND
 | 
			
		||||
   * indicators.
 | 
			
		||||
   */
 | 
			
		||||
  if (!impl->layered &&
 | 
			
		||||
      GDK_WINDOW_HWND (window) != NULL &&
 | 
			
		||||
      impl->type_hint == GDK_WINDOW_TYPE_HINT_DND)
 | 
			
		||||
    {
 | 
			
		||||
      needs_basic_layering = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (impl->layered || needs_basic_layering)
 | 
			
		||||
    new_exstyle |= WS_EX_LAYERED;
 | 
			
		||||
  else
 | 
			
		||||
    new_exstyle &= ~WS_EX_LAYERED;
 | 
			
		||||
@ -2859,6 +2870,19 @@ _gdk_win32_window_update_style_bits (GdkWindow *window)
 | 
			
		||||
      update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (needs_basic_layering)
 | 
			
		||||
    {
 | 
			
		||||
      /* SetLayeredWindowAttributes may have been already called, e.g. to set an opacity level.
 | 
			
		||||
       * We only have to call the API in case it has never been called before on the window.
 | 
			
		||||
       */
 | 
			
		||||
      if (SetLastError(0),
 | 
			
		||||
          !GetLayeredWindowAttributes (GDK_WINDOW_HWND (window), NULL, NULL, NULL) &&
 | 
			
		||||
          GetLastError() == 0)
 | 
			
		||||
        {
 | 
			
		||||
          API_CALL (SetLayeredWindowAttributes, (GDK_WINDOW_HWND (window), 0, 255, LWA_ALPHA));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (old_style == new_style && old_exstyle == new_exstyle )
 | 
			
		||||
    {
 | 
			
		||||
      GDK_NOTE (MISC, g_print ("_gdk_win32_window_update_style_bits: %p: no change\n",
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user