Index: gdkevents-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkevents-win32.c,v
retrieving revision 1.137
diff -u -6 -p -r1.137 gdkevents-win32.c
--- gdkevents-win32.c	3 Sep 2004 01:27:57 -0000	1.137
+++ gdkevents-win32.c	18 Sep 2004 17:16:46 -0000
@@ -100,21 +100,25 @@ static GdkFilterReturn
 static gboolean  gdk_event_translate	(GdkDisplay *display,
 					 MSG	    *msg,
 					 gint       *ret_valp);
 static void      handle_wm_paint        (MSG        *msg,
 					 GdkWindow  *window,
 					 gboolean    return_exposes,
-					 GdkEvent  **event);
+					 GdkEvent  **event,
+					 gboolean erase_back);
 
 static gboolean gdk_event_prepare  (GSource     *source,
 				    gint        *timeout);
 static gboolean gdk_event_check    (GSource     *source);
 static gboolean gdk_event_dispatch (GSource     *source,
 				    GSourceFunc  callback,
 				    gpointer     user_data);
 
+static void append_event (GdkDisplay *display,
+			  GdkEvent   *event);
+
 /* Private variable declarations
  */
 
 static GdkWindow *p_grab_window = NULL; /* Window that currently holds
 					 * the pointer grab
 					 */
@@ -227,12 +231,25 @@ _gdk_win32_get_next_tick (gulong suggest
   if (suggested_tick <= cur_tick)
     return ++cur_tick;
   else
     return cur_tick = suggested_tick;
 }
 
