Index: docs/reference/gdk/gdk-sections.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gdk/gdk-sections.txt,v
retrieving revision 1.41
diff -u -r1.41 gdk-sections.txt
--- docs/reference/gdk/gdk-sections.txt	16 Dec 2003 00:56:45 -0000	1.41
+++ docs/reference/gdk/gdk-sections.txt	17 Feb 2004 23:34:26 -0000
@@ -665,6 +665,7 @@
 gdk_window_set_user_data
 gdk_window_set_override_redirect
 gdk_window_set_accept_focus
+gdk_window_set_focus_on_map
 gdk_window_add_filter
 gdk_window_remove_filter
 GdkFilterFunc
Index: docs/reference/gtk/gtk-sections.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/gtk-sections.txt,v
retrieving revision 1.118
diff -u -r1.118 gtk-sections.txt
--- docs/reference/gtk/gtk-sections.txt	14 Feb 2004 02:06:36 -0000	1.118
+++ docs/reference/gtk/gtk-sections.txt	17 Feb 2004 23:34:26 -0000
@@ -4403,6 +4403,7 @@
 gtk_window_set_skip_taskbar_hint
 gtk_window_set_skip_pager_hint
 gtk_window_set_accept_focus
+gtk_window_set_focus_on_map
 gtk_window_get_decorated
 gtk_window_get_default_icon_list
 gtk_window_get_default_size
@@ -4422,6 +4423,7 @@
 gtk_window_get_skip_taskbar_hint
 gtk_window_get_skip_pager_hint
 gtk_window_get_accept_focus
+gtk_window_get_focus_on_map
 gtk_window_move
 gtk_window_parse_geometry
 gtk_window_reshow_with_initial_size
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.49
diff -u -r1.49 gdkwindow.h
--- gdk/gdkwindow.h	26 Jan 2004 20:20:42 -0000	1.49
+++ gdk/gdkwindow.h	17 Feb 2004 23:34:26 -0000
@@ -262,6 +262,7 @@
   guint destroyed : 2;
 
   guint accept_focus : 1;
+  guint focus_on_map : 1;
   
   GdkEventMask event_mask;
 };
@@ -321,6 +322,8 @@
                                                 gboolean       override_redirect);
 void          gdk_window_set_accept_focus      (GdkWindow     *window,
 					        gboolean       accept_focus);
+void          gdk_window_set_focus_on_map      (GdkWindow     *window,
+					        gboolean       focus_on_map);
 void          gdk_window_add_filter            (GdkWindow     *window,
                                                 GdkFilterFunc  function,
                                                 gpointer       data);
Index: gdk/linux-fb/gdkwindow-fb.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/linux-fb/gdkwindow-fb.c,v
retrieving revision 1.55
diff -u -r1.55 gdkwindow-fb.c
--- gdk/linux-fb/gdkwindow-fb.c	26 Jan 2004 20:20:43 -0000	1.55
+++ gdk/linux-fb/gdkwindow-fb.c	17 Feb 2004 23:34:27 -0000
@@ -189,6 +189,7 @@
   private->parent = parent_private;
 
   private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
 
   if (attributes_mask & GDK_WA_X)
     x = attributes->x;
@@ -2008,6 +2009,22 @@
     private->accept_focus = accept_focus;
 }
 
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+			     gboolean focus_on_map)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  focus_on_map = focus_on_map != FALSE;
+
+  if (private->focus_on_map != focus_on_map)
+    private->focus_on_map = focus_on_map;
+}
+
 void          
 gdk_window_set_icon (GdkWindow *window, 
 		     GdkWindow *icon_window,
Index: gdk/win32/gdkwindow-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkwindow-win32.c,v
retrieving revision 1.111
diff -u -r1.111 gdkwindow-win32.c
--- gdk/win32/gdkwindow-win32.c	26 Jan 2004 20:20:46 -0000	1.111
+++ gdk/win32/gdkwindow-win32.c	17 Feb 2004 23:34:27 -0000
@@ -507,6 +507,7 @@
   private->parent = (GdkWindowObject *)parent;
 
   private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
 
   if (attributes_mask & GDK_WA_X)
     private->x = attributes->x;
@@ -2207,6 +2208,22 @@
     private->accept_focus = accept_focus;
 }
 
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+			     gboolean focus_on_map)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  focus_on_map = focus_on_map != FALSE;
+
+  if (private->focus_on_map != focus_on_map)
+    private->focus_on_map = focus_on_map;
+}
+
 static HICON
 pixbuf_to_hicon_alpha_winxp (GdkWindow *window,
 			     GdkPixbuf *pixbuf)
