Index: gtk/gtk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.symbols,v
retrieving revision 1.131
diff -u -p -r1.131 gtk.symbols
--- gtk/gtk.symbols	10 Oct 2006 21:55:29 -0000	1.131
+++ gtk/gtk.symbols	12 Oct 2006 14:44:28 -0000
@@ -4460,6 +4460,7 @@ gtk_widget_create_pango_layout
 gtk_widget_destroy
 gtk_widget_destroyed
 gtk_widget_ensure_style
+gtk_widget_error_bell
 gtk_widget_event
 gtk_widget_freeze_child_notify
 gtk_widget_get_accessible
@@ -4501,6 +4502,7 @@ gtk_widget_hide_on_delete
 gtk_widget_intersect
 gtk_widget_is_ancestor
 gtk_widget_is_focus
+gtk_widget_keynav_failed
 gtk_widget_list_accel_closures
 gtk_widget_list_mnemonic_labels
 gtk_widget_map
Index: gtk/gtkcellrendereraccel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcellrendereraccel.c,v
retrieving revision 1.4
diff -u -p -r1.4 gtkcellrendereraccel.c
--- gtk/gtkcellrendereraccel.c	8 Oct 2006 05:06:33 -0000	1.4
+++ gtk/gtkcellrendereraccel.c	12 Oct 2006 14:44:28 -0000
@@ -456,7 +456,7 @@ grab_key_callback (GtkWidget    *widget,
     {
       if (!gtk_accelerator_valid (accel_key, accel_mods))
 	{
-	  gdk_display_beep (display);
+	  gtk_widget_error_bell (widget);
 
 	  return TRUE;
 	}
Index: gtk/gtkcombobox.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcombobox.c,v
retrieving revision 1.185
diff -u -p -r1.185 gtkcombobox.c
--- gtk/gtkcombobox.c	12 Oct 2006 13:48:07 -0000	1.185
+++ gtk/gtkcombobox.c	12 Oct 2006 14:44:28 -0000
@@ -4941,7 +4941,10 @@ gtk_combo_box_real_move_active (GtkCombo
   gboolean    found;
 
   if (!combo_box->priv->model)
-    return;
+    {
+      gtk_widget_error_bell (GTK_WIDGET (combo_box));
+      return;
+    }
 
   active_iter = gtk_combo_box_get_active_iter (combo_box, &iter);
 
@@ -4987,28 +4990,28 @@ gtk_combo_box_real_move_active (GtkCombo
       return;
     }
 
-  if (found)
+  if (found && active_iter)
     {
-      if (active_iter)
-        {
-          GtkTreePath *old_path;
-          GtkTreePath *new_path;
+      GtkTreePath *old_path;
+      GtkTreePath *new_path;
 
-          old_path = gtk_tree_model_get_path (combo_box->priv->model, &iter);
-          new_path = gtk_tree_model_get_path (combo_box->priv->model, &new_iter);
+      old_path = gtk_tree_model_get_path (combo_box->priv->model, &iter);
+      new_path = gtk_tree_model_get_path (combo_box->priv->model, &new_iter);
 
-          if (gtk_tree_path_compare (old_path, new_path) == 0)
-            found = FALSE;
+      if (gtk_tree_path_compare (old_path, new_path) == 0)
+        found = FALSE;
 
-          gtk_tree_path_free (old_path);
-          gtk_tree_path_free (new_path);
-        }
+      gtk_tree_path_free (old_path);
+      gtk_tree_path_free (new_path);
+    }
 
-      if (found)
-        {
-          gtk_combo_box_set_active_iter (combo_box, &new_iter);
-          return;
-        }
+  if (found)
+    {
+      gtk_combo_box_set_active_iter (combo_box, &new_iter);
+    }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (combo_box));
     }
 }
 
Index: gtk/gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.324
diff -u -p -r1.324 gtkentry.c
--- gtk/gtkentry.c	4 Oct 2006 03:26:34 -0000	1.324
+++ gtk/gtkentry.c	12 Oct 2006 14:44:28 -0000
@@ -1709,12 +1709,18 @@ gtk_entry_button_press (GtkWidget      *
 
       return TRUE;
     }
-  else if (event->button == 2 && event->type == GDK_BUTTON_PRESS && entry->editable)
+  else if (event->button == 2 && event->type == GDK_BUTTON_PRESS)
     {
-      priv->insert_pos = tmp_pos;
-      gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
-
-      return TRUE;
+      if (entry->editable)
+        {
+          priv->insert_pos = tmp_pos;
+          gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
+          return TRUE;
+        }
+      else
+        {
+          gtk_widget_error_bell (widget);
+        }
     }
   else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
     {
@@ -1976,6 +1982,9 @@ gtk_entry_key_press (GtkWidget   *widget
      */
     return TRUE;
 
+  if (!entry->editable && event->length)
+    gtk_widget_error_bell (widget);
+
   return FALSE;
 }
 
@@ -2329,7 +2338,7 @@ gtk_entry_real_insert_text (GtkEditable 
   n_chars = g_utf8_strlen (new_text, new_text_length);
   if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
     {
-      gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (entry)));
+      gtk_widget_error_bell (GTK_WIDGET (entry));
       n_chars = entry->text_max_length - entry->text_length;
       new_text_length = g_utf8_offset_to_pointer (new_text, n_chars) - new_text;
     }
@@ -2535,7 +2544,6 @@ gtk_entry_move_cursor (GtkEntry       *e
 	      new_pos = current_x < bound_x ? entry->current_pos : entry->selection_bound;
 	    else 
 	      new_pos = current_x > bound_x ? entry->current_pos : entry->selection_bound;
-
 	    break;
 	  }
 	case GTK_MOVEMENT_LOGICAL_POSITIONS:
