[gtk/wip/matthiasc/can-focus: 83/83] wip: Make can-focus recursive



commit 597176cbe9f9a6ec116fa6c04f693b82f6a81ede
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Apr 3 09:36:40 2020 -0400

    wip: Make can-focus recursive
    
    Make can-focus default to TRUE and prevent all focus
    in a widget subtree when set to FALSE. Adapt all
    widgets to have grab_focus and focus vfuncs that
    do the right thing, instead of relying on can-focus.

 demos/gtk-demo/fontplane.c  |  2 --
 gtk/gtkbuiltinicon.c        |  2 ++
 gtk/gtkbutton.c             |  4 ++-
 gtk/gtkcolorbutton.c        |  4 +++
 gtk/gtkcolorchooserwidget.c |  4 +++
 gtk/gtkcolorplane.c         |  2 --
 gtk/gtkcolorswatch.c        |  2 ++
 gtk/gtkcombobox.c           |  1 +
 gtk/gtkcontainer.c          |  2 ++
 gtk/gtkentry.c              |  1 +
 gtk/gtkexpander.c           |  2 --
 gtk/gtkfilechooserbutton.c  |  3 ++
 gtk/gtkfontbutton.c         |  4 +++
 gtk/gtkiconview.c           |  1 -
 gtk/gtkimage.c              |  2 ++
 gtk/gtklevelbar.c           |  2 ++
 gtk/gtkprogressbar.c        |  2 ++
 gtk/gtkscale.c              |  3 ++
 gtk/gtkspinbutton.c         |  1 +
 gtk/gtkswitch.c             |  3 ++
 gtk/gtkwidget.c             | 83 ++++++++++++++++++++++++++++++++-------------
 gtk/gtkwidgetprivate.h      | 12 +++++++
 gtk/inspector/css-editor.ui |  1 -
 23 files changed, 111 insertions(+), 32 deletions(-)
---
diff --git a/demos/gtk-demo/fontplane.c b/demos/gtk-demo/fontplane.c
index 1f7e074adb..0a7aae6339 100644
--- a/demos/gtk-demo/fontplane.c
+++ b/demos/gtk-demo/fontplane.c
@@ -189,8 +189,6 @@ gtk_font_plane_init (GtkFontPlane *plane)
 {
   GtkGesture *gesture;
 
-  gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
-
   gesture = gtk_gesture_drag_new ();
   g_signal_connect (gesture, "drag-begin",
                    G_CALLBACK (plane_drag_gesture_begin), plane);
diff --git a/gtk/gtkbuiltinicon.c b/gtk/gtkbuiltinicon.c
index b91864db44..53b0318239 100644
--- a/gtk/gtkbuiltinicon.c
+++ b/gtk/gtkbuiltinicon.c
@@ -95,6 +95,8 @@ gtk_builtin_icon_class_init (GtkBuiltinIconClass *klass)
   wclass->snapshot = gtk_builtin_icon_snapshot;
   wclass->measure = gtk_builtin_icon_measure;
   wclass->css_changed = gtk_builtin_icon_css_changed;
+  wclass->grab_focus = gtk_widget_grab_focus_none;
+  wclass->focus = gtk_widget_focus_none;
 }
 
 static void
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index d633c77fe6..7276d2c24d 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -68,6 +68,7 @@
 #include "gtkprivate.h"
 #include "gtkstylecontext.h"
 #include "gtktypebuiltins.h"
+#include "gtkwidgetprivate.h"
 
 #include "a11y/gtkbuttonaccessible.h"
 
@@ -204,6 +205,8 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class->state_flags_changed = gtk_button_state_flags_changed;
   widget_class->grab_notify = gtk_button_grab_notify;
   widget_class->unmap = gtk_button_unmap;
+  widget_class->grab_focus = gtk_widget_grab_focus_self;
+  widget_class->focus = gtk_widget_focus_self;
 
   container_class->add    = gtk_button_add;
   container_class->remove = gtk_button_remove;
@@ -408,7 +411,6 @@ gtk_button_init (GtkButton *button)
   GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
   GtkEventController *key_controller;
 
-  gtk_widget_set_can_focus (GTK_WIDGET (button), TRUE);
   gtk_widget_set_receives_default (GTK_WIDGET (button), TRUE);
 
   priv->in_button = FALSE;
