Some questions regarding _gdk_window_impl_new() (csw, win32, patch)



while trying to fix _gdk_window_impl_new() for win32 some more,
quite some questions arose around that (apparently undocumented;)) API:

 - if the information given to _gdk_window_impl_new() is redundant,
   as with GDK_WA_VISUAL set and visual given by parameter, which one
   has precedence?
 - when turning a csw into a native window, shouldn't the new window
   position be calculated against the native parent? If so: should
   the caller do it and give GDK_WA_(X|Y)?
 - how to get back default OS/window-manager placment of toplevel
   windows? (The old implementation used to place toplevel windows
   with CW_USEDEFAULT, my new implementation is doing similar)
 - what's the (visual) depth of a GDK_INPUT_ONLY window?
   ( Dia(win32) with gtk>=2.18 is crashing on it's Navigation popup,
    which can be fixed by setting the visual depth to something
    reasonable, but it used to be 0 before csw. Maybe this is hiding
    a bug elsewhere, e.g. returning the wrong window when forced to
    be native? )

Another question is regarding "GDK_NATIVE_WINDOWS". With my current
patch at least the drawing seems to work reasonable again, but the
(ENTER|LEAVE)_NOTIFY handling is not, so the mouse pointer is almost
useless. Is it necessary to ressurect most of the original code (pre-csw)
to make it work again, or should there be an easier way?

Thanks,
	Hans

-------- Hans "at" Breuer "dot" Org -----------
Tell me what you need, and I'll tell you how to
get along without it.                -- Dilbert
D:\Devel\from-git\gtk-2-2x\gdk>d:\Devel\Git\bin\git diff win32 
diff --git a/gdk/win32/gdkgeometry-win32.c b/gdk/win32/gdkgeometry-win32.c
index 6cdb860..47fcc12 100644
--- a/gdk/win32/gdkgeometry-win32.c
+++ b/gdk/win32/gdkgeometry-win32.c
@@ -70,9 +70,14 @@ _gdk_window_move_resize_child (GdkWindow *window,
   obj = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
+#if 0 /* the values are already set by caller, so this calculation is flawed */
   is_move = (x - obj->x != 0) && (y - obj->y != 0);
   is_resize = obj->width != width && obj->height != height;
-  
+#else
+  is_move = TRUE;
+  is_resize = TRUE;
+#endif
+
   GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s %+d%+d %dx%d %+d%+d\n",
 			   _gdk_win32_drawable_description (window),
 			   obj->x, obj->y, width, height, x, y));
@@ -92,8 +97,8 @@ _gdk_window_move_resize_child (GdkWindow *window,
   obj->width = width;
   obj->height = height;
 
-  _gdk_win32_window_tmp_unset_parent_bg (window);
-  _gdk_win32_window_tmp_unset_bg (window, TRUE);
+  //_gdk_win32_window_tmp_unset_parent_bg (window);
+  //_gdk_win32_window_tmp_unset_bg (window, TRUE);
   
   GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
 			   "NOACTIVATE|NOZORDER%s%s)\n",
@@ -111,7 +116,7 @@ _gdk_window_move_resize_child (GdkWindow *window,
 			   (is_resize ? 0 : SWP_NOSIZE)));
 
   //_gdk_win32_window_tmp_reset_parent_bg (window);