+static void
+generate_focus_event (GdkWindow *window,
+		      gboolean   in)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (GDK_FOCUS_CHANGE);
+  event->focus_change.window = window;
+  event->focus_change.in = in;
+
+  append_event (gdk_drawable_get_display (window), event);
+}
+
 static LRESULT 
 inner_window_procedure (HWND   hwnd,
 			UINT   message,
 			WPARAM wparam,
 			LPARAM lparam)
 {
@@ -459,13 +476,13 @@ gdk_event_get_graphics_expose (GdkWindow
   g_return_val_if_fail (window != NULL, NULL);
   
   GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose\n"));
 
   if (PeekMessage (&msg, GDK_WINDOW_HWND (window), WM_PAINT, WM_PAINT, PM_REMOVE))
     {
-      handle_wm_paint (&msg, window, TRUE, &event);
+      handle_wm_paint (&msg, window, TRUE, &event, FALSE);
       if (event != NULL)
 	{
 	  GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose: got it!\n"));
 	  return event;
 	}
     }
@@ -516,12 +533,13 @@ gdk_pointer_grab (GdkWindow    *window,
 		  GdkEventMask	event_mask,
 		  GdkWindow    *confine_to,
 		  GdkCursor    *cursor,
 		  guint32	time)
 {
   HCURSOR hcursor;
+  GdkEvent *cross_grab_event;
   GdkCursorPrivate *cursor_private;
   gint return_val = GDK_GRAB_SUCCESS;
 
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
@@ -597,33 +615,47 @@ gdk_pointer_grab (GdkWindow    *window,
 	  rect.bottom = y + height;
 	  API_CALL (ClipCursor, (&rect));
 	  p_grab_confine_to = confine_to;
 	}
 
       /* FIXME: Generate GDK_CROSSING_GRAB events */
+	cross_grab_event = gdk_event_new( GDK_ENTER_NOTIFY );
+	cross_grab_event->crossing.window = p_grab_window;
+	cross_grab_event->crossing.time = time;
+	cross_grab_event->crossing.subwindow = confine_to;
+	cross_grab_event->crossing.focus = TRUE;
+	append_event( gdk_display_get_default(), cross_grab_event );
+	//gdk_event_put( cross_grab_event );
     }
   
   return return_val;
 }
 
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
                             guint32     time)
 {
+  GdkEvent *cross_grab_event;
   g_return_if_fail (display == gdk_display_get_default ());
 
   GDK_NOTE (EVENTS, g_print ("%sgdk_display_pointer_ungrab%s",
 			     (debug_indent > 0 ? "\n" : ""),
 			     (debug_indent == 0 ? "\n" : "")));
 
   _gdk_input_ungrab_pointer (time);
 
   if (GetCapture () != NULL)
     ReleaseCapture ();
 
   /* FIXME: Generate GDK_CROSSING_UNGRAB events */
+  cross_grab_event = gdk_event_new( GDK_LEAVE_NOTIFY );
+  cross_grab_event->crossing.window = p_grab_window;
+  cross_grab_event->crossing.time = time;
+  cross_grab_event->crossing.focus = FALSE;
+  append_event( display, cross_grab_event );
+  //gdk_event_put( cross_grab_event );
 
   p_grab_window = NULL;
   if (p_grab_cursor != NULL)
     {
       if (GetCursor () == p_grab_cursor)
 	SetCursor (NULL);
@@ -713,12 +745,14 @@ gdk_pointer_grab_info_libgtk_only (GdkDi
 
 GdkGrabStatus
 gdk_keyboard_grab (GdkWindow *window,
 		   gboolean   owner_events,
 		   guint32    time)
 {
+  GdkWindow *real_focus_window, *grab_focus_window;
+
   gint return_val;
   
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   
   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p\n",
@@ -730,25 +764,78 @@ gdk_keyboard_grab (GdkWindow *window,
       return_val = GDK_GRAB_SUCCESS;
     }
   else
     return_val = GDK_GRAB_ALREADY_GRABBED;
 
   if (return_val == GDK_GRAB_SUCCESS)
-    k_grab_window = window;
+    {
+      k_grab_window = window;
+
+      if (!k_grab_owner_events)
+	{
+	  real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
+	  if (real_focus_window)
+	    real_focus_window = gdk_window_get_toplevel (real_focus_window);
+	  grab_focus_window = gdk_window_get_toplevel (k_grab_window);
+	  if (real_focus_window != grab_focus_window)
+	    {
+	      /* Generate events for focus change from the window that really
+	       * has focus to the grabber.
+	       */
+	      if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
+		  && (((GdkWindowObject *) real_focus_window)->event_mask
+		      & GDK_FOCUS_CHANGE_MASK))
+		generate_focus_event (real_focus_window, FALSE);
+
+	      if (((GdkWindowObject *) grab_focus_window)->event_mask 
+		  & GDK_FOCUS_CHANGE_MASK)
+		generate_focus_event (grab_focus_window, TRUE);
+	    }
+	}
+    }
   
   return return_val;
 }
 
 void
 gdk_display_keyboard_ungrab (GdkDisplay *display,
                              guint32 time)
 {
+  GdkWindow *real_focus_window, *grab_focus_window;
+
   g_return_if_fail (display == gdk_display_get_default ());
 
   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
 
+  if (k_grab_window && !k_grab_owner_events)
+    {
+      real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
+      if (real_focus_window)
+	real_focus_window = gdk_window_get_toplevel (real_focus_window);
+      if (!GDK_WINDOW_DESTROYED (k_grab_window))
+	grab_focus_window = gdk_window_get_toplevel (k_grab_window);
+      else
+	grab_focus_window = NULL;
+      if (real_focus_window != grab_focus_window)
+	{
+	  /* Generate events for focus change from grabber to the window that
+	   * really has focus. Important for example if a new window is created
+	   * while focus is grabbed.
+	   */
+	  if (grab_focus_window
+	      && (((GdkWindowObject *) grab_focus_window)->event_mask
+		  & GDK_FOCUS_CHANGE_MASK))
+	    generate_focus_event (grab_focus_window, FALSE);
+
+	  if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
+	      && (((GdkWindowObject *) real_focus_window)->event_mask
+		  & GDK_FOCUS_CHANGE_MASK))
+	    generate_focus_event (real_focus_window, TRUE);
+	}
+    }
+
   k_grab_window = NULL;
 }
 
 gboolean
 gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
 				    GdkWindow **grab_window,
@@ -1747,34 +1834,33 @@ handle_configure_event (MSG       *msg,
       event->configure.x = point.x;
       event->configure.y = point.y;
 
       append_event (gdk_drawable_get_display (window), event);
     }
 }
-
 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 ||
       GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.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))
     {
@@ -1799,12 +1885,13 @@ erase_background (GdkWindow *window,
        * the grandparent, etc.)
        */
       x_offset += ((GdkWindowObject *) window)->x;
       y_offset += ((GdkWindowObject *) window)->y;
       window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
     }
+
   
   if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
     {
       /* Improves scolling effect, e.g. main buttons of testgtk */
       return;
     }
@@ -1879,12 +1966,13 @@ erase_background (GdkWindow *window,
 	      x += pixmap_impl->width;
 	    }
 	  SelectObject (bgdc, oldbitmap);
 	  DeleteDC (bgdc);
 	}
     }