Index: gdk/x11/gdkdisplay-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.c,v
retrieving revision 1.40
diff -u -r1.40 gdkdisplay-x11.c
--- gdk/x11/gdkdisplay-x11.c	2 Feb 2004 18:18:18 -0000	1.40
+++ gdk/x11/gdkdisplay-x11.c	17 Feb 2004 23:34:27 -0000
@@ -81,6 +81,7 @@
   "_NET_WM_STATE_FULLSCREEN",
   "_NET_WM_WINDOW_TYPE",
   "_NET_WM_WINDOW_TYPE_NORMAL",
+  "_NET_WM_USER_TIME",
 };
 
 GType
@@ -217,6 +218,14 @@
 		   display_x11->leader_window,
 		   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
 		   XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
+
+  XEvent event;
+  XWindowEvent (display_x11->xdisplay,
+                display_x11->leader_window,
+                PropertyChangeMask,
+                &event);
+
+  display_x11->user_time = event.xproperty.time;
   
 #ifdef HAVE_XKB
   {
Index: gdk/x11/gdkdisplay-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.h,v
retrieving revision 1.15
diff -u -r1.15 gdkdisplay-x11.h
--- gdk/x11/gdkdisplay-x11.h	2 Feb 2004 18:18:18 -0000	1.15
+++ gdk/x11/gdkdisplay-x11.h	17 Feb 2004 23:34:27 -0000
@@ -138,6 +138,9 @@
   /* Startup notification */
   gchar *startup_notification_id;
 
+  /* Time of most recent user interaction. */
+  gulong user_time;
+
   /* Sets of atoms for DND */
   guint base_dnd_atoms_precached : 1;
   guint xdnd_atoms_precached : 1;
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.123
diff -u -r1.123 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	10 Feb 2004 18:51:14 -0000	1.123
+++ gdk/x11/gdkevents-x11.c	17 Feb 2004 23:34:27 -0000
@@ -24,6 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <assert.h>
 #include "gdk.h"
 #include "gdkprivate-x11.h"
 #include "gdkinternals.h"
@@ -805,6 +806,19 @@
 };
 #endif
 
+void
+set_user_time (GdkWindow* window, GdkEvent *event)
+{
+  g_return_if_fail (event != NULL);
+
+  window = gdk_window_get_toplevel (event->client.window);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  assert (gdk_event_get_time (event) != GDK_CURRENT_TIME);
+  gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                gdk_event_get_time (event));
+}
+
 static gboolean
 gdk_event_translate (GdkDisplay *display,
 		     GdkEvent   *event,
@@ -998,6 +1012,7 @@
           break;
         }
       translate_key_event (display, event, xevent);
+      set_user_time (window, event);
       break;
 
     case KeyRelease:
@@ -1096,6 +1111,7 @@
           break;
 	}
 
+      set_user_time (window, event);
       break;
       
     case ButtonRelease:
Index: gdk/x11/gdkinput-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkinput-x11.c,v
retrieving revision 1.32
diff -u -r1.32 gdkinput-x11.c
--- gdk/x11/gdkinput-x11.c	31 Dec 2003 22:00:21 -0000	1.32
+++ gdk/x11/gdkinput-x11.c	17 Feb 2004 23:34:27 -0000
@@ -24,6 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <assert.h>
 #include "gdkinputprivate.h"
 #include "gdkinternals.h"
 #include "gdkx.h"
@@ -583,6 +584,9 @@
 		 event->button.x, event->button.y,
 		 xdbe->button));
 
+      assert (gdk_event_get_time (event) != GDK_CURRENT_TIME);
+      gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
+                                    gdk_event_get_time (event));
       return TRUE;
   }
 
@@ -643,6 +647,9 @@
 		 event->key.keyval,
 		 event->key.state));
 
+      assert (gdk_event_get_time (event) != GDK_CURRENT_TIME);
+      gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
+                                    gdk_event_get_time (event));
       return TRUE;
     }
 
@@ -673,6 +680,9 @@
 		 (xdme->is_hint) ? "true" : "false"));
       
       
+      assert (gdk_event_get_time (event) != GDK_CURRENT_TIME);
+      gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
+                                    gdk_event_get_time (event));
       return TRUE;
     }
 
@@ -687,6 +697,9 @@
       event->proximity.window = input_window->window;
       event->proximity.time = xpne->time;
       
