Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4476300

Various dangerous and inconsistent focus-related APIs should be deprecated

    Details

    • Subcomponent:
    • Resolved In Build:
      beta2
    • CPU:
      generic
    • OS:
      generic
    • Verification:
      Verified

      Description

         * <code>DefaultFocusTraversalPolicy</code>.
           *
           * @see java.awt.DefaultFocusTraversalPolicy
           * @see java.awt.KeyboardFocusManager#setDefaultFocusTraversalPolicy
           * @deprecated as of 1.4, replaced by <code>KeyboardFocusManager.setDefaultFocusTraversalPolicy(FocusTraversalPolicy)</code>.
           */
          public static void disableSwingFocusManager();

          /**
           * Returns whether the application has invoked
           * <code>disableSwingFocusManager()</code>.
           *
           * @see #disableSwingFocusManager
           * @deprecated As of 1.4, replaced by
           * <code>KeyboardFocusManager.getDefaultFocusTraversalPolicy()</code>.
           */
          public static boolean isFocusManagerEnabled();

          /**
           * Requests focus on this <code>JComponent</code>'s
           * <code>FocusTraversalPolicy</code>'s default <code>Component</code>. If
           * this <code>JComponent</code> is a focus cycle root, then its
           * <code>FocusTraversalPolicy</code> is used. Otherwise, the
           * <code>FocusTraversalPolicy</code> of this <code>JComponent</code>'s
           * focus-cycle-root ancestor is used.
           *
           * @see java.awt.FocusTraversalPolicy#getDefaultComponent
           * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy.getDefaultComponent(Container).requestFocus()</code>.
           */
          public boolean requestDefaultFocus();

          /**
           * Changes this <code>JComponent</code>'s focus traversal keys to CTRL+TAB
           * and CTRL+SHIFT+TAB. Also prevents
           * <code>SortingFocusTraversalPolicy</code> from considering descendants of
           * this JComponent when computing a focus traversal cycle.
           *
           * @see java.awt.Component#setFocusTraversalKeys
           * @see SortingFocusTraversalPolicy
           * @deprecated As of 1.4, replaced by
           * <code>Component.setFocusTraversalKeys(int, Set)</code> and
           * <code>Container.setFocusCycleRoot(boolean)</code>.
           */
          public boolean isManagingFocus();

          /**
           * Overrides the default <code>FocusTraversalPolicy</code> for this
           * <code>JComponent</code>'s focus traversal cycle by unconditionally
           * setting the specified <code>Component</code> as the next
           * <code>Component</code> in the cycle, and this <code>JComponent</code> as
           * the specified <code>Component</code>'s previous <code>Component</code>
           * in the cycle.
           *
           * @param aComponent the <code>Component</code> that should follow this
           * <code>JComponent</code> in the focus traversal cycle
           *
           * @see #getNextFocusableComponent
           * @see java.awt.FocusTraversalPolicy
           * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
           */
          public void setNextFocusableComponent(Component aComponent);

          /**
           * Returns the <code>Component</code> set by a prior call to
           * <code>setNextFocusableComponent(Component)</code> on this
           * <code>JComponent</code>.
           *
           * @return the <code>Component</code> that will follow this
           * <code>JComponent</code> in the focus traversal cycle, or
           * <code>null</code> if none has been explicitly specified
           *
           * @see #setNextFocusableComponent
           * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
           */
          public Component getNextFocusableComponent();

          /**
           * Returns whether this <code>Component</code> can become the focus owner.
           *
           * @return <code>true</code> if this <code>Component</code> is focusable;
           * <code>false</code> otherwise
           * @see #setFocusable
           * @since JDK1.1
           * @deprecated As of 1.4, replaced by <code>isFocusable()</code>.
           */
          public boolean isFocusTraversable();

          /**
           * Returns <code>true</code> if this <code>Component</code> is the focus
           * owner.
           *
           * @return <code>true</code> if this <code>Component</code> is the focus
                     owner
           * @since 1.2
           * @deprecated As of 1.4, replaced by <code>isFocusOwner()</code>.
           */
          public boolean hasFocus();

          /**
           * Return the child <code>Component</code> of the specified
           * <code>Component</code> that is the focus owner, if any.
           *
           * @param comp the root of the <code>Component</code> hierarchy to search
           * for the focus owner
           * @return the focus owner, or <code>null</code> if there is no focus
           * owner, or if the focus owner is not <code>comp</code>, or a
           * descendant of <code>comp</code>
           *
           * @see java.awt.KeyboardFocusManager#getFocusOwner
           * @deprecated As of 1.4, replaced by
           * <code>KeyboardFocusManager.getFocusOwner()</code>.
           */
          public static Component findFocusOwner(Component comp);


      API reviewed and approved by:

      awt-core@eng swing-eng@eng


      Implementation:
         - Engineer who made (or will make) the changes: David Mendenhall
         - Date at which changes will be complete: Immediately
         - Number of lines of new or modified code:
              + Java: None
              + Native: None
         - Code reviewed (or will be reviewed) by: N/A


      Risk assessment:

      Despite the deprecation, we will continue to support all of the APIs
      except for FOCUS_MANAGER_CLASS_PROPERTY. They have already been
      reimplemented in terms of the new focus architecture. Otherwise, there
      is only the standard deprecation risk of annoying our customers.


      SQE (product testing) impact:

      TBD


      JCK (compatibility testing) impact:

      TBD


      Doc impact:

      javadoc changes only.


      Localization impact:

      None.


      Internationalization impact:

      None.


      Security impact:

      None.


      Legal impact:

      None.


      For feature changes, Product Marketing approval:

      N/A
      Release: merlin-beta-refresh

      Problem: (BugID 4476300)
        Various dangerous and inconsistent focus-related APIs should be deprecated

      The Merlin Focus Enhancements project (RFE 4290675) introduced a new,
      public architecture and a new terminology for handling keyboard focus
      in sophisticated AWT and Swing applications. Prior to this project,
      many of the focus-related APIs were inconsistent in usage and
      terminology, were improperly documented, and led to poorly designed
      UIs. Now that a viable alternative is available, we propose to
      deprecate the most egregious of these APIs, discouraging developers
      from ever using them again.

      We recognize that deprecation has become the proverbial nuclear weapon
      of the Java class libraries, and thus have curbed our desire to
      deprecate anything that is only marginally obscene. We feel that the
      nine methods and one field listed in this proposal have strong cases
      for deprecation, and we make that case for each one. Even so, we
      understand that the CCC may agree with some of our arguments, but not
      others. Therefore, we ask that the CCC consider and approve each of
      the proposed changes separately. (We refrained from submitting
      separate requests in the interests of paperwork reduction.)


      1. javax.swing.FocusManager.FOCUS_MANAGER_CLASS_PROPERTY

      This field allowed an application to specify the class name of a
      subclass of javax.swing.FocusManager that should be instantiated as
      the default FocusManager. To do this, the application would call
      UIManager.getDefaults().put(FocusManager.FOCUS_MANAGER_CLASS_PROPERTY,
      "<class name>"). Because this was a String based API, there was
      obviously no compile-time type checking of <class name>, and any
      instantiation problems would be reported only at runtime. All known,
      real-world applications avoided this approach, and instead simply
      called FocusManager.setCurrentManager(FocusManager). This approach was
      completely type-safe and was essentially equivalent in behavior.

      With the adoption of the Merlin Focus Enhancements project, the
      current FocusManager can no longer be considered a property of the UI;
      its role has been substantially expanded, and it is now clearly
      designed to be a property of the application. In fact, in terms of
      implementation, the FocusManager was *always* a property of the
      application. The old design merely made it look as though it were
      associated with the PLAF. Continuing to allow developers to refer to
      the current FocusManager via the UI maligns the basic focus
      architecture, and blurs the line between Swing and the underlying
      AWT. Given that no known developers are even using this field, and
      that there is a simple replacement API, this field should be
      deprecated so that future developers can more rapidly focus on the
      salient points of the architecture.


      2. javax.swing.FocusManager.disableSwingFocusManager() and
         javax.swing.FocusManager.isFocusManagerEnabled()

      These two methods should be considered together, as we do not
      recommend deprecating one, but not the other.

      Prior to the Merlin Focus Enhancements, any Swing application
      effectively had two focus managers. One was an instance of
      javax.swing.FocusManager, and the other was woven into the
      implementation of the AWT. Applications that mixed heavyweight AWT
      Components, or non-Swing lightweight Components, with JComponents
      experienced bizarre focus behavior unless they called
      disableSwingFocusManager(). This prevented the two focus managers from
      fighting against each other, and allowed AWT to manage all keyboard
      traversal alone. Unfortunately, this also rendered useless all of the
      Swing APIs related to keyboard traversal.

      In merlin, there is only one focus manager: an instance of
      java.awt.KeyboardFocusManager. Swing and AWT are designed to work in
      concert, so there will never be a need to disable the "Swing" focus
      manager. Indeed, such a concept doesn't even make sense. As with (1),
      continuing to allow developers to make a distinction between a Swing
      focus manager and an AWT focus manager maligns the basic
      architecture. In addition, we cannot exactly replicate the behavior of
      disableSwingFocusManager() under the new architecture. The current
      implementation changes the default FocusTraversalPolicy from Swing's
      LayoutFocusTraversalPolicy to AWT's DefaultFocusTraversalPolicy, which
      is pretty close. However, the Swing APIs related to keyboard traversal
      are no longer disabled, and there are other, subtle and unavoidable
      differences.


      3. javax.swing.JComponent.requestDefaultFocus()

      This method was intended to provide a quick and convenient mechanism
      for setting focus to the default Component of a container. For
      example, this method could be used to move focus to the "OK" button of
      a JDialog. However, the default implementation merely moved focus to
      the first focus traversable Component.

      This was a poor implementation for two significant reasons. First, the
      Component chosen by the default implementation was often the wrong
      Component for a given application. Therefore, applications had to
      customize this "default" Component. But since there was no
      'setDefaultComponent' method, developers had to subclass the container
      and override 'requestDefaultFocus()'. Even worse, because
      'requestDefaultFocus()' is invoked recursively by default, it was
      sometimes necessary to subclass every Component in the
      hierarchy. Second, this implementation relies upon the
      'isFocusTraversable()' method, which we propose to deprecate in (6).

      There is an additional, subtle reason why this method is badly
      designed. Swing (and, starting in 1.4, AWT) allows a developer to
      divide the Component hierarchy into a hierarchy of focus traversal
      cycles, each of which has a default Component. The 1.3.1
      implementation of 'requestDefaultFocus()' ignored this feature, but
      the 1.4 implementation attempts to handle it. The problem is that
      containers which are the roots of inferior focus traversal cycles
      actually belong to two cycles: the one that they root, and the one of
      their focus-cycle-root ancestor. There is no way to indicate when
      calling this method on such a container which default Component (that
      is, which focus traversal cycle's default Component) should be
      focused. In writing the new implementation, we had to choose
      arbitrarily, and developers will have to refer to the javadoc in order
      to recall which one will be used.

      For all of these reasons, and because there is a fairly simple
      replacement, we propose to discourage developers from ever using this
      method again.


      4. javax.swing.JComponent.isManagingFocus()

      The name for this method implies that it distinguishes whether the
      Swing FocusManager (see (2)) interacts with the JComponent or not.
      The 1.3.1 javadoc for this method reads differently, however:

          /**
           * Override this method and return true if your JComponent manages focus.
           * If your component manages focus, the focus manager will handle your
           * component's children. All key event will be sent to your key listener
           * including TAB and SHIFT+TAB. CONTROL+TAB and CONTROL+SHIFT+TAB
           * will move the focus to the next or previous component.
           */

      The javadoc is, in fact, an oxymoron. CONTROL+TAB and
      CONTROL+SHIFT+TAB are certainly KeyEvents, yet they will not be sent
      to any KeyListeners, ever, even if this method returns 'true'.

      In addition, as the name implies, this method does affect the behavior
      of the JComponent when interacting with the FocusManager. If a Swing
      application uses DefaultFocusManager (as most do), isManagingFocus()
      affects the behavior of DefaultFocusManager.getNextComponent (but not
      getPreviousComponent). The behavior of JTextAreas and JEditorPanes is
      also subtly modified. None of these additional behaviors is
      documented. And as a final insult, there is no
      'setManagingFocus(boolean)' method. Developers must subclass
      JComponent and override the method to return 'true'.

      This method is, quite simply, a complete disaster. In the new
      architecture, there are much better, documented mechanisms for
      effecting all of these behaviors. More importantly, these mechanisms
      are separated, so it is not necessary to use all of them or
      none. There is no reason to encourage developers to continue to use
      this method, and doing so would only perpetuate reliance on
      undocumented, nonsensical behavior.


      5. javax.swing.JComponent.setNextFocusableComponent(Component) and
         javax.swing.JComponent.getNextFocusableComponent()

      These two methods should be considered together, as we do not
      recommend deprecating one, but not the other.

      Prior to merlin, there existed two primary mechanisms for customizing
      keyboard traversal in a Swing application. One option was to replace
      DefaultFocusManager. This was a heavyweight approach, but allowed the
      developer to express the keyboard traversal behavior of the
      application algorithmically. The more common approach was to leave
      DefaultFocusManager alone, and instead use the methods above.

      These methods required developers to hard code the traversal policy,
      JComponent by JComponent. If a developer later added a JComponent to
      the GUI, he would have to return to this code, and manually insert the
      new JComponent into the traversal cycle. Developers often forgot to do
      this, thus creating an incomplete cycle. During testing, few
      developers verify that all Component are reachable via keyboard
      traversal; instead, they typically use the mouse to focus a Component.
      As discussed in (6), this is fine for sighted users, but prevents
      blind users from using the application in a comparable, accessible
      way.

      Another subtle problem with these methods is that there is no
      'setPreviousFocusableComponent(Component)' method. Instead,
      setNextFocusableComponent establishes mappings in both directions.
      Consider the following case:

        a.setNextFocusableComponent(c);
        b.setNextFocusableComponent(c);

      Following execution of these methods, forward traversal from 'b' will
      reach 'c', and backward traversal from 'c' will reach 'b'. However,
      forward traversal from 'a' will also reach 'c'. Forward and backward
      traversal among 'a', 'b', and 'c' is thus asymmetric. Starting from
      'a', the user would expect that a forward traversal followed by a
      backward traversal would return focus to 'a'. However, it moves focus
      to 'b'.

      We must strongly discourage developers from using these methods, as
      they often lead to inadvertently inaccessible applications, and
      asymmetric focus traversal cycles. The new FocusTraversalPolicy class
      allows developers to express traversal algorithmically, but is more
      lightweight than the DefaultFocusManager approach.


      6. java.awt.Component.isFocusTraversable()

      Prior to merlin, Swing and the AWT made a distinction between a
      Component's ability to become the focus owner ("focusability") and its
      participation in keyboard focus traversal ("focus
      traversability"). This distinction led to GUIs that were not
      accessible. Sighted users could set focus to a Component by clicking
      on it with the mouse. Blind users who relied on screen readers,
      however, could never reach the Component via keyboard traversal, and
      thus could not use the application in a comparable way. The Merlin
      Focus Enhancements eliminated this distinction, and unified both
      concepts under a single 'java.awt.Component.isFocusable()' method.
      'isFocusTraversable()' should be deprecated to discourage developers
      from unknowingly creating inaccessible applications.


      7. java.awt.Component.hasFocus()

      This method has been replaced by 'java.awt.Component.isFocusOwner()'.
      The new name is vastly preferable because it distinguishes between the
      concept of the "focus owner" and the "focused Window". If we fail to
      migrate developers to the new name, we are passively encouraging them
      to write code that is non-obvious. Sustaining engineers will need to
      refer to the documentation to understand what a call to 'hasFocus()'
      means. In contrast, the name 'isFocusOwner()' is unambiguous to any
      developer familiar with the standardized terminology of the Merlin
      Focus Enhancements project.


      8. javax.swing.SwingUtilities.findFocusOwner(Component)

      One of the cornerstone RFEs implemented in the Merlin Focus
      Enhancements project was a single API for querying the current focus
      owner. Implementing this RFE was not a matter of simply adding a
      method to return a state variable. This information was simply not
      tracked by the AWT prior to merlin, and substantial architectural
      work was required in order to start tracking it.

      Without such a method, developers often resorted to writing utility
      methods that searched the Component hierarchy for a Component whose
      hasFocus() method (see (7)) returned 'true'. 'findFocusOwner()' is one
      such method.

      While it is trivial to reimplement 'findFocusOwner()' to invoke the
      new method, 'findFocusOwner()' attempted to optimize the search by
      taking a Component as the root of the hierarchy to search. If the
      focus owner was not a descendant of the specified Component, even if
      there existed a focus owner elsewhere in the application, 'null' was
      returned.

      What was an optimization prior to merlin is now a hindrance. After
      performing a constant time operation to determine the current focus
      owner, the new implementation of 'findFocusOwner()' must perform a
      non-constant time search of the Component hierarchy to verify that the
      focus owner is a descendant of the specified Component. No application
      should incur this penalty. Consequently, this method should be
      deprecated so that developers immediately switch to the new, constant
      time method.


      Requesters:

      AWT Core (David Mendenhall and Hania Gajewska)


      Proposed API change:

      Deprecate the following:
        javax.swing.FocusManager.FOCUS_MANAGER_CLASS_PROPERTY
        javax.swing.FocusManager.disableSwingFocusManager()
        javax.swing.FocusManager.isFocusManagerEnabled()
        javax.swing.JComponent.requestDefaultFocus()
        javax.swing.JComponent.isManagingFocus()
        javax.swing.JComponent.setNextFocusableComponent(Component)
        javax.swing.JComponent.getNextFocusableComponent()
        java.awt.Component.isFocusTraversable()
        java.awt.Component.hasFocus()
        javax.swing.SwingUtilities.findFocusOwner(Component)

      The javadoc for these APIs will be rewritten as follows:

          /**
           * This field has been deprecated because its specification is incompatible
           * with the 1.4 focus APIs. Use of this field is no longer supported. See
           * the Focus Specification for more information.
           *
           * @see java.awt.KeyboardFocusManager#getCurrentKeyboardFocusManager
           * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
           * @deprecated As of 1.4, with no replacement. The current FocusManager is
           * no longer a property of the UI. Client code must query for the
           * current FocusManager using
           * <code>KeyboardFocusManager.getCurrentKeyboardFocusManager()</code>.
           */
          public static final String FOCUS_MANAGER_CLASS_PROPERTY;

          /**
           * Changes the current <code>KeyboardFocusManager</code>'s default
           * <code>FocusTraversalPolicy</code> to
        

        Attachments

          Activity

            People

            • Assignee:
              dmendenhsunw David Mendenhall (Inactive)
              Reporter:
              dmendenhsunw David Mendenhall (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Imported:
                Indexed: