Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.4701
diff -u -p -r1.4701 ChangeLog
--- ChangeLog	10 Dec 2003 20:49:40 -0000	1.4701
+++ ChangeLog	10 Dec 2003 23:43:05 -0000
@@ -1,3 +1,33 @@
+Thu Dec 11 00:35:12 2003  Matthias Clasen  <maclas@gmx.de>
+
+	Changes to allow "no input" windows (#64613):
+	
+	* gdk/gdkwindow.h (struct _GdkWindowObject): Add a new boolean
+	field accept_focus.
+	
+	* gdk/gdkwindow.h (gdk_window_set_accept_focus): New function to
+	set it.
+
+	* gtk/gtkwindow.[hc]: Add a boolean property "accept_focus"
+	and gtk_window_get_focus() and gtk_window_set_focus().
+
+	* gdk/win32/gdkwindow-win32.c (gdk_window_new): 
+	* gdk/linux-fb/gdkwindow-fb.c (gdk_window_new): 
+	* gdk/x11/gdkwindow-x11.c (gdk_window_set_new):
+	Initialize the accept_focus field to TRUE.
+
+	* gdk/win32/gdkwindow-win32.c (gdk_window_set_accept_focus): 
+	* gdk/linux-fb/gdkwindow-fb.c (gdk_window_set_accept_focus): 
+	* gdk/x11/gdkwindow-x11.c (gdk_window_set_accept_focus): 
+	Implementations for the various backends. The Win32 and linux-fb
+	implementations set the accept_focus field, but don't use it yet 
+	to actually implement noinput windows. The X implementation updates
+	the WM_HINTS to select the globally active input model (see the
+	ICCCM) if accept_focus is FALSE.
+
+	* gdk/x11/gdkevents-x11.c (gdk_wm_protocols_filter): Ignore the
+	WM_TAKE_FOCUS message if accept_focus is FALSE.
+	
 2003-12-10  Federico Mena Quintero  <federico@ximian.com>
 
 	* gtk/gtkfilechooserdefault.c (struct _GtkFileChooserDefault):
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.255
diff -u -p -r1.255 gtkwindow.c
--- gtk/gtkwindow.c	7 Nov 2003 21:57:20 -0000	1.255
+++ gtk/gtkwindow.c	10 Dec 2003 23:43:07 -0000
@@ -73,6 +73,7 @@ enum {
   PROP_TYPE_HINT,
   PROP_SKIP_TASKBAR_HINT,
   PROP_SKIP_PAGER_HINT,
+  PROP_ACCEPT_FOCUS,
   PROP_DECORATED,
   PROP_GRAVITY,
   
@@ -159,6 +160,7 @@ struct _GtkWindowPrivate
   guint fullscreen_initially : 1;
   guint skips_taskbar : 1;
   guint skips_pager : 1;
+  guint accept_focus : 1;
 };
 
 static void gtk_window_class_init         (GtkWindowClass    *klass);
@@ -584,6 +586,21 @@ gtk_window_class_init (GtkWindowClass *k
                                                          G_PARAM_READWRITE));  
 
   /**
+   * GtkWindow:accept-focus-hint:
+   *
+   * Whether the window should receive the input focus.
+   *
+   * Since: 2.4
+   */
+  g_object_class_install_property (gobject_class,
+				   PROP_ACCEPT_FOCUS,
+				   g_param_spec_boolean ("accept_focus",
+                                                         _("Accept focus"),
+                                                         _("TRUE if the window should receive the input focus."),
+                                                         TRUE,
+                                                         G_PARAM_READWRITE));  
+
+  /**
    * GtkWindow:decorated:
    *
    * Whether the window should be decorated by the window manager.
@@ -708,6 +725,7 @@ static void
 gtk_window_init (GtkWindow *window)
 {
   GdkColormap *colormap;
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
   
   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
@@ -743,7 +761,9 @@ gtk_window_init (GtkWindow *window)
   window->decorated = TRUE;
   window->mnemonic_modifier = GDK_MOD1_MASK;
   window->screen = gdk_screen_get_default ();
-  
+
+  priv->accept_focus = TRUE;
+
   colormap = _gtk_widget_peek_colormap ();
   if (colormap)
     gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
@@ -834,6 +854,10 @@ gtk_window_set_property (GObject      *o
       gtk_window_set_skip_pager_hint (window,
                                       g_value_get_boolean (value));
       break;
+    case PROP_ACCEPT_FOCUS:
+      gtk_window_set_accept_focus (window,
+				   g_value_get_boolean (value));
+      break;
     case PROP_DECORATED:
       gtk_window_set_decorated (window, g_value_get_boolean (value));
       break;
@@ -923,6 +947,10 @@ gtk_window_get_property (GObject      *o
       g_value_set_boolean (value,
                            gtk_window_get_skip_pager_hint (window));
       break;
+    case PROP_ACCEPT_FOCUS:
+      g_value_set_boolean (value,
+                           gtk_window_get_accept_focus (window));
+      break;
     case PROP_DECORATED:
       g_value_set_boolean (value, gtk_window_get_decorated (window));
       break;
@@ -1969,7 +1997,7 @@ gtk_window_get_type_hint (GtkWindow *win
  * @setting: %TRUE to keep this window from appearing in the task bar
  * 
  * Windows may set a hint asking the desktop environment not to display
- * the window in the task bar. This function toggles this hint.
+ * the window in the task bar. This function sets this hint.
  * 
  * Since: 2.2
  **/