@@ -2566,6 +2574,27 @@ gtk_entry_move_cursor (GtkEntry       *e
 	  break;
 	case GTK_MOVEMENT_VISUAL_POSITIONS:
 	  new_pos = gtk_entry_move_visually (entry, new_pos, count);
+          if (entry->current_pos == new_pos)
+            {
+              if (!extend_selection)
+                {
+                  if (!gtk_widget_keynav_failed (GTK_WIDGET (entry)
+                                                 , count > 0 ?
+                                                 GTK_DIR_RIGHT : GTK_DIR_LEFT))
+                    {
+                      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
+
+                      if (toplevel)
+                        gtk_widget_child_focus (toplevel,
+                                                count > 0 ?
+                                                GTK_DIR_RIGHT : GTK_DIR_LEFT);
+                    }
+                }
+              else
+                {
+                  gtk_widget_error_bell (GTK_WIDGET (entry));
+                }
+            }
 	  break;
 	case GTK_MOVEMENT_WORDS:
 	  while (count > 0)
@@ -2578,11 +2607,15 @@ gtk_entry_move_cursor (GtkEntry       *e
 	      new_pos = gtk_entry_move_backward_word (entry, new_pos, FALSE);
 	      count++;
 	    }
+          if (entry->current_pos == new_pos)
+            gtk_widget_error_bell (GTK_WIDGET (entry));
 	  break;
 	case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
 	case GTK_MOVEMENT_PARAGRAPH_ENDS:
 	case GTK_MOVEMENT_BUFFER_ENDS:
 	  new_pos = count < 0 ? 0 : entry->text_length;
+          if (entry->current_pos == new_pos)
+            gtk_widget_error_bell (GTK_WIDGET (entry));
 	  break;
 	case GTK_MOVEMENT_DISPLAY_LINES:
 	case GTK_MOVEMENT_PARAGRAPHS:
@@ -2624,11 +2657,15 @@ gtk_entry_delete_from_cursor (GtkEntry  
   GtkEditable *editable = GTK_EDITABLE (entry);
   gint start_pos = entry->current_pos;
   gint end_pos = entry->current_pos;
+  gint old_n_bytes = entry->n_bytes;
   
   _gtk_entry_reset_im_context (entry);
 
   if (!entry->editable)
-    return;
+    {
+      gtk_widget_error_bell (GTK_WIDGET (entry));
+      return;
+    }
 
   if (entry->selection_bound != entry->current_pos)
     {
@@ -2685,7 +2722,10 @@ gtk_entry_delete_from_cursor (GtkEntry  
       gtk_entry_delete_whitespace (entry);
       break;
     }
-  
+
+  if (entry->n_bytes == old_n_bytes)
+    gtk_widget_error_bell (GTK_WIDGET (entry));
+
   gtk_entry_pend_cursor_blink (entry);
 }
 
@@ -2698,7 +2738,10 @@ gtk_entry_backspace (GtkEntry *entry)
   _gtk_entry_reset_im_context (entry);
 
   if (!entry->editable || !entry->text)
-    return;
+    {
+      gtk_widget_error_bell (GTK_WIDGET (entry));
+      return;
+    }
 
   if (entry->selection_bound != entry->current_pos)
     {
@@ -2751,6 +2794,10 @@ gtk_entry_backspace (GtkEntry *entry)
       
       g_free (log_attrs);
     }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (entry));
+    }
 
   gtk_entry_pend_cursor_blink (entry);
 }
@@ -2784,6 +2831,10 @@ gtk_entry_cut_clipboard (GtkEntry *entry
       if (gtk_editable_get_selection_bounds (editable, &start, &end))
 	gtk_editable_delete_text (editable, start, end);
     }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (entry));
+    }
 }
 
 static void