diff --git a/gtk/gtkcolorbutton.c b/gtk/gtkcolorbutton.c
index 1638cdc6ee..9b6a7015b7 100644
--- a/gtk/gtkcolorbutton.c
+++ b/gtk/gtkcolorbutton.c
@@ -44,6 +44,7 @@
 #include "gtkprivate.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontext.h"
+#include "gtkwidgetprivate.h"
 
 
 /**
@@ -143,6 +144,9 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
   gobject_class->set_property = gtk_color_button_set_property;
   gobject_class->finalize = gtk_color_button_finalize;
 
+  widget_class->grab_focus = gtk_widget_grab_focus_child;
+  widget_class->focus = gtk_widget_focus_child;
+
   klass->color_set = NULL;
 
   /**
diff --git a/gtk/gtkcolorchooserwidget.c b/gtk/gtkcolorchooserwidget.c
index 0455d07457..ca25709695 100644
--- a/gtk/gtkcolorchooserwidget.c
+++ b/gtk/gtkcolorchooserwidget.c
@@ -30,6 +30,7 @@
 #include "gtksizegroup.h"
 #include "gtkstylecontext.h"
 #include "gtkboxlayout.h"
+#include "gtkwidgetprivate.h"
 
 #include "a11y/gtkcompositeaccessible.h"
 
@@ -709,6 +710,9 @@ gtk_color_chooser_widget_class_init (GtkColorChooserWidgetClass *class)
   object_class->set_property = gtk_color_chooser_widget_set_property;
   object_class->finalize = gtk_color_chooser_widget_finalize;
 
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
+  widget_class->focus = gtk_widget_focus_child;
+
   g_object_class_override_property (object_class, PROP_RGBA, "rgba");
   g_object_class_override_property (object_class, PROP_USE_ALPHA, "use-alpha");
 
diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c
index a11b0752e2..2582cca2ea 100644
--- a/gtk/gtkcolorplane.c
+++ b/gtk/gtkcolorplane.c
@@ -407,8 +407,6 @@ gtk_color_plane_init (GtkColorPlane *plane)
 
   plane->priv = gtk_color_plane_get_instance_private (plane);
 
-  gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
-
   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (plane));
   if (GTK_IS_ACCESSIBLE (atk_obj))
     {
diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c
index f68003cc69..72d66192cc 100644
--- a/gtk/gtkcolorswatch.c
+++ b/gtk/gtkcolorswatch.c
@@ -481,6 +481,8 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
   widget_class->snapshot = swatch_snapshot;
   widget_class->size_allocate = swatch_size_allocate;
   widget_class->state_flags_changed = swatch_state_flags_changed;
+  widget_class->grab_focus = gtk_widget_grab_focus_self;
+  widget_class->focus = gtk_widget_focus_self;
 
   g_object_class_install_property (object_class, PROP_RGBA,
       g_param_spec_boxed ("rgba", P_("RGBA Color"), P_("Color as RGBA"),
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index c1e97debb0..0db20726df 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -420,6 +420,7 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
   widget_class->size_allocate = gtk_combo_box_size_allocate;
   widget_class->mnemonic_activate = gtk_combo_box_mnemonic_activate;
   widget_class->grab_focus = gtk_combo_box_grab_focus;
+  widget_class->focus = gtk_widget_focus_child;
   widget_class->measure = gtk_combo_box_measure;
   widget_class->unmap = gtk_combo_box_unmap;
   widget_class->destroy = gtk_combo_box_destroy;
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 7d74e4f069..1b8953cbbc 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -140,6 +140,8 @@ gtk_container_class_init (GtkContainerClass *class)
   widget_class->destroy = gtk_container_destroy;
   widget_class->compute_expand = gtk_container_compute_expand;
   widget_class->get_request_mode = gtk_container_get_request_mode;
+  widget_class->grab_focus = gtk_widget_grab_focus_child;
+  widget_class->focus = gtk_widget_focus_child;
 
   class->add = gtk_container_add_unimplemented;
   class->remove = gtk_container_remove_unimplemented;
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 13fd885acf..b7c987dc33 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -340,6 +340,7 @@ gtk_entry_class_init (GtkEntryClass *class)
   widget_class->query_tooltip = gtk_entry_query_tooltip;
   widget_class->direction_changed = gtk_entry_direction_changed;
   widget_class->grab_focus = gtk_entry_grab_focus;
+  widget_class->focus = gtk_widget_focus_child;
   widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
   
   quark_entry_completion = g_quark_from_static_string ("gtk-entry-completion-key");
diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c
index dbe31e68e0..91f73aa654 100644
--- a/gtk/gtkexpander.c
+++ b/gtk/gtkexpander.c
@@ -385,8 +385,6 @@ gtk_expander_init (GtkExpander *expander)
   GtkGesture *gesture;
   GtkEventController *controller;
 
-  gtk_widget_set_can_focus (GTK_WIDGET (expander), TRUE);
-
   priv->label_widget = NULL;
   priv->child = NULL;
 
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index ce15326723..e0064fc9f3 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -61,6 +61,7 @@
 #include "gtkstylecontextprivate.h"
 #include "gtkbitmaskprivate.h"
 #include "gtkeventcontroller.h"
+#include "gtkwidgetprivate.h"
 
 /**
  * SECTION:gtkfilechooserbutton
@@ -476,6 +477,8 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
   widget_class->root = gtk_file_chooser_button_root;
   widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
   widget_class->state_flags_changed = gtk_file_chooser_button_state_flags_changed;
+  widget_class->grab_focus = gtk_widget_grab_focus_child;
+  widget_class->focus = gtk_widget_focus_child;
 
   /**
    * GtkFileChooserButton::file-set:
diff --git a/gtk/gtkfontbutton.c b/gtk/gtkfontbutton.c
index 1e5cf9889e..1cad2f6c59 100644
--- a/gtk/gtkfontbutton.c
+++ b/gtk/gtkfontbutton.c
@@ -41,6 +41,7 @@
 #include "gtkprivate.h"
 #include "gtkseparator.h"
 #include "gtkstylecontext.h"
+#include "gtkwidgetprivate.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -483,6 +484,9 @@ gtk_font_button_class_init (GtkFontButtonClass *klass)
   gobject_class->set_property = gtk_font_button_set_property;
   gobject_class->get_property = gtk_font_button_get_property;
 
+  widget_class->grab_focus = gtk_widget_grab_focus_child;
+  widget_class->focus = gtk_widget_focus_child;
+
   klass->font_set = NULL;
 
   _gtk_font_chooser_install_properties (gobject_class);
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index f3bb6ead98..0aa89870c2 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -943,7 +943,6 @@ gtk_icon_view_init (GtkIconView *icon_view)
   icon_view->priv->mouse_x = -1;
   icon_view->priv->mouse_y = -1;
 
-  gtk_widget_set_can_focus (GTK_WIDGET (icon_view), TRUE);
   gtk_widget_set_overflow (GTK_WIDGET (icon_view), GTK_OVERFLOW_HIDDEN);
 
   icon_view->priv->item_orientation = GTK_ORIENTATION_VERTICAL;
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
index da98ccc698..c4ee1642cb 100644
--- a/gtk/gtkimage.c
+++ b/gtk/gtkimage.c
@@ -157,6 +157,8 @@ gtk_image_class_init (GtkImageClass *class)
   widget_class->measure = gtk_image_measure;
   widget_class->unrealize = gtk_image_unrealize;
   widget_class->css_changed = gtk_image_css_changed;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
+  widget_class->focus = gtk_widget_focus_none;
 
   image_props[PROP_PAINTABLE] =
       g_param_spec_object ("paintable",
diff --git a/gtk/gtklevelbar.c b/gtk/gtklevelbar.c
index c34fcc5364..fd2e68ab4d 100644
--- a/gtk/gtklevelbar.c
+++ b/gtk/gtklevelbar.c
@@ -901,6 +901,8 @@ gtk_level_bar_class_init (GtkLevelBarClass *klass)
   oclass->finalize = gtk_level_bar_finalize;
 
   wclass->direction_changed = gtk_level_bar_direction_changed;
+  wclass->grab_focus = gtk_widget_grab_focus_none;
+  wclass->focus = gtk_widget_focus_none;
 
   g_object_class_override_property (oclass, PROP_ORIENTATION, "orientation");
 
diff --git a/gtk/gtkprogressbar.c b/gtk/gtkprogressbar.c
index 42d53dd74b..4a446192bc 100644
--- a/gtk/gtkprogressbar.c
+++ b/gtk/gtkprogressbar.c
@@ -181,6 +181,8 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class)
   gobject_class->finalize = gtk_progress_bar_finalize;
 
   widget_class->direction_changed = gtk_progress_bar_direction_changed;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
+  widget_class->focus = gtk_widget_focus_none;
 
   g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
 
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index 9583c3ea9c..3195d94511 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -41,6 +41,7 @@
 #include "gtkstylecontextprivate.h"
 #include "gtkstylepropertyprivate.h"
 #include "gtktypebuiltins.h"
+#include "gtkwidgetprivate.h"
 
 #include "a11y/gtkscaleaccessible.h"
 
@@ -663,6 +664,8 @@ gtk_scale_class_init (GtkScaleClass *class)
   widget_class->snapshot = gtk_scale_snapshot;
   widget_class->size_allocate = gtk_scale_size_allocate;
   widget_class->measure = gtk_scale_measure;
+  widget_class->grab_focus = gtk_widget_grab_focus_self;
+  widget_class->focus = gtk_widget_focus_self;
 
   range_class->get_range_border = gtk_scale_get_range_border;
   range_class->value_changed = gtk_scale_value_changed;
diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c
index 6d610e7ef3..c59ef30ab8 100644
--- a/gtk/gtkspinbutton.c
+++ b/gtk/gtkspinbutton.c
@@ -349,6 +349,7 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
   widget_class->grab_notify = gtk_spin_button_grab_notify;
   widget_class->state_flags_changed = gtk_spin_button_state_flags_changed;
   widget_class->grab_focus = gtk_spin_button_grab_focus;
+  widget_class->focus = gtk_widget_focus_child;
   widget_class->mnemonic_activate = gtk_spin_button_mnemonic_activate;
 
   class->input = NULL;
diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c
index 148a94a418..781054b265 100644
--- a/gtk/gtkswitch.c
+++ b/gtk/gtkswitch.c
@@ -548,6 +548,9 @@ gtk_switch_class_init (GtkSwitchClass *klass)
 
   g_object_class_install_properties (gobject_class, LAST_PROP, switch_props);
 
+  widget_class->grab_focus = gtk_widget_grab_focus_self;
+  widget_class->focus = gtk_widget_focus_self;
+
   klass->activate = gtk_switch_activate;
   klass->state_set = state_set;
 
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 26853d9cbb..0d2f372110 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -981,7 +981,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
       g_param_spec_boolean ("can-focus",
                             P_("Can focus"),
                             P_("Whether the widget can accept the input focus"),
-                            FALSE,
+                            TRUE,
                             GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
 
   widget_props[PROP_HAS_FOCUS] =
@@ -2297,6 +2297,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
 #ifdef G_ENABLE_DEBUG
   priv->highlight_resize = FALSE;
 #endif
+  priv->can_focus = TRUE;
   priv->can_target = TRUE;
 
   switch (_gtk_widget_get_direction (widget))
@@ -4740,25 +4741,34 @@ gtk_widget_grab_focus (GtkWidget *widget)
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
   if (!gtk_widget_is_sensitive (widget) ||
+      !gtk_widget_get_can_focus (widget) ||
       widget->priv->root == NULL)
     return FALSE;
 
   return GTK_WIDGET_GET_CLASS (widget)->grab_focus (widget);
 }
 
-static gboolean
-gtk_widget_real_grab_focus (GtkWidget *focus_widget)
+gboolean
+gtk_widget_grab_focus_none (GtkWidget *widget)
 {
-  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget);
-  GtkWidget *child;
+  return FALSE;
+}
 
-  if (priv->can_focus)
-    {
-      gtk_root_set_focus (priv->root, focus_widget);
-      return TRUE;
-    }
+gboolean
+gtk_widget_grab_focus_self (GtkWidget *widget)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
 
-  for (child = _gtk_widget_get_first_child (focus_widget);
+  gtk_root_set_focus (priv->root, widget);
+  return TRUE;
+}
+
+gboolean
+gtk_widget_grab_focus_child (GtkWidget *widget)
+{
+  GtkWidget *child;
+
+  for (child = _gtk_widget_get_first_child (widget);
        child != NULL;
        child = _gtk_widget_get_next_sibling (child))
     {
@@ -4769,6 +4779,15 @@ gtk_widget_real_grab_focus (GtkWidget *focus_widget)
   return FALSE;
 }
 
+static gboolean
+gtk_widget_real_grab_focus (GtkWidget *focus_widget)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget);
+
+  gtk_root_set_focus (priv->root, focus_widget);
+  return TRUE;
+}
+
 static gboolean
 gtk_widget_real_query_tooltip (GtkWidget  *widget,
                               gint        x,
@@ -4878,20 +4897,11 @@ direction_is_forward (GtkDirectionType direction)
 }
 
 static gboolean
-gtk_widget_real_focus (GtkWidget         *widget,
-                       GtkDirectionType   direction)
+gtk_widget_real_focus (GtkWidget        *widget,
+                       GtkDirectionType  direction)
 {
   GtkWidget *focus;
 
-  /* The easy case: not focusable. Just try the children */
-  if (!gtk_widget_get_can_focus (widget))
-    {
-      if (gtk_widget_focus_move (widget, direction))
-        return TRUE;
-
-      return FALSE;
-    }
-
   /* For focusable widgets, we want to focus the widget
    * before its children. We differentiate 3 cases:
    * 1) focus is currently on widget
@@ -4934,6 +4944,32 @@ gtk_widget_real_focus (GtkWidget         *widget,
   return TRUE;
 }
 
+gboolean
+gtk_widget_focus_self (GtkWidget         *widget,
+                       GtkDirectionType   direction)
+{
+  if (!gtk_widget_is_focus (widget))
+    {
+      gtk_widget_grab_focus (widget);
+      return TRUE;
+    }
+  return FALSE;
+}
+
+gboolean
+gtk_widget_focus_child (GtkWidget         *widget,
+                        GtkDirectionType   direction)
+{
+  return gtk_widget_focus_move (widget, direction);
+}
+
+gboolean
+gtk_widget_focus_none (GtkWidget        *widget,
+                       GtkDirectionType  direction)
+{
+  return FALSE;
+}
+
 static void
 gtk_widget_real_move_focus (GtkWidget         *widget,
                             GtkDirectionType   direction)
@@ -6658,7 +6694,8 @@ gtk_widget_child_focus (GtkWidget       *widget,
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
   if (!_gtk_widget_get_visible (widget) ||
-      !gtk_widget_is_sensitive (widget))
+      !gtk_widget_is_sensitive (widget) ||
+      !gtk_widget_get_can_focus (widget))
     return FALSE;
 
   /* Emit ::focus in any case, even if can-focus is FALSE,
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 53467aeae1..6ff2be1d74 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -360,6 +360,18 @@ guint             gtk_widget_add_surface_transform_changed_callback (GtkWidget
 void              gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget,
                                                                         guint      id);
 
+/* focus vfuncs for non-focusable non-containers */
+gboolean gtk_widget_grab_focus_none  (GtkWidget        *widget);
+gboolean gtk_widget_focus_none       (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
+/* focus vfuncs for non-focusable containers with focusable children */
+gboolean gtk_widget_grab_focus_child (GtkWidget        *widget);
+gboolean gtk_widget_focus_child      (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
+/* focus vfuncs for focusable widgets with children */
+gboolean gtk_widget_grab_focus_self  (GtkWidget        *widget);
+gboolean gtk_widget_focus_self       (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
 
 /* inline getters */
 
diff --git a/gtk/inspector/css-editor.ui b/gtk/inspector/css-editor.ui
index 15984bc28d..50b9bee503 100644
--- a/gtk/inspector/css-editor.ui
+++ b/gtk/inspector/css-editor.ui
@@ -55,7 +55,6 @@
             <property name="buffer">text</property>
             <property name="wrap-mode">word</property>
             <property name="monospace">1</property>
-            <property name="has-focus">1</property>
             <property name="left-margin">6</property>
             <property name="right-margin">6</property>
             <property name="has-tooltip">1</property>


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