@@ -2023,7 +2051,7 @@ gtk_window_get_skip_taskbar_hint (GtkWin
  * @setting: %TRUE to keep this window from appearing in the pager
  * 
  * Windows may set a hint asking the desktop environment not to display
- * the window in the pager. This function toggles this hint.
+ * the window in the pager. This function sets this hint.
  * (A "pager" is any desktop navigation tool such as a workspace
  * switcher that displays a thumbnail representation of the windows
  * on the screen.)
@@ -2075,6 +2103,60 @@ gtk_window_get_skip_pager_hint (GtkWindo
 }
 
 /**
+ * gtk_window_set_accept_focus:
+ * @window: a #GtkWindow 
+ * @setting: %TRUE to let this window receive input focus
+ * 
+ * Windows may set a hint asking the desktop environment not to receive
+ * the input focus. This function sets this hint.
+ * 
+ * Since: 2.4
+ **/
+void
+gtk_window_set_accept_focus (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->accept_focus != setting)
+    {
+      priv->accept_focus = setting;
+      if (GTK_WIDGET_REALIZED (window))
+        gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
+				     priv->accept_focus);
+      g_object_notify (G_OBJECT (window), "accept_focus");
+    }
+}
+
+/**
+ * gtk_window_get_accept_focus:
+ * @window: a #GtkWindow
+ * 
+ * Gets the value set by gtk_window_set_accept_focus().
+ * 
+ * Return value: %TRUE if window should receive the input focus
+ * 
+ * Since: 2.4
+ **/
+gboolean
+gtk_window_get_accept_focus (GtkWindow *window)
+{
+  GtkWindowPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+  
+  priv = GTK_WINDOW_GET_PRIVATE (window);
+
+  return priv->accept_focus;
+}
+
+/**
  * gtk_window_set_destroy_with_parent:
  * @window: a #GtkWindow
  * @setting: whether to destroy @window with its transient parent
@@ -3833,13 +3915,15 @@ gtk_window_realize (GtkWidget *widget)
   gdk_window_set_type_hint (widget->window, window->type_hint);
 
   if (gtk_window_get_skip_pager_hint (window))
-    {
-      g_print ("setting skip pager when realizing\n");
     gdk_window_set_skip_pager_hint (widget->window, TRUE);
-    }
 
   if (gtk_window_get_skip_taskbar_hint (window))
     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
+
+  if (gtk_window_get_accept_focus (window))
+    gdk_window_set_accept_focus (widget->window, TRUE);
+  else
+    gdk_window_set_accept_focus (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.72
diff -u -p -r1.72 gtkwindow.h
--- gtk/gtkwindow.h	3 Nov 2003 19:41:03 -0000	1.72
+++ gtk/gtkwindow.h	10 Dec 2003 23:43:07 -0000
@@ -201,6 +201,9 @@ gboolean   gtk_window_get_skip_taskbar_h
 void       gtk_window_set_skip_pager_hint      (GtkWindow           *window,
                                                 gboolean             setting);
 gboolean   gtk_window_get_skip_pager_hint      (GtkWindow           *window);
+void       gtk_window_set_accept_focus         (GtkWindow           *window,
+                                                gboolean             setting);
+gboolean   gtk_window_get_accept_focus         (GtkWindow           *window);
 void       gtk_window_set_destroy_with_parent  (GtkWindow           *window,
                                                 gboolean             setting);
 gboolean   gtk_window_get_destroy_with_parent  (GtkWindow           *window);
Index: docs/reference/ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/ChangeLog,v
retrieving revision 1.403
diff -u -p -r1.403 ChangeLog
--- docs/reference/ChangeLog	9 Dec 2003 23:12:47 -0000	1.403
+++ docs/reference/ChangeLog	10 Dec 2003 23:43:08 -0000
@@ -1,3 +1,8 @@
+Thu Dec 11 00:04:10 2003  Matthias Clasen  <maclas@gmx.de>
+
+	* gtk/gtk-sections.txt: Add gtk_window_[sg]et_accept_focus().
+	* gdk/gdk-sections.txt: Add gdk_window_set_accept_focus().
+
 Wed Dec 10 00:09:51 2003  Matthias Clasen  <maclas@gmx.de>
 
 	* gdk/gdk-sections.txt: Add gdk_window_get_group(), 
Index: docs/reference/gdk/gdk-sections.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gdk/gdk-sections.txt,v
retrieving revision 1.37
diff -u -p -r1.37 gdk-sections.txt
--- docs/reference/gdk/gdk-sections.txt	9 Dec 2003 23:12:50 -0000	1.37
+++ docs/reference/gdk/gdk-sections.txt	10 Dec 2003 23:43:08 -0000
@@ -658,6 +658,7 @@ gdk_window_get_internal_paint_info
 <SUBSECTION>
 gdk_window_set_user_data
 gdk_window_set_override_redirect
+gdk_window_set_accept_focus
 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.103
diff -u -p -r1.103 gtk-sections.txt
--- docs/reference/gtk/gtk-sections.txt	8 Dec 2003 22:55:03 -0000	1.103
+++ docs/reference/gtk/gtk-sections.txt	10 Dec 2003 23:43:09 -0000
@@ -4376,6 +4376,7 @@ gtk_window_set_role
 gtk_window_set_type_hint
 gtk_window_set_skip_taskbar_hint
 gtk_window_set_skip_pager_hint
+gtk_window_set_accept_focus
 gtk_window_get_decorated
 gtk_window_get_default_icon_list
 gtk_window_get_default_size
@@ -4394,6 +4395,7 @@ gtk_window_get_transient_for
 gtk_window_get_type_hint
 gtk_window_get_skip_taskbar_hint
 gtk_window_get_skip_pager_hint
+gtk_window_get_accept_focus
 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.47
diff -u -p -r1.47 gdkwindow.h
--- gdk/gdkwindow.h	9 Dec 2003 23:12:51 -0000	1.47
+++ gdk/gdkwindow.h	10 Dec 2003 23:43:10 -0000
@@ -260,6 +260,8 @@ struct _GdkWindowObject
   guint modal_hint : 1;
   
   guint destroyed : 2;
+
+  guint accept_focus : 1;
   
   GdkEventMask event_mask;
 };
@@ -317,6 +319,8 @@ void          gdk_window_set_user_data  
                                                 gpointer       user_data);
 void          gdk_window_set_override_redirect (GdkWindow     *window,
                                                 gboolean       override_redirect);
+void          gdk_window_set_accept_focus      (GdkWindow     *window,
+					        gboolean       accept_focus);
 void          gdk_window_add_filter            (GdkWindow     *window,
                                                 GdkFilterFunc  function,
                                                 gpointer       data);
Index: gdk/win32/gdkwindow-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkwindow-win32.c,v
retrieving revision 1.105
diff -u -p -r1.105 gdkwindow-win32.c
--- gdk/win32/gdkwindow-win32.c	7 Dec 2003 11:03:08 -0000	1.105
+++ gdk/win32/gdkwindow-win32.c	10 Dec 2003 23:43:10 -0000
@@ -468,6 +468,8 @@ gdk_window_new (GdkWindow     *parent,
   
   private->parent = (GdkWindowObject *)parent;
 
+  private->accept_focus = TRUE;
+
   if (attributes_mask & GDK_WA_X)
     private->x = attributes->x;
   else
@@ -2151,6 +2153,22 @@ gdk_window_set_override_redirect (GdkWin
   g_warning ("gdk_window_set_override_redirect not implemented");
 }
 
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+			     gboolean accept_focus)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  accept_focus = accept_focus != FALSE;
+
+  if (private->accept_focus != accept_focus)
+    private->accept_focus = accept_focus;
+}
+
 void          
 gdk_window_set_icon_list (GdkWindow *window,
 			  GList     *pixbufs)
Index: gdk/linux-fb/gdkwindow-fb.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/linux-fb/gdkwindow-fb.c,v
retrieving revision 1.53
diff -u -p -r1.53 gdkwindow-fb.c
--- gdk/linux-fb/gdkwindow-fb.c	16 Sep 2003 17:59:20 -0000	1.53
+++ gdk/linux-fb/gdkwindow-fb.c	10 Dec 2003 23:43:11 -0000
@@ -188,6 +188,8 @@ gdk_window_new (GdkWindow     *parent,
 
   private->parent = parent_private;
 
+  private->accept_focus = TRUE;
+
   if (attributes_mask & GDK_WA_X)
     x = attributes->x;
   else
@@ -1990,6 +1992,22 @@ gdk_window_set_override_redirect (GdkWin
   /* N/A */
 }
 
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+			     gboolean accept_focus)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  accept_focus = accept_focus != FALSE;
+
+  if (private->accept_focus != accept_focus)
+    private->accept_focus = accept_focus;
+}
+
 void          
 gdk_window_set_icon (GdkWindow *window, 
 		     GdkWindow *icon_window,
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.196
diff -u -p -r1.196 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	9 Dec 2003 23:12:52 -0000	1.196
+++ gdk/x11/gdkwindow-x11.c	10 Dec 2003 23:43:12 -0000
@@ -343,6 +343,7 @@ _gdk_windowing_window_init (GdkScreen * 
 static void
 set_wm_protocols (GdkWindow *window)
 {
+  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkDisplay *display = gdk_drawable_get_display (window);
   Atom protocols[3];
   
@@ -463,6 +464,8 @@ gdk_window_new (GdkWindow     *parent,
   
   private->parent = (GdkWindowObject *)parent;
 
+  private->accept_focus = TRUE;
+
   xattributes_mask = 0;
   
   if (attributes_mask & GDK_WA_X)
@@ -989,8 +992,8 @@ update_wm_hints (GdkWindow *window,
       private->state & GDK_WINDOW_STATE_WITHDRAWN)
     return;
 
-  wm_hints.flags = StateHint;
-  wm_hints.input = True;
+  wm_hints.flags = StateHint | InputHint;
+  wm_hints.input = private->accept_focus ? True : False;
   wm_hints.initial_state = NormalState;
   
   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
@@ -3223,6 +3226,40 @@ gdk_window_set_override_redirect (GdkWin
     }
 }
 
+/**
+ * gdk_window_set_accept_focus:
+ * @window: a toplevel #GdkWindow
+ * @accept_focus: %TRUE if the window should receive input focus
+ *
+ * Setting @accept_focus to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus. 
+ *
+ * On X, it is the responsibility of the window manager to interpret this 
+ * hint. ICCCM-compliant window manager usually respect it.
+ *
+ * Since: 2.4 
+ **/
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+			     gboolean accept_focus)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  accept_focus = accept_focus != FALSE;
+
+  if (private->accept_focus != accept_focus)
+    {
+      private->accept_focus = accept_focus;
+
+      if (!GDK_WINDOW_DESTROYED (window))
+	update_wm_hints (window, FALSE);
+    }
+}
+
 
 /**
  * gdk_window_set_icon_list:
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.118
diff -u -p -r1.118 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	11 Aug 2003 16:08:27 -0000	1.118
+++ gdk/x11/gdkevents-x11.c	10 Dec 2003 23:43:13 -0000
@@ -1969,11 +1969,12 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
   else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
     {
       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
+      GdkWindowObject *private = (GdkWindowObject *)win;
 
       /* There is no way of knowing reliably whether we are viewable;
        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
        */
-      if (toplevel)
+      if (toplevel && private->accept_focus)
 	_gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
 				       RevertToParent,
 				       xevent->xclient.data.l[1]);