+      assert (gdk_event_get_time (event) != GDK_CURRENT_TIME);
+      gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
+                                    gdk_event_get_time (event));
       return TRUE;
   }
 
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.201
diff -u -r1.201 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	2 Feb 2004 18:18:15 -0000	1.201
+++ gdk/x11/gdkwindow-x11.c	17 Feb 2004 23:34:28 -0000
@@ -454,6 +454,11 @@
 		   gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
 		   XA_WINDOW, 32, PropModeReplace,
 		   (guchar *) &GDK_DISPLAY_X11 (screen_x11->display)->leader_window, 1);
+
+  if (!obj->focus_on_map)
+    gdk_x11_window_set_user_time(window, 0);
+  else
+    gdk_x11_window_set_user_time(window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
 }
 
 /**
@@ -537,6 +542,7 @@
   private->parent = (GdkWindowObject *)parent;
 
   private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
 
   xattributes_mask = 0;
   
@@ -3295,6 +3301,86 @@
     }
 }
 
+/**
+ * gdk_window_set_focus_on_map:
+ * @window: a toplevel #GdkWindow
+ * @focus_on_map: %TRUE if the window should receive input focus when mapped
+ *
+ * Setting @focus_on_map to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus when it is mapped.  
+ * focus_on_map should be turned off for windows that aren't triggered
+ * interactively (such as popups from network activity).
+ *
+ * On X, it is the responsibility of the window manager to interpret
+ * this hint. Window managers following the freedesktop.org window
+ * manager extension specification should respect it.
+ *
+ * Since: 2.4 
+ **/
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+			     gboolean focus_on_map)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  focus_on_map = focus_on_map != FALSE;
+
+  if (private->focus_on_map != focus_on_map)
+    {
+      private->focus_on_map = focus_on_map;
+
+      if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+	gdk_x11_window_set_user_time (window, 0);
+    }
+}
+
+/**
+ * gdk_x11_window_set_user_time:
+ * @window: A toplevel #GdkWindow
+ * @timestamp: An XServer timestamp to which the property should be set
+ *
+ * The application can use this call to update the _NET_WM_USER_TIME
+ * property on a toplevel window.  This property stores an Xserver
+ * time which represents the time of the last user input event
+ * received for this window.  This property may be used by the window
+ * manager to alter the focus, stacking, and/or placement behavior of
+ * windows when they are mapped depending on whether the new window
+ * was created by a user action or is a "pop-up" window activated by a
+ * timer or some other event.
+ *
+ * Note that this property is automatically updated by GDK, so this
+ * function should only be used by applications which handle input
+ * events bypassing GDK.
+ *
+ * Since: 2.4
+ **/
+void             gdk_x11_window_set_user_time (GdkWindow *window,
+                                               guint32    timestamp)
+{
+  GdkDisplay *display;
+  GdkDisplayX11 *display_x11;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  display = gdk_drawable_get_display (window);
+  display_x11 = GDK_DISPLAY_X11 (display);
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
+                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (guchar *)&timestamp, 1);
+
+  if (timestamp != GDK_CURRENT_TIME)
+    display_x11->user_time = timestamp;
+}
 
 /**
  * gdk_window_set_icon_list:
Index: gdk/x11/gdkwindow-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.h,v
retrieving revision 1.10
diff -u -r1.10 gdkwindow-x11.h
--- gdk/x11/gdkwindow-x11.h	21 Dec 2003 16:37:43 -0000	1.10
+++ gdk/x11/gdkwindow-x11.h	17 Feb 2004 23:34:28 -0000
@@ -124,6 +124,8 @@
 GType gdk_window_impl_x11_get_type (void);
 
 GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window);
+void             gdk_x11_window_set_user_time (GdkWindow *window,
+                                               guint32    timestamp);
 
 G_END_DECLS
 
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.258
diff -u -r1.258 gtkwindow.c
--- gtk/gtkwindow.c	13 Feb 2004 03:03:21 -0000	1.258
+++ gtk/gtkwindow.c	17 Feb 2004 23:34:28 -0000
@@ -74,6 +74,7 @@
   PROP_SKIP_TASKBAR_HINT,
   PROP_SKIP_PAGER_HINT,
   PROP_ACCEPT_FOCUS,
+  PROP_FOCUS_ON_MAP,
   PROP_DECORATED,
   PROP_GRAVITY,
   
@@ -161,6 +162,7 @@
   guint skips_taskbar : 1;
   guint skips_pager : 1;
   guint accept_focus : 1;
+  guint focus_on_map : 1;
 };
 
 static void gtk_window_class_init         (GtkWindowClass    *klass);
@@ -601,6 +603,21 @@
                                                          G_PARAM_READWRITE));  
 
   /**
+   * GtkWindow:focus-on-map-hint:
+   *
+   * Whether the window should receive the input focus when mapped.
+   *
+   * Since: 2.4
+   */
+  g_object_class_install_property (gobject_class,
+				   PROP_FOCUS_ON_MAP,
+				   g_param_spec_boolean ("focus_on_map",
+                                                         P_("Focus on map"),
+                                                         P_("TRUE if the window should receive the input focus when mapped."),
+                                                         TRUE,
+                                                         G_PARAM_READWRITE));  
+
+  /**
    * GtkWindow:decorated:
    *
    * Whether the window should be decorated by the window manager.
@@ -763,6 +780,7 @@
   window->screen = gdk_screen_get_default ();
 
   priv->accept_focus = TRUE;
+  priv->focus_on_map = TRUE;
 
   colormap = _gtk_widget_peek_colormap ();
   if (colormap)
@@ -858,6 +876,10 @@
       gtk_window_set_accept_focus (window,
 				   g_value_get_boolean (value));
       break;
+    case PROP_FOCUS_ON_MAP:
+      gtk_window_set_focus_on_map (window,
+				   g_value_get_boolean (value));
+      break;
     case PROP_DECORATED:
       gtk_window_set_decorated (window, g_value_get_boolean (value));
       break;
@@ -951,6 +973,10 @@
       g_value_set_boolean (value,
                            gtk_window_get_accept_focus (window));
       break;
+    case PROP_FOCUS_ON_MAP:
+      g_value_set_boolean (value,
+                           gtk_window_get_focus_on_map (window));
+      break;
     case PROP_DECORATED:
       g_value_set_boolean (value, gtk_window_get_decorated (window));
       break;
@@ -2157,6 +2183,62 @@
 }
 
 /**
+ * gtk_window_set_focus_on_map:
+ * @window: a #GtkWindow 
+ * @setting: %TRUE to let this window receive input focus on map
+ * 
+ * Windows may set a hint asking the desktop environment not to receive
+ * the input focus when the window is mapped.  This function sets this
+ * hint.
+ * 
+ * Since: 2.4
+ **/
+void
+gtk_window_set_focus_on_map (GtkWindow *window,
+			     gboolean   setting)
+{
+  GtkWindowPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  setting = setting != FALSE;
+
+  if (priv->focus_on_map != setting)
+    {
+      priv->focus_on_map = setting;
+      if (GTK_WIDGET_REALIZED (window))
+        gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
+				     priv->focus_on_map);
+      g_object_notify (G_OBJECT (window), "focus_on_map");
+    }
+}
+
+/**
+ * gtk_window_get_focus_on_map:
+ * @window: a #GtkWindow
+ * 
+ * Gets the value set by gtk_window_set_focus_on_map().
+ * 
+ * Return value: %TRUE if window should receive the input focus when
+ * mapped.
+ * 
+ * Since: 2.4
+ **/
+gboolean
+gtk_window_get_focus_on_map (GtkWindow *window)
+{
+  GtkWindowPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+  
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  return priv->focus_on_map;
+}
+
+/**
  * gtk_window_set_destroy_with_parent:
  * @window: a #GtkWindow
  * @setting: whether to destroy @window with its transient parent
@@ -3924,6 +4006,11 @@
     gdk_window_set_accept_focus (widget->window, TRUE);
   else
     gdk_window_set_accept_focus (widget->window, FALSE);
+
+  if (gtk_window_get_focus_on_map (window))
+    gdk_window_set_focus_on_map (widget->window, TRUE);
+  else
+    gdk_window_set_focus_on_map (widget->window, FALSE);
   
   if (window->modal)
     gdk_window_set_modal_hint (widget->window, TRUE);
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.73
diff -u -r1.73 gtkwindow.h
--- gtk/gtkwindow.h	10 Dec 2003 23:45:55 -0000	1.73
+++ gtk/gtkwindow.h	17 Feb 2004 23:34:28 -0000
@@ -204,6 +204,9 @@
 void       gtk_window_set_accept_focus         (GtkWindow           *window,
                                                 gboolean             setting);
 gboolean   gtk_window_get_accept_focus         (GtkWindow           *window);
+void       gtk_window_set_focus_on_map         (GtkWindow           *window,
+                                                gboolean             setting);
+gboolean   gtk_window_get_focus_on_map         (GtkWindow           *window);
 void       gtk_window_set_destroy_with_parent  (GtkWindow           *window,
                                                 gboolean             setting);
 gboolean   gtk_window_get_destroy_with_parent  (GtkWindow           *window);