-  _gdk_win32_window_tmp_reset_bg (window, TRUE);
+  //_gdk_win32_window_tmp_reset_bg (window, TRUE);
 }
 
 void
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 598d291..8711cdc 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -474,7 +474,6 @@ _gdk_window_impl_new (GdkWindow     *window,
   ATOM klass = 0;
   DWORD dwStyle = 0, dwExStyle;
   RECT rect;
-  GdkWindow *orig_parent;
   GdkWindowObject *private;
   GdkWindowImplWin32 *impl;
   GdkDrawableImplWin32 *draw_impl;
@@ -482,11 +481,10 @@ _gdk_window_impl_new (GdkWindow     *window,
   wchar_t *wtitle;
   gint window_width, window_height;
   gint offset_x = 0, offset_y = 0;
+  gint x, y;
 
   private = (GdkWindowObject *)window;
 
-  orig_parent = real_parent;
-
   GDK_NOTE (MISC,
 	    g_print ("_gdk_window_impl_new: %s\n",
 		     (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
@@ -502,19 +500,9 @@ _gdk_window_impl_new (GdkWindow     *window,
   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
 
-  // XXX: xattributes_mask = 0
-
-#if 0
   if (attributes_mask & GDK_WA_VISUAL)
     visual = attributes->visual;
-  else
-    visual = gdk_visual_get_system ();
-#endif
 
-#if 0
-  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
-  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-#endif
   impl->extension_events_selected = FALSE;
 
   // XXX ?
@@ -543,7 +531,7 @@ _gdk_window_impl_new (GdkWindow     *window,
        * to work well enough for the actual use cases in gtk.
        */
       dwExStyle = WS_EX_TRANSPARENT;
-      private->depth = 0;
+      private->depth = visual->depth; /* xxx: was 0 for years */
       private->input_only = TRUE;
       draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
       g_object_ref (draw_impl->colormap);
@@ -560,7 +548,7 @@ _gdk_window_impl_new (GdkWindow     *window,
 	  hparent = GetDesktopWindow ();
 	}
       /* Children of foreign windows aren't toplevel windows */
-      if (GDK_WINDOW_TYPE (orig_parent) == GDK_WINDOW_FOREIGN)
+      if (GDK_WINDOW_TYPE (real_parent) == GDK_WINDOW_FOREIGN)
 	{
 	  dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
 	}
@@ -601,13 +589,29 @@ _gdk_window_impl_new (GdkWindow     *window,
 
       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
 
+      /* non child windows are placed by the OS/window manager */
+      if (!private->x && !private->y && !offset_x && !offset_y)
+	x = y = CW_USEDEFAULT;
       window_width = rect.right - rect.left;
       window_height = rect.bottom - rect.top;
     }
   else
     {
+      /* adjust position relative to real_parent */
+      GdkWindowObject *parent = private->parent;
+
+      while (parent && !_gdk_window_has_impl (parent))
+	{
+	  offset_x -= parent->x;
+	  offset_y -= parent->y;
+	  parent = parent->parent;
+	}
+
       window_width = private->width;
       window_height = private->height;
+      /* use given position for initial placement */
+      x = private->x - offset_x;
+      y = private->y - offset_y;
     }
 
   if (attributes_mask & GDK_WA_TITLE)
@@ -620,9 +624,7 @@ _gdk_window_impl_new (GdkWindow     *window,
   private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
       
   if (attributes_mask & GDK_WA_TYPE_HINT)
-    impl->type_hint = attributes->type_hint;
-  else
-    impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
+    gdk_window_set_type_hint (window, attributes->type_hint);
 
   if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
     dwExStyle |= WS_EX_TOOLWINDOW;
@@ -638,9 +640,8 @@ _gdk_window_impl_new (GdkWindow     *window,
 			     MAKEINTRESOURCEW (klass),
 			     wtitle,
 			     dwStyle,
-			     ((attributes_mask & GDK_WA_X) ?
-			       private->x - offset_x : CW_USEDEFAULT),
-			     private->y - offset_y,
+			     x,
+			     y,
 			     window_width, window_height,
 			     hparent,
 			     NULL,
@@ -674,8 +675,7 @@ _gdk_window_impl_new (GdkWindow     *window,
   GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d %+d%+d %p = %p\n",
 			   title,
 			   window_width, window_height,
-			   ((attributes_mask & GDK_WA_X) ?
-			    private->x - offset_x: CW_USEDEFAULT),
+			   private->x - offset_x,
 			   private->y - offset_y, 
 			   hparent,
 			   GDK_WINDOW_HWND (window)));
@@ -857,7 +857,8 @@ gdk_window_destroy_notify (GdkWindow *window)
     }
   
   gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
-  g_object_unref (window);
+  // crash on GDK_NATIVE_WINDOWS:
+  // g_object_unref (window);
 }
 
 static void
@@ -1096,7 +1097,7 @@ static void
 gdk_win32_window_show (GdkWindow *window, 
 		       gboolean already_mapped)
 {
-  show_window_internal (window, FALSE, FALSE);
+  show_window_internal (window, already_mapped, FALSE);
 }
 
 static void
@@ -1423,6 +1424,202 @@ gdk_win32_window_reparent (GdkWindow *window,
 }
 
 static void
+erase_background (GdkWindow *window,
+		  HDC        hdc)
+{
+  HDC bgdc = NULL;
+  HBRUSH hbr = NULL;
+  HPALETTE holdpal = NULL;
+  RECT rect;
+  COLORREF bg;
+  GdkColormap *colormap;
+  GdkColormapPrivateWin32 *colormap_private;
+  int x, y;
+  int x_offset, y_offset;
+  
+  if (((GdkWindowObject *) window)->input_only ||
+      ((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG)
+    {
+      return;
+    }
+
+  colormap = gdk_drawable_get_colormap (window);
+
+  if (colormap &&
+      (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
+       colormap->visual->type == GDK_VISUAL_STATIC_COLOR))
+    {
+      int k;
+	  
+      colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
+
+      if (!(holdpal = SelectPalette (hdc,  colormap_private->hpal, FALSE)))
+        WIN32_GDI_FAILED ("SelectPalette");
+      else if ((k = RealizePalette (hdc)) == GDI_ERROR)
+	WIN32_GDI_FAILED ("RealizePalette");
+      else if (k > 0)
+	GDK_NOTE (COLORMAP, g_print ("erase_background: realized %p: %d colors\n",
+				     colormap_private->hpal, k));
+    }
+  
+  x_offset = y_offset = 0;
+  while (window && ((GdkWindowObject *) window)->bg_pixmap == GDK_PARENT_RELATIVE_BG)
+    {
+      /* If this window should have the same background as the parent,
+       * fetch the parent. (And if the same goes for the parent, fetch
+       * the grandparent, etc.)
+       */
+      x_offset += ((GdkWindowObject *) window)->x;
+      y_offset += ((GdkWindowObject *) window)->y;
+      window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
+    }
+  
+  GetClipBox (hdc, &rect);
+
+  if (((GdkWindowObject *) window)->bg_pixmap == NULL)
+    {
+      bg = _gdk_win32_colormap_color (GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->colormap,
+				      ((GdkWindowObject *) window)->bg_color.pixel);
+      
+      if (!(hbr = CreateSolidBrush (bg)))
+	WIN32_GDI_FAILED ("CreateSolidBrush");
+      else if (!FillRect (hdc, &rect, hbr))
+	WIN32_GDI_FAILED ("FillRect");
+      if (hbr != NULL)
+	DeleteObject (hbr);
+    }
+  else if (((GdkWindowObject *) window)->bg_pixmap != GDK_NO_BG)
+    {
+      GdkPixmap *pixmap = ((GdkWindowObject *) window)->bg_pixmap;
+      GdkPixmapImplWin32 *pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
+      
+      if (x_offset == 0 && y_offset == 0 &&
+	  pixmap_impl->width <= 8 && pixmap_impl->height <= 8)
+	{
+	  if (!(hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (pixmap))))
+	    WIN32_GDI_FAILED ("CreatePatternBrush");
+	  else if (!FillRect (hdc, &rect, hbr))
+	    WIN32_GDI_FAILED ("FillRect");
+	  if (hbr != NULL)
+	    DeleteObject (hbr);
+	}
+      else
+	{
+	  HGDIOBJ oldbitmap;
+
+	  if (!(bgdc = CreateCompatibleDC (hdc)))
+	    {
+	      WIN32_GDI_FAILED ("CreateCompatibleDC");
+	      return;
+	    }
+	  if (!(oldbitmap = SelectObject (bgdc, GDK_PIXMAP_HBITMAP (pixmap))))
+	    {
+	      WIN32_GDI_FAILED ("SelectObject");
+	      DeleteDC (bgdc);
+	      return;
+	    }
+	  x = -x_offset;
+	  while (x < rect.right)
+	    {
+	      if (x + pixmap_impl->width >= rect.left)
+		{
+		  y = -y_offset;
+		  while (y < rect.bottom)
+		    {
+		      if (y + pixmap_impl->height >= rect.top)
+			{
+			  if (!BitBlt (hdc, x, y,
+				       pixmap_impl->width, pixmap_impl->height,
+				       bgdc, 0, 0, SRCCOPY))
+			    {
+			      WIN32_GDI_FAILED ("BitBlt");
+			      SelectObject (bgdc, oldbitmap);
+			      DeleteDC (bgdc);
+			      return;
+			    }
+			}
+		      y += pixmap_impl->height;
+		    }
+		}
+	      x += pixmap_impl->width;
+	    }
+	  SelectObject (bgdc, oldbitmap);
+	  DeleteDC (bgdc);
+	}
+    }
+}
+
+static void
+gdk_win32_window_clear_area (GdkWindow *window,
+			     gint       x,
+			     gint       y,
+			     gint       width,
+			     gint       height,
+			     gboolean   send_expose)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      HDC hdc;
+      RECT rect;
+
+      hdc = GetDC (GDK_WINDOW_HWND (window));
+
+      if (!send_expose)
+	{
+	  if (width == 0)
+	    width = private->width - x;
+	  if (height == 0)
+	    height = private->height - y;
+	  GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: %p: "
+				   "%dx%d %+d%+d\n",
+				   GDK_WINDOW_HWND (window),
+				   width, height, x, y));
+	  IntersectClipRect (hdc, x, y, x + width, y + height);
+	  erase_background (window, hdc);
+	  GDI_CALL (ReleaseDC, (GDK_WINDOW_HWND (window), hdc));
+	}
+      else
+	{
+	  /* The background should be erased before the expose event is
+	     generated */
+	  IntersectClipRect (hdc, x, y, x + width, y + height);
+	  erase_background (window, hdc);
+	  GDI_CALL (ReleaseDC, (GDK_WINDOW_HWND (window), hdc));
+
+	  rect.left = x;
+	  rect.right = x + width;
+	  rect.top = y;
+	  rect.bottom = y + height;
+
+	  GDI_CALL (InvalidateRect, (GDK_WINDOW_HWND (window), &rect, TRUE));
+	  UpdateWindow (GDK_WINDOW_HWND (window));
+	}
+    }
+}
+
+static void
+gdk_window_win32_clear_region (GdkWindow *window,
+			     GdkRegion *region,
+			     gboolean   send_expose)
+{
+  GdkRectangle *rectangles;
+  int n_rectangles, i;
+
+  gdk_region_get_rectangles  (region,
+			      &rectangles,
+			      &n_rectangles);
+
+  for (i = 0; i < n_rectangles; i++)
+    gdk_win32_window_clear_area (window,
+		rectangles[i].x, rectangles[i].y,
+		rectangles[i].width, rectangles[i].height,
+		send_expose);
+
+  g_free (rectangles);
+}
+static void
 gdk_win32_window_raise (GdkWindow *window)
 {
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1865,13 +2062,46 @@ gdk_win32_window_set_background (GdkWindow      *window,
 			   _gdk_win32_color_to_string (color)));
 
   private->bg_color = *color;
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    {
+      g_object_unref (private->bg_pixmap);
+      private->bg_pixmap = NULL;
+    }
 }
 
 static void
 gdk_win32_window_set_back_pixmap (GdkWindow *window,
 				  GdkPixmap *pixmap)
 {
-  /* TODO_CSW? but win32 has no XSetWindowBackgroundPixmap */
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (pixmap != GDK_PARENT_RELATIVE_BG &&
+      pixmap != GDK_NO_BG &&
+      pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+  
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  if (pixmap != GDK_PARENT_RELATIVE_BG &&
+      pixmap != GDK_NO_BG &&
+      pixmap)
+    {
+      g_object_ref (pixmap);
+      private->bg_pixmap = pixmap;
+    }
+  else
+    {
+      private->bg_pixmap = pixmap;
+    }
 }
 
 static void
@@ -2086,7 +2316,21 @@ static void
 gdk_win32_window_restack_under (GdkWindow *window,
 				GList *native_siblings)
 {
-	// ### TODO
+  GList *list;
+
+  /* input order is bottom-most first */
+  for (list = native_siblings;;)
+    {
+      HWND lower = list->data, upper;
+
+      list = list->next;
+      if (!list)
+	break;
+      upper = list->data;
+      API_CALL (SetWindowPos, (upper, lower, 0, 0, 0, 0, 
+		  SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW));
+    }
+
 }
 
 static void
@@ -2094,7 +2338,11 @@ gdk_win32_window_restack_toplevel (GdkWindow *window,
 				   GdkWindow *sibling,
 				   gboolean   above)
 {
-	// ### TODO
+  HWND lower = above ? GDK_WINDOW_HWND (sibling) : GDK_WINDOW_HWND (window);
+  HWND upper = above ? GDK_WINDOW_HWND (window) : GDK_WINDOW_HWND (sibling);
+
+  API_CALL (SetWindowPos, (upper, lower, 0, 0, 0, 0, 
+	      SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW));
 }
 
 void
@@ -2352,6 +2600,38 @@ do_shape_combine_region (GdkWindow *window,
   SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
 }
 
+static void
+gdk_win32_window_shape_combine_mask (GdkWindow *window,
+				     GdkBitmap *mask,
+				     gint x, gint y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (!mask)
+    {
+      GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: none\n",
+			       GDK_WINDOW_HWND (window)));
+      SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
+
+      private->shaped = FALSE;
+    }
+  else
+    {
+      HRGN hrgn;
+
+      GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: %p\n",
+			       GDK_WINDOW_HWND (window),
+			       GDK_WINDOW_HWND (mask)));
+
+      /* Convert mask bitmap to region */
+      hrgn = _gdk_win32_bitmap_to_hrgn (mask);
+
+      do_shape_combine_region (window, hrgn, x, y);
+
+      private->shaped = TRUE;
+    }
+}
+
 void
 gdk_window_set_override_redirect (GdkWindow *window,
 				  gboolean   override_redirect)