+
 }
 
 static GdkRegion *
 _gdk_win32_hrgn_to_region (HRGN hrgn)
 {
   RGNDATA *rgndata;
@@ -1939,13 +2027,14 @@ adjust_drag (LONG *drag,
 }
 
 static void
 handle_wm_paint (MSG        *msg,
 		 GdkWindow  *window,
 		 gboolean    return_exposes,
-		 GdkEvent  **event)
+		 GdkEvent  **event,
+		 gboolean erasebk)
 {
   HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
   HDC hdc;
   PAINTSTRUCT paintstruct;
   GdkRegion *update_region;
   gint xoffset, yoffset;
@@ -1955,12 +2044,30 @@ handle_wm_paint (MSG        *msg,
       WIN32_GDI_FAILED ("GetUpdateRgn");
       return;
     }
 
   hdc = BeginPaint (msg->hwnd, &paintstruct);
 
+  if (erasebk) {
+    /*HDC hdcMem;
+    HBITMAP hbmMem;
+    HANDLE hOld;
+		int width = paintstruct.rcPaint.right - paintstruct.rcPaint.left;
+		int height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
+    hdcMem = CreateCompatibleDC (hdc);
+    hbmMem = CreateCompatibleBitmap (hdc, width, height);
+    hOld   = SelectObject (hdcMem, hbmMem);
+    erase_background (window, hdcMem);
+    BitBlt (hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
+
+    SelectObject (hdcMem, hOld);
+    DeleteObject (hbmMem);
+    DeleteDC     (hdcMem);*/
+		//erase_background (window, hdc);
+  }
+
   GDK_NOTE (EVENTS, g_print (" %s %s dc %p%s",
 			     _gdk_win32_rect_to_string (&paintstruct.rcPaint),
 			     (paintstruct.fErase ? "erase" : ""),
 			     hdc,
 			     (return_exposes ? " return_exposes" : "")));
 
@@ -2079,12 +2186,13 @@ gdk_event_translate (GdkDisplay *display
   HCURSOR hcursor;
   CHARSETINFO charset_info;
   BYTE key_state[256];
   HIMC himc;
 
   GdkEvent *event;
+	gboolean clear_background;
 
   wchar_t wbuf[100];
   gint ccount;
 
   GdkWindow *window = NULL;
   GdkWindowImplWin32 *impl;
@@ -2092,13 +2200,13 @@ gdk_event_translate (GdkDisplay *display
   GdkWindow *orig_window, *new_window;
   gint xoffset, yoffset;
 
   static gint update_colors_counter = 0;
   gint button;
 
-  gchar buf[256];
+//  gchar buf[256];
   gboolean return_val = FALSE;
 
   int i;
 
   if (_gdk_default_filters)
     {
@@ -2280,12 +2388,14 @@ gdk_event_translate (GdkDisplay *display
 		}
 	    }
 	  tmp_list = tmp_list->next;
 	}
     }
 
+  clear_background = FALSE;
+
   switch (msg->message)
     {
     case WM_INPUTLANGCHANGE:
       _gdk_input_locale = (HKL) msg->lParam;
       _gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
       TranslateCharsetInfo ((DWORD FAR *) msg->wParam,
@@ -2828,13 +2938,13 @@ gdk_event_translate (GdkDisplay *display
 	   return_val = TRUE;
 	 }
        break;
 
     case WM_SETFOCUS:
     case WM_KILLFOCUS:
-      if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_FOCUS_CHANGE_MASK))
+      if (k_grab_window != NULL && !k_grab_owner_events)
 	break;
 
       if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK))
 	break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2852,19 +2962,20 @@ gdk_event_translate (GdkDisplay *display
     case WM_ERASEBKGND:
       GDK_NOTE (EVENTS, g_print (" %p", (HANDLE) msg->wParam));
       
       if (GDK_WINDOW_DESTROYED (window))
 	break;
 
-      erase_background (window, (HDC) msg->wParam);
+      //erase_background (window, (HDC) msg->wParam);
+			clear_background = TRUE;
       return_val = TRUE;
-      *ret_valp = 1;
-      break;
+      *ret_valp = 0;
+      //break;
 
     case WM_PAINT:
-      handle_wm_paint (msg, window, FALSE, NULL);
+      handle_wm_paint (msg, window, FALSE, NULL, clear_background);
       break;
 
     case WM_SETCURSOR:
       GDK_NOTE (EVENTS, g_print (" %#x %#x",
 				 LOWORD (msg->lParam), HIWORD (msg->lParam)));
 