@@ -2791,6 +2842,8 @@ gtk_entry_paste_clipboard (GtkEntry *ent
 {
   if (entry->editable)
     gtk_entry_paste (entry, GDK_NONE);
+  else
+    gtk_widget_error_bell (GTK_WIDGET (entry));
 }
 
 static void
Index: gtk/gtkiconview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkiconview.c,v
retrieving revision 1.105
diff -u -p -r1.105 gtkiconview.c
--- gtk/gtkiconview.c	8 Oct 2006 05:07:02 -0000	1.105
+++ gtk/gtkiconview.c	12 Oct 2006 14:44:30 -0000
@@ -3796,7 +3796,10 @@ gtk_icon_view_move_cursor_up_down (GtkIc
     }
 
   if (!item)
-    return;
+    {
+      gtk_widget_error_bell (GTK_WIDGET (icon_view));
+      return;
+    }
 
   if (icon_view->priv->ctrl_pressed ||
       !icon_view->priv->shift_pressed ||
@@ -3847,6 +3850,9 @@ gtk_icon_view_move_cursor_page_up_down (
 				   icon_view->priv->cursor_item,
 				   count);
 
+  if (item == icon_view->priv->cursor_item)
+    gtk_widget_error_bell (GTK_WIDGET (icon_view));
+
   if (!item)
     return;
 
@@ -3915,7 +3921,10 @@ gtk_icon_view_move_cursor_left_right (Gt
     }
 
   if (!item)
-    return;
+    {
+      gtk_widget_error_bell (GTK_WIDGET (icon_view));
+      return;
+    }
 
   if (icon_view->priv->ctrl_pressed ||
       !icon_view->priv->shift_pressed ||
@@ -3957,6 +3966,9 @@ gtk_icon_view_move_cursor_start_end (Gtk
     list = g_list_last (icon_view->priv->items);
   
   item = list ? list->data : NULL;
+
+  if (item == icon_view->priv->cursor_item)
+    gtk_widget_error_bell (GTK_WIDGET (icon_view));
 
   if (!item)
     return;
Index: gtk/gtkimcontextsimple.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimcontextsimple.c,v
retrieving revision 1.57
diff -u -p -r1.57 gtkimcontextsimple.c
--- gtk/gtkimcontextsimple.c	21 Jul 2006 13:42:43 -0000	1.57
+++ gtk/gtkimcontextsimple.c	12 Oct 2006 14:44:31 -0000
@@ -23,6 +23,8 @@
 #include <gdk/gdkkeysyms.h>
 #include "gtkaccelgroup.h"
 #include "gtkimcontextsimple.h"
+#include "gtksettings.h"
+#include "gtkwidget.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -1175,6 +1177,31 @@ check_hex (GtkIMContextSimple *context_s
   return TRUE;
 }
 
+static void
+beep_window (GdkWindow *window)
+{
+  GtkWidget *widget;
+
+  gdk_window_get_user_data (window, &widget);
+
+  if (GTK_IS_WIDGET (widget))
+    {
+      gtk_widget_error_bell (widget);
+    }
+  else
+    {
+      GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+      gboolean   beep;
+
+      g_object_get (gtk_settings_get_for_screen (screen),
+                    "gtk-error-bell", &beep,
+                    NULL);
+
+      if (beep)
+        gdk_window_beep (window);
+    }
+}
+
 static gboolean
 no_sequence_matches (GtkIMContextSimple *context_simple,
                      gint                n_compose,
@@ -1212,7 +1239,7 @@ no_sequence_matches (GtkIMContextSimple 
       context_simple->compose_buffer[0] = 0;
       if (n_compose > 1)		/* Invalid sequence */
 	{
-	  gdk_display_beep (gdk_drawable_get_display (event->window));
+	  beep_window (event->window);
 	  return TRUE;
 	}
   
@@ -1317,7 +1344,7 @@ gtk_im_context_simple_filter_keypress (G
 	  else
 	    {
 	      /* invalid hex sequence */
-	      gdk_display_beep (gdk_drawable_get_display (event->window));
+	      beep_window (event->window);
 	      
 	      context_simple->tentative_match = 0;
 	      context_simple->in_hex_sequence = FALSE;
@@ -1403,7 +1430,7 @@ gtk_im_context_simple_filter_keypress (G
 	{
 	  /* invalid hex sequence */
 	  if (n_compose > 0)
-	    gdk_display_beep (gdk_drawable_get_display (event->window));
+	    beep_window (event->window);
 	  
 	  context_simple->tentative_match = 0;
 	  context_simple->in_hex_sequence = FALSE;
@@ -1438,7 +1465,7 @@ gtk_im_context_simple_filter_keypress (G
       else if (!is_hex_end)
 	{
 	  /* non-hex character in hex sequence */
-	  gdk_display_beep (gdk_drawable_get_display (event->window));
+	  beep_window (event->window);
 	  
 	  return TRUE;
 	}
@@ -1465,7 +1492,7 @@ gtk_im_context_simple_filter_keypress (G
 	      else
 		{
 		  /* invalid hex sequence */
-		  gdk_display_beep (gdk_drawable_get_display (event->window));
+		  beep_window (event->window);
 
 		  context_simple->tentative_match = 0;
 		  context_simple->in_hex_sequence = FALSE;
@@ -1473,7 +1500,7 @@ gtk_im_context_simple_filter_keypress (G
 		}
             }
           else if (!check_hex (context_simple, n_compose))
-	    gdk_display_beep (gdk_drawable_get_display (event->window));
+	    beep_window (event->window);
 	  
 	  g_signal_emit_by_name (context_simple, "preedit_changed");
 
Index: gtk/gtklabel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtklabel.c,v
retrieving revision 1.203
diff -u -p -r1.203 gtklabel.c
--- gtk/gtklabel.c	6 Jul 2006 05:14:01 -0000	1.203
+++ gtk/gtklabel.c	12 Oct 2006 14:44:32 -0000
@@ -891,8 +891,8 @@ gtk_label_mnemonic_activate (GtkWidget *
 
   /* barf if there was nothing to activate */
   g_warning ("Couldn't find a target for a mnemonic activation.");
-  gdk_display_beep (gtk_widget_get_display (widget));
-  
+  gtk_widget_error_bell (widget);
+
   return FALSE;
 }
 
@@ -3871,12 +3871,13 @@ gtk_label_move_cursor (GtkLabel       *l
 		       gint            count,
 		       gboolean        extend_selection)
 {
+  gint old_pos;
   gint new_pos;
   
   if (label->select_info == NULL)
     return;
-  
-  new_pos = label->select_info->selection_end;
+
+  old_pos = new_pos = label->select_info->selection_end;
 
   if (label->select_info->selection_end != label->select_info->selection_anchor &&
       !extend_selection)
@@ -3901,7 +3902,6 @@ gtk_label_move_cursor (GtkLabel       *l
 	      new_pos = end_is_left ? label->select_info->selection_end : label->select_info->selection_anchor;
 	    else
 	      new_pos = !end_is_left ? label->select_info->selection_end : label->select_info->selection_anchor;
-
 	    break;
 	  }
 	case GTK_MOVEMENT_LOGICAL_POSITIONS:
@@ -3933,6 +3933,27 @@ gtk_label_move_cursor (GtkLabel       *l
 	  break;
 	case GTK_MOVEMENT_VISUAL_POSITIONS:
 	  new_pos = gtk_label_move_visually (label, new_pos, count);
+          if (new_pos == old_pos)
+            {
+              if (!extend_selection)
+                {
+                  if (!gtk_widget_keynav_failed (GTK_WIDGET (label),
+                                                 count > 0 ?
+                                                 GTK_DIR_RIGHT : GTK_DIR_LEFT))
+                    {
+                      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+                      if (toplevel)
+                        gtk_widget_child_focus (toplevel,
+                                                count > 0 ?
+                                                GTK_DIR_RIGHT : GTK_DIR_LEFT);
+                    }
+                }
+              else
+                {
+                  gtk_widget_error_bell (GTK_WIDGET (label));
+                }
+            }
 	  break;
 	case GTK_MOVEMENT_WORDS:
 	  while (count > 0)
@@ -3945,12 +3966,16 @@ gtk_label_move_cursor (GtkLabel       *l
 	      new_pos = gtk_label_move_backward_word (label, new_pos);
 	      count++;
 	    }
+          if (new_pos == old_pos)
+            gtk_widget_error_bell (GTK_WIDGET (label));
 	  break;
 	case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
 	case GTK_MOVEMENT_PARAGRAPH_ENDS:
 	case GTK_MOVEMENT_BUFFER_ENDS:
 	  /* FIXME: Can do better here */
 	  new_pos = count < 0 ? 0 : strlen (label->text);
+          if (new_pos == old_pos)
+            gtk_widget_error_bell (GTK_WIDGET (label));
 	  break;
 	case GTK_MOVEMENT_DISPLAY_LINES:
 	case GTK_MOVEMENT_PARAGRAPHS:
Index: gtk/gtkmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.c,v
retrieving revision 1.224
diff -u -p -r1.224 gtkmenu.c
--- gtk/gtkmenu.c	8 Oct 2006 05:07:07 -0000	1.224
+++ gtk/gtkmenu.c	12 Oct 2006 14:44:34 -0000
@@ -2756,7 +2756,7 @@ gtk_menu_key_press (GtkWidget	*widget,
 	   * (basically, those items are accelerator-locked).
 	   */
 	  /* g_print("item has no path or is locked, menu prefix: %s\n", menu->accel_path); */
-	  gdk_display_beep (display);
+	  gtk_widget_error_bell (widget);
 	}
       else
 	{
@@ -2785,7 +2785,7 @@ gtk_menu_key_press (GtkWidget	*widget,
 	       * locked already
 	       */
 	      /* g_print("failed to change\n"); */
-	      gdk_display_beep (display);
+	      gtk_widget_error_bell (widget);
 	    }
 	}
     }
Index: gtk/gtkmenushell.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenushell.c,v
retrieving revision 1.101
diff -u -p -r1.101 gtkmenushell.c
--- gtk/gtkmenushell.c	14 May 2006 04:25:29 -0000	1.101
+++ gtk/gtkmenushell.c	12 Oct 2006 14:44:34 -0000
@@ -1044,17 +1044,27 @@ gtk_menu_shell_move_selected (GtkMenuShe
       GList *node = g_list_find (menu_shell->children,
 				 menu_shell->active_menu_item);
       GList *start_node = node;
-      
+      gboolean wrap_around;
+
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
+                    "gtk-keynav-wrap-around", &wrap_around,
+                    NULL);
+
       if (distance > 0)
 	{
 	  node = node->next;
 	  while (node != start_node && 
 		 (!node || !_gtk_menu_item_is_selectable (node->data)))
 	    {
-	      if (!node)
-		node = menu_shell->children;
-	      else
+	      if (node)
 		node = node->next;
+              else if (wrap_around)
+		node = menu_shell->children;
+              else
+                {
+                  gtk_widget_error_bell (GTK_WIDGET (menu_shell));
+                  break;
+                }
 	    }
 	}
       else
@@ -1063,10 +1073,15 @@ gtk_menu_shell_move_selected (GtkMenuShe
 	  while (node != start_node &&
 		 (!node || !_gtk_menu_item_is_selectable (node->data)))
 	    {
-	      if (!node)
-		node = g_list_last (menu_shell->children);
-	      else
+	      if (node)
 		node = node->prev;
+              else if (wrap_around)
+		node = g_list_last (menu_shell->children);
+              else
+                {
+                  gtk_widget_error_bell (GTK_WIDGET (menu_shell));
+                  break;
+                }
 	    }
 	}
       
Index: gtk/gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.229
diff -u -p -r1.229 gtknotebook.c
--- gtk/gtknotebook.c	8 Oct 2006 19:00:31 -0000	1.229
+++ gtk/gtknotebook.c	12 Oct 2006 14:44:36 -0000
@@ -1066,14 +1066,33 @@ gtk_notebook_change_current_page (GtkNot
 
   while (offset != 0)
     {
-      current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
+      current = gtk_notebook_search_page (notebook, current,
+                                          offset < 0 ? STEP_PREV : STEP_NEXT,
+                                          TRUE);
+
+      if (!current)
+        {
+          gboolean wrap_around;
+
+          g_object_get (gtk_widget_get_settings (GTK_WIDGET (notebook)),
+                        "gtk-keynav-wrap-around", &wrap_around,
+                        NULL);
+
+          if (wrap_around)
+            current = gtk_notebook_search_page (notebook, NULL,
+                                                offset < 0 ? STEP_PREV : STEP_NEXT,
+                                                TRUE);
+          else
+            break;
+        }
+
       offset += offset < 0 ? 1 : -1;
     }
 
   if (current)
     gtk_notebook_switch_page (notebook, current->data, -1);
   else
-    gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
+    gtk_widget_error_bell (GTK_WIDGET (notebook));
 }
 
 static GtkDirectionType
@@ -3589,11 +3608,24 @@ focus_tabs_move (GtkNotebook     *notebo
 
   new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
 				       search_direction, TRUE);
+  if (!new_page)
+    {
+      gboolean wrap_around;
+
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (notebook)),
+                    "gtk-keynav-wrap-around", &wrap_around,
+                    NULL);
+
+      if (wrap_around)
+        new_page = gtk_notebook_search_page (notebook, NULL,
+                                             search_direction, TRUE);
+    }
+
   if (new_page)
     gtk_notebook_switch_focus_tab (notebook, new_page);
   else
-    gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
-  
+    gtk_widget_error_bell (GTK_WIDGET (notebook));
+
   return TRUE;
 }
 
Index: gtk/gtkradiobutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkradiobutton.c,v
retrieving revision 1.63
diff -u -p -r1.63 gtkradiobutton.c
--- gtk/gtkradiobutton.c	8 Oct 2006 05:32:06 -0000	1.63
+++ gtk/gtkradiobutton.c	12 Oct 2006 14:44:36 -0000
@@ -491,6 +491,12 @@ gtk_radio_button_focus (GtkWidget       
 
       if (!new_focus)
 	{
+          if (!gtk_widget_keynav_failed (widget, direction))
+            {
+              g_slist_free (focus_list);
+              return FALSE;
+            }
+
 	  tmp_list = focus_list;
 
 	  while (tmp_list)
@@ -511,8 +517,17 @@ gtk_radio_button_focus (GtkWidget       
 
       if (new_focus)
 	{
+          GtkSettings *settings = gtk_widget_get_settings (widget);
+          gboolean     cursor_only;
+
+          g_object_get (settings,
+                        "gtk-keynav-cursor-only", &cursor_only,
+                        NULL);
+
 	  gtk_widget_grab_focus (new_focus);
-	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
+
+          if (!cursor_only)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
 	}
 
       return TRUE;
Index: gtk/gtkrange.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.c,v
retrieving revision 1.129
diff -u -p -r1.129 gtkrange.c
--- gtk/gtkrange.c	8 Oct 2006 05:07:15 -0000	1.129
+++ gtk/gtkrange.c	12 Oct 2006 14:44:37 -0000
@@ -2168,6 +2168,42 @@ static void
 gtk_range_move_slider (GtkRange     *range,
                        GtkScrollType scroll)
 {
+  gboolean cursor_only;
+
+  g_object_get (gtk_widget_get_settings (GTK_WIDGET (range)),
+                "gtk-keynav-cursor-only", &cursor_only,
+                NULL);
+
+  if (cursor_only)
+    {
+      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (range));
+
+      if (range->orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          if (scroll == GTK_SCROLL_STEP_UP ||
+              scroll == GTK_SCROLL_STEP_DOWN)
+            {
+              if (toplevel)
+                gtk_widget_child_focus (toplevel,
+                                        scroll == GTK_SCROLL_STEP_UP ?
+                                        GTK_DIR_UP : GTK_DIR_DOWN);
+              return;
+            }
+        }
+      else
+        {
+          if (scroll == GTK_SCROLL_STEP_LEFT ||
+              scroll == GTK_SCROLL_STEP_RIGHT)
+            {
+              if (toplevel)
+                gtk_widget_child_focus (toplevel,
+                                        scroll == GTK_SCROLL_STEP_LEFT ?
+                                        GTK_DIR_LEFT : GTK_DIR_RIGHT);
+              return;
+            }
+        }
+    }
+
   gtk_range_scroll (range, scroll);
 
   /* Policy DELAYED makes sense with key events,
Index: gtk/gtksettings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksettings.c,v
retrieving revision 1.102
diff -u -p -r1.102 gtksettings.c
--- gtk/gtksettings.c	9 Sep 2006 05:22:16 -0000	1.102
+++ gtk/gtksettings.c	12 Oct 2006 14:44:37 -0000
@@ -93,6 +93,9 @@ enum {
   PROP_COLOR_SCHEME,
   PROP_ENABLE_ANIMATIONS,
   PROP_TOUCHSCREEN_MODE,
+  PROP_KEYNAV_CURSOR_ONLY,
+  PROP_KEYNAV_WRAP_AROUND,
+  PROP_ERROR_BELL,
   PROP_COLOR_HASH
 };
 
@@ -522,6 +525,59 @@ gtk_settings_class_init (GtkSettingsClas
                                              NULL);
 
   g_assert (result == PROP_TOUCHSCREEN_MODE);
+
+  /**
+   * GtkSettings:gtk-keynav-cursor-only:
+   *
+   * When TRUE, keyboard navigation should be able to reach all widgets
+   * by using the cursor keys only. Tab, Shift etc. keys can't be expected
+   * to be present on the used input device.
+   *
+   * Since: 2.12
+   */
+  result = settings_install_property_parser (class,
+                                             g_param_spec_boolean ("gtk-keynav-cursor-only",
+                                                                   P_("Keynav Cursor Only"),
+                                                                   P_("When TRUE, there are only cursor keys available to navigate widgets"),
+                                                                   FALSE,
+                                                                   GTK_PARAM_READWRITE),
+                                             NULL);
+
+  g_assert (result == PROP_KEYNAV_CURSOR_ONLY);
+
+  /**
+   * GtkSettings:gtk-keynav-wrap-around:
+   *
+   * When TRUE, some widgets will wrap around when doing keyboard navigation.
+   *
+   * Since: 2.12
+   */
+  result = settings_install_property_parser (class,
+                                             g_param_spec_boolean ("gtk-keynav-wrap-around",
+                                                                   P_("Keynav Wrap Around"),
+                                                                   P_("Whether to wrap around when keyboard-navigating widgets"),
+                                                                   TRUE,
+                                                                   GTK_PARAM_READWRITE),
+                                             NULL);
+
+  g_assert (result == PROP_KEYNAV_WRAP_AROUND);
+
+  /**
+   * GtkSettings:gtk-error-bell:
+   *
+   * When TRUE, keyboard navigation and other errors will cause a beep.
+   *
+   * Since: 2.12
+   */
+  result = settings_install_property_parser (class,
+                                             g_param_spec_boolean ("gtk-error-bell",
+                                                                   P_("Error Bell"),
+                                                                   P_("When TRUE, keyboard navigation and other errors will cause a beep"),
+                                                                   TRUE,
+                                                                   GTK_PARAM_READWRITE),
+                                             NULL);
+
+  g_assert (result == PROP_ERROR_BELL);
 
   /**
    * GtkSettings:color-hash:
Index: gtk/gtkspinbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkspinbutton.c,v
retrieving revision 1.128
diff -u -p -r1.128 gtkspinbutton.c
--- gtk/gtkspinbutton.c	15 Aug 2006 18:52:14 -0000	1.128
+++ gtk/gtkspinbutton.c	12 Oct 2006 14:44:38 -0000
@@ -1243,6 +1243,8 @@ static void
 gtk_spin_button_real_change_value (GtkSpinButton *spin,
 				   GtkScrollType  scroll)
 {
+  gdouble old_value = spin->adjustment->value;
+
   /* We don't test whether the entry is editable, since
    * this key binding conceptually corresponds to changing
    * the value with the buttons using the mouse, which
@@ -1320,6 +1322,9 @@ gtk_spin_button_real_change_value (GtkSp
     }
   
   gtk_spin_button_update (spin);
+
+  if (spin->adjustment->value == old_value)
+    gtk_widget_error_bell (GTK_WIDGET (spin));
 }
 
 static gint
Index: gtk/gtktextview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextview.c,v
retrieving revision 1.322
diff -u -p -r1.322 gtktextview.c
--- gtk/gtktextview.c	1 Sep 2006 02:14:30 -0000	1.322
+++ gtk/gtktextview.c	12 Oct 2006 14:44:41 -0000
@@ -260,10 +260,10 @@ static void gtk_text_view_move_viewport 
                                              GtkScrollStep          step,
                                              gint                   count);
 static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
-static void gtk_text_view_scroll_pages     (GtkTextView           *text_view,
+static gboolean gtk_text_view_scroll_pages (GtkTextView           *text_view,
                                             gint                   count,
                                             gboolean               extend_selection);
-static void gtk_text_view_scroll_hpages    (GtkTextView           *text_view,
+static gboolean gtk_text_view_scroll_hpages(GtkTextView           *text_view,
                                             gint                   count,
                                             gboolean               extend_selection);
 static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
@@ -3922,6 +3922,9 @@ gtk_text_view_key_press_event (GtkWidget
   gtk_text_view_reset_blink_time (text_view);
   gtk_text_view_pend_cursor_blink (text_view);
 
+  if (!retval && event->length)
+    gtk_widget_error_bell (widget);
+
   return retval;
 }
 
@@ -4688,8 +4691,8 @@ gtk_text_view_move_cursor_internal (GtkT
 {
   GtkTextIter insert;
   GtkTextIter newplace;
-
   gint cursor_x_pos = 0;
+  GtkDirectionType leave_direction = -1;
 
   if (!text_view->cursor_visible) 
     {
@@ -4733,14 +4736,18 @@ gtk_text_view_move_cursor_internal (GtkT
 
   if (step == GTK_MOVEMENT_PAGES)
     {
-      gtk_text_view_scroll_pages (text_view, count, extend_selection);
+      if (!gtk_text_view_scroll_pages (text_view, count, extend_selection))
+        gtk_widget_error_bell (GTK_WIDGET (text_view));
+
       gtk_text_view_check_cursor_blink (text_view);
       gtk_text_view_pend_cursor_blink (text_view);
       return;
     }
   else if (step == GTK_MOVEMENT_HORIZONTAL_PAGES)
     {
-      gtk_text_view_scroll_hpages (text_view, count, extend_selection);
+      if (!gtk_text_view_scroll_hpages (text_view, count, extend_selection))
+        gtk_widget_error_bell (GTK_WIDGET (text_view));
+
       gtk_text_view_check_cursor_blink (text_view);
       gtk_text_view_pend_cursor_blink (text_view);
       return;
@@ -4777,19 +4784,23 @@ gtk_text_view_move_cursor_internal (GtkT
 
     case GTK_MOVEMENT_DISPLAY_LINES:
       if (count < 0)
-      {
-        if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
-          gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
-        else
-          gtk_text_iter_set_line_offset (&newplace, 0);
-      }
+        {
+          leave_direction = GTK_DIR_UP;
+
+          if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
+            gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
+          else
+            gtk_text_iter_set_line_offset (&newplace, 0);
+        }
       if (count > 0)
-      {
-        if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
-          gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
-        else
-          gtk_text_iter_forward_to_line_end (&newplace);
-      }
+        {
+          leave_direction = GTK_DIR_DOWN;
+
+          if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
+            gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
+          else
+            gtk_text_iter_forward_to_line_end (&newplace);
+        }
       break;
 
     case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
@@ -4860,6 +4871,18 @@ gtk_text_view_move_cursor_internal (GtkT
       if (step == GTK_MOVEMENT_DISPLAY_LINES)
         gtk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1);
     }
+  else if (leave_direction != -1)
+    {
+      if (!gtk_widget_keynav_failed (GTK_WIDGET (text_view),
+                                     leave_direction))
+        {
+          gtk_text_view_move_focus (text_view, leave_direction);
+        }
+    }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (text_view));
+    }
 
   gtk_text_view_check_cursor_blink (text_view);
   gtk_text_view_pend_cursor_blink (text_view);
@@ -4943,7 +4966,7 @@ gtk_text_view_set_anchor (GtkTextView *t
   gtk_text_buffer_create_mark (get_buffer (text_view), "anchor", &insert, TRUE);
 }
 
-static void
+static gboolean
 gtk_text_view_scroll_pages (GtkTextView *text_view,
                             gint         count,
                             gboolean     extend_selection)
@@ -4952,11 +4975,12 @@ gtk_text_view_scroll_pages (GtkTextView 
   gdouble oldval;
   GtkAdjustment *adj;
   gint cursor_x_pos, cursor_y_pos;
+  GtkTextIter old_insert;
   GtkTextIter new_insert;
   GtkTextIter anchor;
   gint y0, y1;
 
-  g_return_if_fail (text_view->vadjustment != NULL);
+  g_return_val_if_fail (text_view->vadjustment != NULL, FALSE);
   
   adj = text_view->vadjustment;
 
@@ -4970,9 +4994,13 @@ gtk_text_view_scroll_pages (GtkTextView 
     gtk_text_view_scroll_mark_onscreen (text_view,
 					gtk_text_buffer_get_mark (get_buffer (text_view),
 								  "insert"));
-  
-/* Validate the region that will be brought into view by the cursor motion
+
+  /* Validate the region that will be brought into view by the cursor motion
    */
+  gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+                                    &old_insert,
+                                    gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
+
   if (count < 0)
     {
       gtk_text_view_get_first_para_iter (text_view, &anchor);
@@ -4989,6 +5017,8 @@ gtk_text_view_scroll_pages (GtkTextView 
   gtk_text_layout_validate_yrange (text_view->layout, &anchor, y0, y1);
   /* FIXME do we need to update the adjustment ranges here? */
 
+  new_insert = old_insert;
+
   if (count < 0 && adj->value <= (adj->lower + 1e-12))
     {
       /* already at top, just be sure we are at offset 0 */
@@ -5005,9 +5035,9 @@ gtk_text_view_scroll_pages (GtkTextView 
     {
       gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
 
-      newval = adj->value;
       oldval = adj->value;
-  
+      newval = adj->value;
+
       newval += count * adj->page_increment;
 
       set_adjustment_clamped (adj, newval);
@@ -5027,9 +5057,11 @@ gtk_text_view_scroll_pages (GtkTextView 
   gtk_text_view_scroll_mark_onscreen (text_view,
                                       gtk_text_buffer_get_mark (get_buffer (text_view),
                                                                 "insert"));
+
+  return !gtk_text_iter_equal (&old_insert, &new_insert);
 }
 
-static void
+static gboolean
 gtk_text_view_scroll_hpages (GtkTextView *text_view,
                              gint         count,
                              gboolean     extend_selection)
@@ -5038,10 +5070,11 @@ gtk_text_view_scroll_hpages (GtkTextView
   gdouble oldval;
   GtkAdjustment *adj;
   gint cursor_x_pos, cursor_y_pos;
+  GtkTextIter old_insert;
   GtkTextIter new_insert;
   gint y, height;
   
-  g_return_if_fail (text_view->hadjustment != NULL);
+  g_return_val_if_fail (text_view->hadjustment != NULL, FALSE);
 
   adj = text_view->hadjustment;
 
@@ -5055,16 +5088,18 @@ gtk_text_view_scroll_hpages (GtkTextView
     gtk_text_view_scroll_mark_onscreen (text_view,
 					gtk_text_buffer_get_mark (get_buffer (text_view),
 								  "insert"));
-  
+
   /* Validate the line that we're moving within.
    */
   gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
-                                    &new_insert,
+                                    &old_insert,
                                     gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
   gtk_text_layout_get_line_yrange (text_view->layout, &new_insert, &y, &height);
   gtk_text_layout_validate_yrange (text_view->layout, &new_insert, y, y + height);
   /* FIXME do we need to update the adjustment ranges here? */
-  
+
+  new_insert = old_insert;
+
   if (count < 0 && adj->value <= (adj->lower + 1e-12))
     {
       /* already at far left, just be sure we are at offset 0 */
@@ -5082,9 +5117,9 @@ gtk_text_view_scroll_hpages (GtkTextView
     {
       gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
 
-      newval = adj->value;
       oldval = adj->value;
-  
+      newval = adj->value;
+
       newval += count * adj->page_increment;
 
       set_adjustment_clamped (adj, newval);
@@ -5110,6 +5145,8 @@ gtk_text_view_scroll_hpages (GtkTextView
   gtk_text_view_scroll_mark_onscreen (text_view,
                                       gtk_text_buffer_get_mark (get_buffer (text_view),
                                                                 "insert"));
+
+  return !gtk_text_iter_equal (&old_insert, &new_insert);
 }
 
 static gboolean
@@ -5143,8 +5180,11 @@ static void
 gtk_text_view_insert_at_cursor (GtkTextView *text_view,
                                 const gchar *str)
 {
-  gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
-                                                text_view->editable);
+  if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
+                                                     text_view->editable))
+    {
+      gtk_widget_error_bell (GTK_WIDGET (text_view));
+    }
 }
 
 static void
@@ -5261,6 +5301,10 @@ gtk_text_view_delete_from_cursor (GtkTex
                                                           " ", 1,
                                                           text_view->editable);
         }
+      else
+        {
+          gtk_widget_error_bell (GTK_WIDGET (text_view));
+        }
 
       gtk_text_buffer_end_user_action (get_buffer (text_view));
       gtk_text_view_set_virtual_cursor_pos (text_view, -1, -1);
@@ -5269,6 +5313,10 @@ gtk_text_view_delete_from_cursor (GtkTex
       gtk_text_view_scroll_mark_onscreen (text_view,
                                           gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
     }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (text_view));
+    }
 }
 
 static void
@@ -5295,6 +5343,10 @@ gtk_text_view_backspace (GtkTextView *te
       gtk_text_view_scroll_mark_onscreen (text_view,
                                           gtk_text_buffer_get_insert (get_buffer (text_view)));
     }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (text_view));
+    }
 }
 
 static void
@@ -6337,9 +6389,13 @@ insert_text_data (GtkTextView      *text
 
   if (str)
     {
-      gtk_text_buffer_insert_interactive (get_buffer (text_view),
-                                          drop_point, (gchar *) str, -1,
-                                          text_view->editable);
+      if (!gtk_text_buffer_insert_interactive (get_buffer (text_view),
+                                               drop_point, (gchar *) str, -1,
+                                               text_view->editable))
+        {
+          gtk_widget_error_bell (GTK_WIDGET (text_view));
+        }
+
       g_free (str);
     }
 }
@@ -6804,8 +6860,11 @@ gtk_text_view_commit_text (GtkTextView  
 
   if (!strcmp (str, "\n"))
     {
-      gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\n", 1,
-                                                    text_view->editable);
+      if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\n", 1,
+                                                         text_view->editable))
+        {
+          gtk_widget_error_bell (GTK_WIDGET (text_view));
+        }
     }
   else
     {
@@ -6820,8 +6879,12 @@ gtk_text_view_commit_text (GtkTextView  
 	  if (!gtk_text_iter_ends_line (&insert))
 	    gtk_text_view_delete_from_cursor (text_view, GTK_DELETE_CHARS, 1);
 	}
-      gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
-                                                    text_view->editable);
+
+      if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
+                                                         text_view->editable))
+        {
+          gtk_widget_error_bell (GTK_WIDGET (text_view));
+        }
     }
 
   gtk_text_buffer_end_user_action (get_buffer (text_view));
Index: gtk/gtktreeview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeview.c,v
retrieving revision 1.573
diff -u -p -r1.573 gtktreeview.c
--- gtk/gtktreeview.c	8 Oct 2006 14:36:20 -0000	1.573
+++ gtk/gtktreeview.c	12 Oct 2006 14:44:45 -0000
@@ -5112,11 +5112,16 @@ gtk_tree_view_key_press (GtkWidget   *wi
           GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
 
           if (!column->resizable)
-            return TRUE;
+            {
+              gtk_widget_error_bell (widget);
+              return TRUE;
+            }
 
           if (event->keyval == (rtl ? GDK_Right : GDK_Left)
               || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
             {
+              gint old_width = column->resized_width;
+
               column->resized_width = MAX (column->resized_width,
                                            column->width);
               column->resized_width -= 2;
@@ -5135,11 +5140,17 @@ gtk_tree_view_key_press (GtkWidget   *wi
                                              column->max_width);
 
               column->use_resized_width = TRUE;
-              gtk_widget_queue_resize (widget);
+
+              if (column->resized_width != old_width)
+                gtk_widget_queue_resize (widget);
+              else
+                gtk_widget_error_bell (widget);
             }
           else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
                    || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
             {
+              gint old_width = column->resized_width;
+
               column->resized_width = MAX (column->resized_width,
                                            column->width);
               column->resized_width += 2;
@@ -5149,7 +5160,11 @@ gtk_tree_view_key_press (GtkWidget   *wi
                                              column->max_width);
 
               column->use_resized_width = TRUE;
-              gtk_widget_queue_resize (widget);
+
+              if (column->resized_width != old_width)
+                gtk_widget_queue_resize (widget);
+              else
+                gtk_widget_error_bell (widget);
             }
 
           return TRUE;
@@ -5203,8 +5218,7 @@ gtk_tree_view_key_press (GtkWidget   *wi
            || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
         {
           if ((event->keyval == (rtl ? GDK_Right : GDK_Left)
-               || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
-              && focus_column->prev)
+               || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left)))
             {
               GList *tmp;
 
@@ -5213,7 +5227,10 @@ gtk_tree_view_key_press (GtkWidget   *wi
                   break;
 
               if (!tmp)
-                return FALSE;
+                {
+                  gtk_widget_error_bell (widget);
+                  return TRUE;
+                }
 
               tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
               gtk_widget_grab_focus (tree_view->priv->focus_column->button);
@@ -5224,8 +5241,7 @@ gtk_tree_view_key_press (GtkWidget   *wi
                                                tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
             }
           else if ((event->keyval == (rtl ? GDK_Left : GDK_Right)
-                    || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
-                   && focus_column->next)
+                    || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right)))
             {
               GList *tmp;
 
@@ -5234,7 +5250,10 @@ gtk_tree_view_key_press (GtkWidget   *wi
                   break;
 
               if (!tmp)
-                return FALSE;
+                {
+                  gtk_widget_error_bell (widget);
+                  return TRUE;
+                }
 
               tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
 
@@ -9554,6 +9573,7 @@ gtk_tree_view_move_cursor_up_down (GtkTr
   else
     {
       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+      gtk_widget_error_bell (GTK_WIDGET (tree_view));
     }
 
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
@@ -9565,6 +9585,7 @@ gtk_tree_view_move_cursor_page_up_down (
 {
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
+  GtkTreePath *old_cursor_path = NULL;
   GtkTreePath *cursor_path = NULL;
   gint y;
   gint window_y;
@@ -9574,20 +9595,21 @@ gtk_tree_view_move_cursor_page_up_down (
     return;
 
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
-    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+    old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
   else
     /* This is sorta weird.  Focus in should give us a cursor */
     return;
 
   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
-  _gtk_tree_view_find_node (tree_view, cursor_path,
+  _gtk_tree_view_find_node (tree_view, old_cursor_path,
 			    &cursor_tree, &cursor_node);
 
-  gtk_tree_path_free (cursor_path);
-
   if (cursor_tree == NULL)
-    /* FIXME: we lost the cursor.  Should we try to get one? */
-    return;
+    {
+      /* FIXME: we lost the cursor.  Should we try to get one? */
+      gtk_tree_path_free (old_cursor_path);
+      return;
+    }
   g_return_if_fail (cursor_node != NULL);
 
   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
@@ -9602,10 +9624,15 @@ gtk_tree_view_move_cursor_page_up_down (
   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
   g_return_if_fail (cursor_path != NULL);
   gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
-  gtk_tree_path_free (cursor_path);
 
   y -= window_y;
   gtk_tree_view_scroll_to_point (tree_view, -1, y);
+
+  if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
+    gtk_widget_error_bell (GTK_WIDGET (tree_view));
+
+  gtk_tree_path_free (old_cursor_path);
+  gtk_tree_path_free (cursor_path);
 }
 
 static void
@@ -9698,6 +9725,11 @@ gtk_tree_view_move_cursor_left_right (Gt
 				        NULL);
       g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
     }
+  else
+    {
+      gtk_widget_error_bell (GTK_WIDGET (tree_view));
+    }
+
   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
 }
 
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.446
diff -u -p -r1.446 gtkwidget.c
--- gtk/gtkwidget.c	8 Oct 2006 05:07:45 -0000	1.446
+++ gtk/gtkwidget.c	12 Oct 2006 14:44:47 -0000
@@ -121,6 +121,7 @@ enum {
   CAN_ACTIVATE_ACCEL,
   GRAB_BROKEN,
   COMPOSITED_CHANGED,
+  KEYNAV_FAILED,
   LAST_SIGNAL
 };
 
@@ -204,6 +205,8 @@ static gboolean		gtk_widget_real_focus_o
 								 GdkEventFocus    *event);
 static gboolean		gtk_widget_real_focus			(GtkWidget        *widget,
 								 GtkDirectionType  direction);
+static gboolean		gtk_widget_real_keynav_failed		(GtkWidget        *widget,
+								 GtkDirectionType  direction);
 static PangoContext*	gtk_widget_peek_pango_context		(GtkWidget	  *widget);
 static void     	gtk_widget_update_pango_context		(GtkWidget	  *widget);
 static void		gtk_widget_propagate_state		(GtkWidget	  *widget,
@@ -403,6 +406,7 @@ gtk_widget_class_init (GtkWidgetClass *k
   klass->screen_changed = NULL;
   klass->can_activate_accel = gtk_widget_real_can_activate_accel;
   klass->grab_broken_event = NULL;
+  klass->keynav_failed = gtk_widget_real_keynav_failed;
 
   klass->show_help = gtk_widget_real_show_help;
   
@@ -806,6 +810,15 @@ gtk_widget_class_init (GtkWidgetClass *k
 		  NULL, NULL,
 		  _gtk_marshal_VOID__VOID,
 		  G_TYPE_NONE, 0);
+  widget_signals[KEYNAV_FAILED] =
+    g_signal_new (I_("keynav-failed"),
+		  G_TYPE_FROM_CLASS (object_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, keynav_failed),
+		  _gtk_boolean_handled_accumulator, NULL,
+		  _gtk_marshal_BOOLEAN__ENUM,
+		  G_TYPE_BOOLEAN, 1,
+		  GTK_TYPE_DIRECTION_TYPE);
 
 /**
  * GtkWidget::delete-event:
@@ -3642,7 +3655,7 @@ gtk_widget_real_mnemonic_activate (GtkWi
     {
       g_warning ("widget `%s' isn't suitable for mnemonic activation",
 		 G_OBJECT_TYPE_NAME (widget));
-      gdk_display_beep (gtk_widget_get_display (widget));
+      gtk_widget_error_bell (widget);
     }
   return TRUE;
 }
@@ -4326,6 +4339,34 @@ gtk_widget_real_focus (GtkWidget        
     return FALSE;
 }
 
+static gboolean
+gtk_widget_real_keynav_failed (GtkWidget        *widget,
+                               GtkDirectionType  direction)
+{
+  gboolean cursor_only;
+
+  switch (direction)
+    {
+    case GTK_DIR_TAB_FORWARD:
+    case GTK_DIR_TAB_BACKWARD:
+      return FALSE;
+
+    case GTK_DIR_UP:
+    case GTK_DIR_DOWN:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_RIGHT:
+      g_object_get (gtk_widget_get_settings (widget),
+                    "gtk-keynav-cursor-only", &cursor_only,
+                    NULL);
+      if (cursor_only)
+        return FALSE;
+    }
+
+  gtk_widget_error_bell (widget);
+
+  return TRUE;
+}
+
 /**
  * gtk_widget_is_focus:
  * @widget: a #GtkWidget
@@ -5897,6 +5938,35 @@ gtk_widget_child_focus (GtkWidget       
 		 direction, &return_val);
 
   return return_val;
+}
+
+gboolean
+gtk_widget_keynav_failed (GtkWidget        *widget,
+                          GtkDirectionType  direction)
+{
+  gboolean return_val;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  g_signal_emit (widget, widget_signals[KEYNAV_FAILED], 0,
+		 direction, &return_val);
+
+  return return_val;
+}
+
+void
+gtk_widget_error_bell (GtkWidget *widget)
+{
+  gboolean beep;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  g_object_get (gtk_widget_get_settings (widget),
+                "gtk-error-bell", &beep,
+                NULL);
+
+  if (beep && widget->window)
+    gdk_window_beep (widget->window);
 }
 
 /**
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.159
diff -u -p -r1.159 gtkwidget.h
--- gtk/gtkwidget.h	25 Apr 2006 14:27:31 -0000	1.159
+++ gtk/gtkwidget.h	12 Oct 2006 14:44:47 -0000
@@ -408,9 +408,11 @@ struct _GtkWidgetClass
                                  GdkEventGrabBroken  *event);
 
   void         (* composited_changed) (GtkWidget *widget);
-	
+
+  gboolean     (* keynav_failed)      (GtkWidget        *widget,
+                                       GtkDirectionType  direction);
+
   /* Padding for future expansion */
-  void (*_gtk_reserved4) (void);
   void (*_gtk_reserved5) (void);
   void (*_gtk_reserved6) (void);
   void (*_gtk_reserved7) (void);
@@ -563,6 +565,9 @@ GdkWindow *gtk_widget_get_parent_window	
 
 gboolean   gtk_widget_child_focus         (GtkWidget           *widget,
                                            GtkDirectionType     direction);
+gboolean   gtk_widget_keynav_failed       (GtkWidget           *widget,
+                                           GtkDirectionType     direction);
+void       gtk_widget_error_bell          (GtkWidget           *widget);
 
 void       gtk_widget_set_size_request    (GtkWidget           *widget,
                                            gint                 width,