@@ -3531,17 +3811,20 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->set_background = gdk_win32_window_set_background;
   iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
   iface->reparent = gdk_win32_window_reparent;
+  iface->clear_region = gdk_window_win32_clear_region;
   iface->set_cursor = gdk_win32_window_set_cursor;
   iface->get_geometry = gdk_win32_window_get_geometry;
-  iface->get_pointer = gdk_window_win32_get_pointer;
   iface->get_root_coords = gdk_win32_window_get_root_coords;
+  iface->get_pointer = gdk_window_win32_get_pointer;
+  iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin;
   iface->shape_combine_region = gdk_win32_window_shape_combine_region;
   iface->input_shape_combine_region = gdk_win32_input_shape_combine_region;
-  iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin;
   iface->set_static_gravities = gdk_win32_window_set_static_gravities;
   iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
   iface->queue_translation = _gdk_win32_window_queue_translation;
   iface->destroy = _gdk_win32_window_destroy;
   iface->input_window_destroy = _gdk_input_window_destroy;
   iface->input_window_crossing = _gdk_input_crossing_event;
+  /* CHECK: we may not need set_pixmap anymore if setting FALSE */
+  iface->supports_native_bg = TRUE;
 }
diff --git a/gdk/win32/makefile.msc b/gdk/win32/makefile.msc
index 5a4fa41..7a88284 100644
--- a/gdk/win32/makefile.msc
+++ b/gdk/win32/makefile.msc
@@ -21,7 +21,8 @@ DEFINES = \
 	-DGDK_COMPILATION -DG_LOG_DOMAIN=\"Gdk\"
 
 INCLUDES = -FImsvc_recommended_pragmas.h \
-	-I. -I.. -I..\.. $(GLIB_CFLAGS) $(PANGO_CFLAGS) $(CAIRO_CFLAGS) \
+	-I. -I.. -I..\.. $(GLIB_CFLAGS) $(GDK_PIXBUF_CFLAGS) \
+	$(PANGO_CFLAGS) $(CAIRO_CFLAGS) \
 	-I$(WTKIT)\include -I$(GLIB) \
 
 all: \


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]